Mercurial > pidgin
annotate src/gtkhtml.c @ 780:c714def9cebb
[gaim-migrate @ 790]
You may be a geek if...
You've ever used a computer on Friday, Saturday and Sunday of the
same weekend.
You find yourself interrupting computer store salesman to correct
something he said.
The first thing you notice when walking in a business is their
computer system. ...and offer advice on how you would change it.
You've ever mounted a magnetic tape reel.
You own any shareware.
You know more IP addresses than phone numbers.
You've ever accidentally dialed an IP address.
Your friends use you as tech support.
You've ever named a computer.
You have your local computer store on speed dial.
You can't carry on a conversation without talking about computers.
Co-workers have to E-mail you about the fire alarm to get you out of
the building.
You've ever found "stray" diskettes when doing laundry.
Your computer has it's own phone line - but your teenager doesn't.
You check the national weather service web page for current weather
conditions (rather than look out the window).
You know more URLs than street addresses.
Your pet has a web page.
You get really excited when Yahoo adds your link.
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Tue, 29 Aug 2000 03:59:01 +0000 |
| parents | 01d3c96867e2 |
| children | 678bdc430df7 |
| rev | line source |
|---|---|
| 12 | 1 |
| 1 | 2 /* |
| 3 * gaim | |
| 4 * | |
| 5 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
| 6 * | |
| 7 * This program is free software; you can redistribute it and/or modify | |
| 8 * it under the terms of the GNU General Public License as published by | |
| 9 * the Free Software Foundation; either version 2 of the License, or | |
| 10 * (at your option) any later version. | |
| 11 * | |
| 12 * This program is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 * GNU General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU General Public License | |
| 18 * along with this program; if not, write to the Free Software | |
| 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 * | |
| 21 */ | |
| 22 | |
|
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
337
diff
changeset
|
23 #ifdef HAVE_CONFIG_H |
|
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
337
diff
changeset
|
24 #include "../config.h" |
|
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
337
diff
changeset
|
25 #endif |
| 1 | 26 #include <stdio.h> |
| 27 #include <stdlib.h> | |
| 28 #include <string.h> | |
| 29 #include <gtk/gtk.h> | |
| 30 #include <gdk/gdkprivate.h> | |
| 31 #include <gdk/gdkx.h> | |
| 32 #include <gdk/gdkkeysyms.h> | |
|
604
0b1a132e0f75
[gaim-migrate @ 614]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
574
diff
changeset
|
33 #include <ctype.h> |
| 12 | 34 |
| 35 #ifndef _WIN32 | |
| 1 | 36 #include <X11/Xlib.h> |
| 37 #include <X11/Xatom.h> | |
| 12 | 38 #endif |
| 39 | |
| 69 | 40 #include "gaim.h" |
| 1 | 41 #include "gtkhtml.h" |
| 42 | |
| 549 | 43 #include "pixmaps/aol_icon.xpm" |
| 44 #include "pixmaps/admin_icon.xpm" | |
| 45 #include "pixmaps/free_icon.xpm" | |
| 46 #include "pixmaps/dt_icon.xpm" | |
| 1 | 47 #define MAX_SIZE 7 |
| 48 #define MIN_HTML_WIDTH_LINES 20 | |
| 49 #define MIN_HTML_HEIGHT_LINES 10 | |
| 50 #define BORDER_WIDTH 2 | |
| 51 #define SCROLL_TIME 100 | |
| 52 #define SCROLL_PIXELS 5 | |
| 53 #define KEY_SCROLL_PIXELS 10 | |
| 54 | |
| 55 int font_sizes[] = { 80, 100, 120, 140, 200, 300, 400 }; | |
| 56 | |
| 12 | 57 /* |
| 1 | 58 GdkFont *fixed_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; |
| 59 GdkFont *fixed_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 60 GdkFont *fixed_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 12 | 61 GdkFont *fixed_bold_italic_font[] = |
| 62 { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 1 | 63 GdkFont *prop_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; |
| 64 GdkFont *prop_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 65 GdkFont *prop_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 66 GdkFont *prop_bold_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | |
| 12 | 67 */ |
| 68 | |
| 69 GData * font_cache; | |
| 70 static gboolean cache_init = FALSE; | |
| 71 | |
| 72 struct font_state | |
| 73 { | |
| 74 int size; | |
| 75 int owncolor; | |
| 76 int ownbg; | |
| 77 gchar font[1024]; | |
| 78 GdkColor *color; | |
| 79 GdkColor *bgcol; | |
| 80 struct font_state *next; | |
| 1 | 81 }; |
| 82 | |
| 83 struct font_state *push_state(struct font_state *current) | |
| 84 { | |
| 12 | 85 struct font_state *tmp; |
| 86 tmp = (struct font_state *) g_new0(struct font_state, 1); | |
| 1 | 87 tmp->next = current; |
| 88 tmp->color = current->color; | |
| 89 tmp->bgcol = current->bgcol; | |
| 90 tmp->size = current->size; | |
| 91 tmp->owncolor = 0; | |
| 92 tmp->ownbg = 0; | |
| 12 | 93 strcpy( tmp->font, current->font ); |
| 1 | 94 return tmp; |
| 95 } | |
| 96 | |
| 12 | 97 enum |
| 98 { | |
| 99 ARG_0, | |
| 100 ARG_HADJUSTMENT, | |
| 101 ARG_VADJUSTMENT, | |
| 1 | 102 }; |
| 103 | |
| 104 | |
| 12 | 105 enum |
| 106 { | |
| 107 TARGET_STRING, | |
| 108 TARGET_TEXT, | |
| 109 TARGET_COMPOUND_TEXT | |
| 1 | 110 }; |
| 111 | |
| 112 | |
| 12 | 113 static void gtk_html_class_init(GtkHtmlClass * klass); |
| 114 static void gtk_html_set_arg(GtkObject * object, GtkArg * arg, guint arg_id); | |
| 115 static void gtk_html_get_arg(GtkObject * object, GtkArg * arg, guint arg_id); | |
| 116 static void gtk_html_init(GtkHtml * html); | |
| 117 static void gtk_html_destroy(GtkObject * object); | |
| 118 static void gtk_html_finalize(GtkObject * object); | |
| 119 static void gtk_html_realize(GtkWidget * widget); | |
| 120 static void gtk_html_unrealize(GtkWidget * widget); | |
| 121 static void gtk_html_style_set(GtkWidget * widget, GtkStyle * previous_style); | |
| 122 static void gtk_html_draw_focus(GtkWidget * widget); | |
| 123 static void gtk_html_size_request(GtkWidget * widget, | |
| 124 GtkRequisition * requisition); | |
| 125 static void gtk_html_size_allocate(GtkWidget * widget, | |
| 126 GtkAllocation * allocation); | |
| 127 static void gtk_html_adjustment(GtkAdjustment * adjustment, GtkHtml * html); | |
| 128 static void gtk_html_disconnect(GtkAdjustment * adjustment, GtkHtml * html); | |
| 129 static void gtk_html_add_seperator(GtkHtml * html); | |
| 337 | 130 // static void gtk_html_add_pixmap(GtkHtml * html, GdkPixmap * pm, gint fit); |
| 12 | 131 static void gtk_html_add_text(GtkHtml * html, |
| 132 GdkFont * font, | |
| 133 GdkColor * fore, | |
| 134 GdkColor * back, | |
| 135 gchar * chars, | |
| 136 gint length, | |
| 137 gint uline, gint strike, gchar * url); | |
| 138 static void gtk_html_draw_bit(GtkHtml * html, | |
| 139 GtkHtmlBit * htmlbit, gint redraw); | |
| 140 static void gtk_html_selection_get(GtkWidget * widget, | |
| 141 GtkSelectionData * selection_data, | |
| 142 guint sel_info, guint32 time); | |
| 143 static gint gtk_html_selection_clear(GtkWidget * widget, | |
| 144 GdkEventSelection * event); | |
| 145 static gint gtk_html_visibility_notify(GtkWidget * widget, | |
| 146 GdkEventVisibility * event); | |
| 1 | 147 |
| 148 | |
| 149 /* Event handlers */ | |
| 12 | 150 static void gtk_html_draw(GtkWidget * widget, GdkRectangle * area); |
| 151 static gint gtk_html_expose(GtkWidget * widget, GdkEventExpose * event); | |
| 152 static gint gtk_html_button_press(GtkWidget * widget, GdkEventButton * event); | |
| 153 static gint gtk_html_button_release(GtkWidget * widget, GdkEventButton * event); | |
| 154 static gint gtk_html_motion_notify(GtkWidget * widget, GdkEventMotion * event); | |
| 155 static gint gtk_html_key_press(GtkWidget * widget, GdkEventKey * event); | |
| 156 static gint gtk_html_leave_notify(GtkWidget * widget, GdkEventCrossing * event); | |
| 1 | 157 |
| 158 static gint gtk_html_tooltip_timeout(gpointer data); | |
| 159 | |
| 160 | |
| 12 | 161 static void clear_area(GtkHtml * html, GdkRectangle * area); |
| 162 static void expose_html(GtkHtml * html, GdkRectangle * area, gboolean cursor); | |
| 163 static void scroll_down(GtkHtml * html, gint diff0); | |
| 164 static void scroll_up(GtkHtml * html, gint diff0); | |
| 165 | |
| 166 static void adjust_adj(GtkHtml * html, GtkAdjustment * adj); | |
| 167 static void resize_html(GtkHtml * html); | |
| 168 static gint html_bit_is_onscreen(GtkHtml * html, GtkHtmlBit * hb); | |
| 169 static void draw_cursor(GtkHtml * html); | |
| 170 static void undraw_cursor(GtkHtml * html); | |
| 1 | 171 |
| 172 static GtkWidgetClass *parent_class = NULL; | |
| 173 | |
| 174 GtkType gtk_html_get_type(void) | |
| 175 { | |
| 12 | 176 static GtkType html_type = 0; |
| 177 | |
| 178 if (!html_type) | |
| 179 { | |
| 180 static const GtkTypeInfo html_info = { | |
| 181 "GtkHtml", | |
| 182 sizeof(GtkHtml), | |
| 183 sizeof(GtkHtmlClass), | |
| 184 (GtkClassInitFunc) gtk_html_class_init, | |
| 185 (GtkObjectInitFunc) gtk_html_init, | |
| 186 NULL, | |
| 187 NULL, | |
| 188 NULL, | |
| 189 }; | |
| 190 html_type = gtk_type_unique(GTK_TYPE_WIDGET, &html_info); | |
| 191 } | |
| 192 return html_type; | |
| 1 | 193 } |
| 194 | |
| 195 | |
| 12 | 196 static void gtk_html_class_init(GtkHtmlClass * class) |
| 1 | 197 { |
| 12 | 198 GtkObjectClass *object_class; |
| 199 GtkWidgetClass *widget_class; | |
| 200 | |
| 201 object_class = (GtkObjectClass *) class; | |
| 202 widget_class = (GtkWidgetClass *) class; | |
| 203 parent_class = gtk_type_class(GTK_TYPE_WIDGET); | |
| 204 | |
| 205 | |
| 206 gtk_object_add_arg_type("GtkHtml::hadjustment", | |
| 207 GTK_TYPE_ADJUSTMENT, | |
| 208 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, | |
| 209 ARG_HADJUSTMENT); | |
| 210 | |
| 211 gtk_object_add_arg_type("GtkHtml::vadjustment", | |
| 212 GTK_TYPE_ADJUSTMENT, | |
| 213 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, | |
| 214 ARG_VADJUSTMENT); | |
| 215 | |
| 216 object_class->set_arg = gtk_html_set_arg; | |
| 217 object_class->get_arg = gtk_html_get_arg; | |
| 218 object_class->destroy = gtk_html_destroy; | |
| 219 object_class->finalize = gtk_html_finalize; | |
| 220 | |
| 221 widget_class->realize = gtk_html_realize; | |
| 222 widget_class->unrealize = gtk_html_unrealize; | |
| 223 widget_class->style_set = gtk_html_style_set; | |
| 224 widget_class->draw_focus = gtk_html_draw_focus; | |
| 225 widget_class->size_request = gtk_html_size_request; | |
| 226 widget_class->size_allocate = gtk_html_size_allocate; | |
| 227 widget_class->draw = gtk_html_draw; | |
| 228 widget_class->expose_event = gtk_html_expose; | |
| 229 widget_class->button_press_event = gtk_html_button_press; | |
| 230 widget_class->button_release_event = gtk_html_button_release; | |
| 1 | 231 widget_class->motion_notify_event = gtk_html_motion_notify; |
| 232 widget_class->leave_notify_event = gtk_html_leave_notify; | |
| 12 | 233 widget_class->selection_get = gtk_html_selection_get; |
| 1 | 234 widget_class->selection_clear_event = gtk_html_selection_clear; |
| 235 widget_class->key_press_event = gtk_html_key_press; | |
| 236 widget_class->visibility_notify_event = gtk_html_visibility_notify; | |
| 12 | 237 |
| 238 | |
| 239 widget_class->set_scroll_adjustments_signal = | |
| 240 gtk_signal_new("set_scroll_adjustments", | |
| 241 GTK_RUN_LAST, | |
| 242 object_class->type, | |
| 243 GTK_SIGNAL_OFFSET(GtkHtmlClass, set_scroll_adjustments), | |
| 244 gtk_marshal_NONE__POINTER_POINTER, | |
| 245 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, | |
| 246 GTK_TYPE_ADJUSTMENT); | |
| 247 | |
| 248 | |
| 249 class->set_scroll_adjustments = gtk_html_set_adjustments; | |
| 1 | 250 |
| 251 } | |
| 252 | |
| 12 | 253 static void gtk_html_set_arg(GtkObject * object, GtkArg * arg, guint arg_id) |
| 1 | 254 { |
| 12 | 255 GtkHtml *html; |
| 256 | |
| 257 html = GTK_HTML(object); | |
| 258 | |
| 259 switch (arg_id) | |
| 260 { | |
| 261 case ARG_HADJUSTMENT: | |
| 262 gtk_html_set_adjustments(html, GTK_VALUE_POINTER(*arg), html->vadj); | |
| 263 break; | |
| 264 case ARG_VADJUSTMENT: | |
| 265 gtk_html_set_adjustments(html, html->hadj, GTK_VALUE_POINTER(*arg)); | |
| 266 break; | |
| 267 default: | |
| 268 break; | |
| 269 } | |
| 1 | 270 } |
| 271 | |
| 12 | 272 static void gtk_html_get_arg(GtkObject * object, GtkArg * arg, guint arg_id) |
| 1 | 273 { |
| 12 | 274 GtkHtml *html; |
| 275 | |
| 276 html = GTK_HTML(object); | |
| 277 | |
| 278 switch (arg_id) | |
| 279 { | |
| 280 case ARG_HADJUSTMENT: | |
| 281 GTK_VALUE_POINTER(*arg) = html->hadj; | |
| 282 break; | |
| 283 case ARG_VADJUSTMENT: | |
| 284 GTK_VALUE_POINTER(*arg) = html->vadj; | |
| 285 break; | |
| 286 default: | |
| 287 arg->type = GTK_TYPE_INVALID; | |
| 288 break; | |
| 289 } | |
| 1 | 290 } |
| 291 | |
| 12 | 292 static void gtk_html_init(GtkHtml * html) |
| 1 | 293 { |
| 12 | 294 static const GtkTargetEntry targets[] = { |
| 295 {"STRING", 0, TARGET_STRING}, | |
| 296 {"TEXT", 0, TARGET_TEXT}, | |
| 297 {"COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT} | |
| 298 }; | |
| 299 | |
| 300 static const gint n_targets = sizeof(targets) / sizeof(targets[0]); | |
| 301 | |
| 302 GTK_WIDGET_SET_FLAGS(html, GTK_CAN_FOCUS); | |
| 303 | |
| 304 html->html_area = NULL; | |
| 305 html->hadj = NULL; | |
| 306 html->vadj = NULL; | |
| 1 | 307 html->current_x = 0; |
| 308 html->current_y = 0; | |
| 12 | 309 html->start_sel = html->end_sel = NULL; |
| 310 html->start_sel_x = html->start_sel_y = -1; | |
| 311 html->num_end = html->num_start = -1; | |
| 312 | |
| 1 | 313 html->html_bits = NULL; |
| 314 html->urls = NULL; | |
| 315 html->selected_text = NULL; | |
| 316 html->tooltip_hb = NULL; | |
| 317 html->tooltip_timer = -1; | |
| 318 html->tooltip_window = NULL; | |
| 12 | 319 html->cursor_hb = NULL; |
| 1 | 320 html->cursor_pos = 0; |
| 321 | |
| 322 html->pm = NULL; | |
| 323 | |
| 324 html->editable = 0; | |
| 325 html->transparent = 0; | |
| 326 | |
| 12 | 327 html->frozen = 0; |
| 328 | |
| 329 gtk_selection_add_targets(GTK_WIDGET(html), GDK_SELECTION_PRIMARY, | |
| 330 targets, n_targets); | |
| 331 | |
| 332 | |
| 333 | |
| 1 | 334 } |
| 335 | |
| 336 | |
| 12 | 337 GtkWidget *gtk_html_new(GtkAdjustment * hadj, GtkAdjustment * vadj) |
| 1 | 338 { |
| 12 | 339 GtkWidget *html; |
| 340 if(!cache_init) | |
| 341 { | |
| 342 g_datalist_init(&font_cache); | |
| 343 cache_init = TRUE; | |
| 344 } | |
| 345 | |
| 346 if (hadj) | |
| 347 g_return_val_if_fail(GTK_IS_ADJUSTMENT(hadj), NULL); | |
| 348 if (vadj) | |
| 349 g_return_val_if_fail(GTK_IS_ADJUSTMENT(vadj), NULL); | |
| 350 | |
| 351 html = gtk_widget_new(GTK_TYPE_HTML, | |
| 352 "hadjustment", hadj, "vadjustment", vadj, NULL); | |
| 353 | |
| 354 return html; | |
| 1 | 355 } |
| 356 | |
| 357 | |
| 12 | 358 void gtk_html_set_editable(GtkHtml * html, gboolean is_editable) |
| 1 | 359 { |
| 12 | 360 g_return_if_fail(html != NULL); |
| 361 g_return_if_fail(GTK_IS_HTML(html)); | |
| 362 | |
| 363 | |
| 364 html->editable = (is_editable != FALSE); | |
| 365 | |
| 366 if (is_editable) | |
| 367 draw_cursor(html); | |
| 368 else | |
| 369 undraw_cursor(html); | |
| 1 | 370 |
| 371 } | |
| 372 | |
| 12 | 373 void gtk_html_set_transparent(GtkHtml * html, gboolean is_transparent) |
| 1 | 374 { |
| 12 | 375 GdkRectangle rect; |
| 376 gint width, | |
| 377 height; | |
| 378 GtkWidget *widget; | |
| 379 | |
| 380 g_return_if_fail(html != NULL); | |
| 381 g_return_if_fail(GTK_IS_HTML(html)); | |
| 382 | |
| 383 | |
| 384 widget = GTK_WIDGET(html); | |
| 385 html->transparent = (is_transparent != FALSE); | |
| 386 | |
| 387 if (!GTK_WIDGET_REALIZED(widget)) | |
| 388 return; | |
| 389 | |
| 390 html->bg_gc = NULL; | |
| 391 gdk_window_get_size(widget->window, &width, &height); | |
| 392 rect.x = 0; | |
| 393 rect.y = 0; | |
| 394 rect.width = width; | |
| 395 rect.height = height; | |
| 396 gdk_window_clear_area(widget->window, rect.x, rect.y, rect.width, | |
| 397 rect.height); | |
| 398 | |
| 399 expose_html(html, &rect, FALSE); | |
| 400 gtk_html_draw_focus((GtkWidget *) html); | |
| 1 | 401 } |
| 402 | |
| 403 | |
| 12 | 404 void gtk_html_set_adjustments(GtkHtml * html, |
| 405 GtkAdjustment * hadj, GtkAdjustment * vadj) | |
| 1 | 406 { |
| 12 | 407 g_return_if_fail(html != NULL); |
| 408 g_return_if_fail(GTK_IS_HTML(html)); | |
| 409 if (hadj) | |
| 410 g_return_if_fail(GTK_IS_ADJUSTMENT(hadj)); | |
| 411 else | |
| 412 hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); | |
| 413 if (vadj) | |
| 414 g_return_if_fail(GTK_IS_ADJUSTMENT(vadj)); | |
| 415 else | |
| 416 vadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); | |
| 417 | |
| 418 if (html->hadj && (html->hadj != hadj)) | |
| 419 { | |
| 420 gtk_signal_disconnect_by_data(GTK_OBJECT(html->hadj), html); | |
| 421 gtk_object_unref(GTK_OBJECT(html->hadj)); | |
| 422 } | |
| 423 | |
| 424 if (html->vadj && (html->vadj != vadj)) | |
| 425 { | |
| 426 gtk_signal_disconnect_by_data(GTK_OBJECT(html->vadj), html); | |
| 427 gtk_object_unref(GTK_OBJECT(html->vadj)); | |
| 428 } | |
| 429 | |
| 430 if (html->hadj != hadj) | |
| 431 { | |
| 432 html->hadj = hadj; | |
| 433 gtk_object_ref(GTK_OBJECT(html->hadj)); | |
| 434 gtk_object_sink(GTK_OBJECT(html->hadj)); | |
| 435 | |
| 436 gtk_signal_connect(GTK_OBJECT(html->hadj), "changed", | |
| 437 (GtkSignalFunc) gtk_html_adjustment, html); | |
| 438 gtk_signal_connect(GTK_OBJECT(html->hadj), "value_changed", | |
| 439 (GtkSignalFunc) gtk_html_adjustment, html); | |
| 440 gtk_signal_connect(GTK_OBJECT(html->hadj), "disconnect", | |
| 441 (GtkSignalFunc) gtk_html_disconnect, html); | |
| 442 gtk_html_adjustment(hadj, html); | |
| 443 } | |
| 444 | |
| 445 if (html->vadj != vadj) | |
| 446 { | |
| 447 html->vadj = vadj; | |
| 448 gtk_object_ref(GTK_OBJECT(html->vadj)); | |
| 449 gtk_object_sink(GTK_OBJECT(html->vadj)); | |
| 450 | |
| 451 gtk_signal_connect(GTK_OBJECT(html->vadj), "changed", | |
| 452 (GtkSignalFunc) gtk_html_adjustment, html); | |
| 453 gtk_signal_connect(GTK_OBJECT(html->vadj), "value_changed", | |
| 454 (GtkSignalFunc) gtk_html_adjustment, html); | |
| 455 gtk_signal_connect(GTK_OBJECT(html->vadj), "disconnect", | |
| 456 (GtkSignalFunc) gtk_html_disconnect, html); | |
| 457 gtk_html_adjustment(vadj, html); | |
| 458 } | |
| 1 | 459 } |
| 460 | |
| 461 | |
| 462 | |
| 12 | 463 GdkColor *get_color(int colorv, GdkColormap * map) |
| 1 | 464 { |
| 465 GdkColor *color; | |
| 12 | 466 #if 0 |
| 467 fprintf(stdout, "color is %x\n", colorv); | |
| 468 #endif | |
| 469 color = (GdkColor *) g_new0(GdkColor, 1); | |
| 1 | 470 color->red = ((colorv & 0xff0000) >> 16) * 256; |
| 471 color->green = ((colorv & 0xff00) >> 8) * 256; | |
| 472 color->blue = ((colorv & 0xff)) * 256; | |
| 473 #if 0 | |
| 12 | 474 fprintf(stdout, "Colors are %d, %d, %d\n", color->red, color->green, |
| 475 color->blue); | |
| 1 | 476 #endif |
| 477 gdk_color_alloc(map, color); | |
| 478 return color; | |
| 479 } | |
| 480 | |
| 481 | |
| 286 | 482 int load_font_with_cache(const char *name, const char *weight, char slant, |
| 483 int size, GdkFont **font_return) | |
| 1 | 484 { |
| 286 | 485 gchar font_spec[1024]; |
| 486 | |
|
306
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
487 if (size > 0) |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
488 g_snprintf(font_spec, sizeof font_spec, |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
489 "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*", |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
490 name, weight, slant, size); |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
491 else |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
492 g_snprintf(font_spec, sizeof font_spec, |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
493 "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"); |
| 286 | 494 |
| 495 if((*font_return = g_datalist_id_get_data(&font_cache, | |
| 496 g_quark_from_string(font_spec)))) { | |
| 497 return TRUE; | |
| 498 } else if ((*font_return = gdk_font_load(font_spec))) { | |
| 499 g_datalist_id_set_data(&font_cache, | |
| 500 g_quark_from_string(font_spec), *font_return); | |
| 501 return TRUE; | |
| 502 } else { | |
| 503 return FALSE; | |
| 12 | 504 } |
| 286 | 505 } |
| 506 | |
| 507 | |
| 508 GdkFont *getfont(const char *font, int bold, int italic, int fixed, int size) | |
| 509 { | |
| 510 GdkFont *my_font = NULL; | |
| 511 gchar *weight, slant; | |
| 512 | |
| 513 if (!font || !strlen(font)) font = fixed ? "courier" : "helvetica"; | |
| 514 weight = bold ? "bold" : "medium"; | |
| 515 slant = italic ? 'i' : 'r'; | |
| 516 | |
| 517 if (size > MAX_SIZE) size = MAX_SIZE; | |
| 518 if (size < 1) size = 1; | |
| 519 size = font_sizes[size-1]; | |
| 520 | |
| 521 /* try both 'i'talic and 'o'blique for italic fonts, and keep | |
| 522 * increasing the size until we get one that works. */ | |
| 523 | |
|
305
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
524 while (size <= 720) { |
| 286 | 525 if (load_font_with_cache(font, weight, slant, size, &my_font)) |
| 526 return my_font; | |
| 527 if (italic && load_font_with_cache(font, weight, 'o', size, &my_font)) | |
| 528 return my_font; | |
| 529 size += 10; | |
| 12 | 530 } |
| 531 | |
| 286 | 532 /* since we couldn't get any size up to 72, fall back to the |
| 533 * default fonts. */ | |
| 534 | |
| 535 font = fixed ? "courier" : "helvetica"; | |
|
305
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
536 size = 120; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
537 while (size <= 720) { |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
538 if (load_font_with_cache(font, weight, slant, size, &my_font)) |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
539 return my_font; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
540 size += 10; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
541 } |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
542 |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
543 font = fixed ? "helvetica" : "courier"; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
544 size = 120; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
545 while (size <= 720) { |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
546 if (load_font_with_cache(font, weight, slant, size, &my_font)) |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
547 return my_font; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
548 size += 10; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
549 } |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
550 |
|
721
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
551 /* whoops, couldn't do any of those. maybe they have a default outgoing |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
552 * font? maybe we can use that. */ |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
553 if (fontface[0]) { |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
554 /* woohoo! */ |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
555 size = 120; |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
556 while (size <= 720) { |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
557 if (load_font_with_cache(fontface, "medium", 'r', size, &my_font)) |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
558 return my_font; |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
559 size += 10; |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
560 } |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
561 } |
|
8e7ad10b5f26
[gaim-migrate @ 731]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
720
diff
changeset
|
562 |
|
305
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
563 /* ok, now we're in a pickle. if we can't do any of the above, let's |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
564 * try doing the most boring font we can find. */ |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
565 size = 120; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
566 while (size <= 720) { |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
567 if (load_font_with_cache("courier", "medium", 'r', size, &my_font)) |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
568 return my_font; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
569 size += 10; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
570 } |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
571 |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
572 size = 120; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
573 while (size <= 720) { |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
574 if (load_font_with_cache("helvetica", "medium", 'r', size, &my_font)) |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
575 return my_font; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
576 size += 10; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
577 } |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
578 |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
579 size = 120; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
580 while (size <= 720) { |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
581 if (load_font_with_cache("times", "medium", 'r', size, &my_font)) |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
582 return my_font; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
583 size += 10; |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
584 } |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
585 |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
586 /* my god, how did we end up here. is there a 'generic font' function |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
587 * in gdk? that would be incredibly useful here. there's gotta be a |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
588 * better way to do this. */ |
|
77404a4692b1
[gaim-migrate @ 315]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
286
diff
changeset
|
589 |
|
306
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
590 /* well, if they can't do any of the fonts above, they'll take whatever |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
591 * they can get, and be happy about it, damn it. :) */ |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
592 load_font_with_cache("*", "*", '*', -1, &my_font); |
|
a8f964718837
[gaim-migrate @ 316]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
305
diff
changeset
|
593 return my_font; |
| 1 | 594 } |
| 595 | |
| 596 | |
| 597 /* 'Borrowed' from ETerm */ | |
| 12 | 598 GdkWindow *get_desktop_window(GtkWidget * widget) |
| 1 | 599 { |
| 12 | 600 #ifndef _WIN32 |
| 601 GdkAtom prop, | |
| 602 type, | |
| 603 prop2; | |
| 604 int format; | |
| 605 gint length; | |
| 606 guchar *data; | |
| 1 | 607 GtkWidget *w; |
| 608 | |
| 12 | 609 prop = gdk_atom_intern("_XROOTPMAP_ID", 1); |
| 610 prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1); | |
| 611 | |
| 612 if (prop == None && prop2 == None) | |
| 613 { | |
| 614 return NULL; | |
| 615 } | |
| 616 | |
| 617 | |
| 618 | |
| 619 for (w = widget; w; w = w->parent) | |
| 620 { | |
| 621 | |
| 622 if (prop != None) | |
| 623 { | |
| 1 | 624 gdk_property_get(w->window, prop, AnyPropertyType, 0L, 1L, 0, |
| 12 | 625 &type, &format, &length, &data); |
| 626 } | |
| 627 else if (prop2 != None) | |
| 628 { | |
| 1 | 629 gdk_property_get(w->window, prop2, AnyPropertyType, 0L, 1L, 0, |
| 12 | 630 &type, &format, &length, &data); |
| 631 } | |
| 632 else | |
| 633 { | |
| 1 | 634 continue; |
| 635 } | |
| 12 | 636 if (type != None) |
| 637 { | |
| 1 | 638 return (w->window); |
| 639 } | |
| 640 } | |
| 12 | 641 #endif |
| 1 | 642 return NULL; |
| 643 | |
| 644 } | |
| 645 | |
| 646 | |
| 647 | |
| 12 | 648 GdkPixmap *get_desktop_pixmap(GtkWidget * widget) |
| 1 | 649 { |
| 12 | 650 #ifndef _WIN32 |
| 651 GdkPixmap *p; | |
| 652 GdkAtom prop, | |
| 653 type, | |
| 654 prop2; | |
| 655 int format; | |
| 656 gint length; | |
| 657 guint32 id; | |
| 658 guchar *data; | |
| 659 | |
| 660 prop = gdk_atom_intern("_XROOTPMAP_ID", 1); | |
| 661 prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1); | |
| 662 | |
| 663 | |
| 664 if (prop == None && prop2 == None) | |
| 665 { | |
| 666 return NULL; | |
| 667 } | |
| 668 | |
| 669 if (prop != None) | |
| 670 { | |
| 671 gdk_property_get(get_desktop_window(widget), prop, AnyPropertyType, 0L, | |
| 672 1L, 0, &type, &format, &length, &data); | |
| 673 if (type == XA_PIXMAP) | |
| 674 { | |
| 1 | 675 id = data[0]; |
| 676 id += data[1] << 8; | |
| 677 id += data[2] << 16; | |
| 678 id += data[3] << 24; | |
| 12 | 679 p = gdk_pixmap_foreign_new(id); |
| 680 return p; | |
| 681 } | |
| 682 } | |
| 683 if (prop2 != None) | |
| 684 { | |
| 685 | |
| 1 | 686 /* XGetWindowProperty(Xdisplay, desktop_window, prop2, 0L, 1L, False, AnyPropertyType, |
| 687 &type, &format, &length, &after, &data);*/ | |
| 12 | 688 |
| 1 | 689 /* if (type == XA_CARDINAL) {*/ |
| 12 | 690 /* |
| 691 * D_PIXMAP((" Solid color not yet supported.\n")); | |
| 692 */ | |
| 693 | |
| 1 | 694 /* return NULL; |
| 695 }*/ | |
| 12 | 696 } |
| 697 /* | |
| 698 * D_PIXMAP(("No suitable attribute found.\n")); | |
| 699 */ | |
| 700 #endif | |
| 701 return NULL; | |
| 1 | 702 } |
| 703 | |
| 704 | |
| 12 | 705 static void clear_focus_area(GtkHtml * html, |
| 706 gint area_x, | |
| 707 gint area_y, gint area_width, gint area_height) | |
| 1 | 708 { |
| 12 | 709 GtkWidget *widget = GTK_WIDGET(html); |
| 710 gint x, | |
| 711 y; | |
| 712 | |
| 713 gint ythick = BORDER_WIDTH + widget->style->klass->ythickness; | |
| 714 gint xthick = BORDER_WIDTH + widget->style->klass->xthickness; | |
| 715 | |
| 716 gint width, | |
| 717 height; | |
| 718 | |
| 719 if (html->frozen > 0) | |
| 720 return; | |
| 721 | |
| 722 if (html->transparent) | |
| 723 { | |
| 1 | 724 if (html->pm == NULL) |
| 725 html->pm = get_desktop_pixmap(widget); | |
| 726 | |
| 12 | 727 if (html->pm == NULL) |
| 728 return; | |
| 729 | |
| 730 if (html->bg_gc == NULL) | |
| 731 { | |
| 1 | 732 GdkGCValues values; |
| 733 | |
| 12 | 734 values.tile = html->pm; |
| 735 values.fill = GDK_TILED; | |
| 736 | |
| 737 html->bg_gc = gdk_gc_new_with_values(html->html_area, &values, | |
| 738 GDK_GC_FILL | GDK_GC_TILE); | |
| 739 | |
| 740 } | |
| 741 | |
| 742 gdk_window_get_deskrelative_origin(widget->window, &x, &y); | |
| 1 | 743 |
| 744 gdk_draw_pixmap(widget->window, html->bg_gc, html->pm, | |
| 12 | 745 x + area_x, y + area_y, area_x, area_y, area_width, |
| 746 area_height); | |
| 747 | |
| 748 | |
| 749 } | |
| 750 else | |
| 751 { | |
| 752 gdk_window_get_size(widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, | |
| 753 &height); | |
| 754 | |
| 755 gdk_gc_set_ts_origin(html->bg_gc, | |
| 756 (-html->xoffset + xthick) % width, | |
| 757 (-html->yoffset + ythick) % height); | |
| 758 | |
| 759 gdk_draw_rectangle(widget->window, html->bg_gc, TRUE, | |
| 760 area_x, area_y, area_width, area_height); | |
| 761 } | |
| 1 | 762 } |
| 763 | |
| 12 | 764 static void gtk_html_draw_focus(GtkWidget * widget) |
| 1 | 765 { |
| 12 | 766 GtkHtml *html; |
| 767 gint width, | |
| 768 height; | |
| 769 gint x, | |
| 770 y; | |
| 771 | |
| 772 g_return_if_fail(widget != NULL); | |
| 773 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 1 | 774 |
| 775 html = GTK_HTML(widget); | |
| 776 | |
| 12 | 777 if (GTK_WIDGET_DRAWABLE(widget)) |
| 778 { | |
| 779 gint ythick = widget->style->klass->ythickness; | |
| 780 gint xthick = widget->style->klass->xthickness; | |
| 781 gint xextra = BORDER_WIDTH; | |
| 782 gint yextra = BORDER_WIDTH; | |
| 783 | |
| 784 x = 0; | |
| 785 y = 0; | |
| 786 width = widget->allocation.width; | |
| 787 height = widget->allocation.height; | |
| 788 | |
| 789 if (GTK_WIDGET_HAS_FOCUS(widget)) | |
| 790 { | |
| 791 x += 1; | |
| 792 y += 1; | |
| 793 width -= 2; | |
| 794 height -= 2; | |
| 795 xextra -= 1; | |
| 796 yextra -= 1; | |
| 797 | |
| 798 gtk_paint_focus(widget->style, widget->window, | |
| 799 NULL, widget, "text", | |
| 800 0, 0, | |
| 801 widget->allocation.width - 1, | |
| 802 widget->allocation.height - 1); | |
| 803 } | |
| 804 | |
| 805 gtk_paint_shadow(widget->style, widget->window, | |
| 806 GTK_STATE_NORMAL, GTK_SHADOW_IN, | |
| 807 NULL, widget, "text", x, y, width, height); | |
| 808 | |
| 809 x += xthick; | |
| 810 y += ythick; | |
| 811 width -= 2 * xthick; | |
| 812 height -= 2 * ythick; | |
| 813 | |
| 814 | |
| 815 if (widget->style->bg_pixmap[GTK_STATE_NORMAL] || html->transparent) | |
| 816 { | |
| 817 /* | |
| 818 * top rect | |
| 819 */ | |
| 820 clear_focus_area(html, x, y, width, yextra); | |
| 821 /* | |
| 822 * left rect | |
| 823 */ | |
| 824 clear_focus_area(html, x, y + yextra, | |
| 825 xextra, y + height - 2 * yextra); | |
| 826 /* | |
| 827 * right rect | |
| 828 */ | |
| 829 clear_focus_area(html, x + width - xextra, y + yextra, | |
| 830 xextra, height - 2 * ythick); | |
| 831 /* | |
| 832 * bottom rect | |
| 833 */ | |
| 834 clear_focus_area(html, x, x + height - yextra, width, yextra); | |
| 835 } | |
| 836 } | |
| 1 | 837 } |
| 838 | |
| 12 | 839 static void gtk_html_size_request(GtkWidget * widget, |
| 840 GtkRequisition * requisition) | |
| 1 | 841 { |
| 12 | 842 gint xthickness; |
| 843 gint ythickness; | |
| 844 gint char_height; | |
| 845 gint char_width; | |
| 846 | |
| 847 g_return_if_fail(widget != NULL); | |
| 848 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 849 g_return_if_fail(requisition != NULL); | |
| 850 | |
| 851 xthickness = widget->style->klass->xthickness + BORDER_WIDTH; | |
| 852 ythickness = widget->style->klass->ythickness + BORDER_WIDTH; | |
| 853 | |
| 854 char_height = MIN_HTML_HEIGHT_LINES * (widget->style->font->ascent + | |
| 855 widget->style->font->descent); | |
| 856 | |
| 857 char_width = MIN_HTML_WIDTH_LINES * (gdk_text_width(widget->style->font, | |
| 858 "ABCDEFGHIJKLMNOPQRSTUVWXYZ", | |
| 859 26) / 26); | |
| 860 | |
| 861 requisition->width = char_width + xthickness * 2; | |
| 862 requisition->height = char_height + ythickness * 2; | |
| 1 | 863 } |
| 864 | |
| 12 | 865 static void gtk_html_size_allocate(GtkWidget * widget, |
| 866 GtkAllocation * allocation) | |
| 1 | 867 { |
| 12 | 868 GtkHtml *html; |
| 869 | |
| 870 g_return_if_fail(widget != NULL); | |
| 871 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 872 g_return_if_fail(allocation != NULL); | |
| 873 | |
| 874 html = GTK_HTML(widget); | |
| 875 | |
| 876 widget->allocation = *allocation; | |
| 877 if (GTK_WIDGET_REALIZED(widget)) | |
| 878 { | |
| 879 gdk_window_move_resize(widget->window, | |
| 880 allocation->x, allocation->y, | |
| 881 allocation->width, allocation->height); | |
| 882 | |
| 883 gdk_window_move_resize(html->html_area, | |
| 884 widget->style->klass->xthickness + BORDER_WIDTH, | |
| 885 widget->style->klass->ythickness + BORDER_WIDTH, | |
| 886 MAX(1, (gint) widget->allocation.width - | |
| 887 (gint) (widget->style->klass->xthickness + | |
| 888 (gint) BORDER_WIDTH) * 2), | |
| 889 MAX(1, (gint) widget->allocation.height - | |
| 890 (gint) (widget->style->klass->ythickness + | |
| 891 (gint) BORDER_WIDTH) * 2)); | |
| 892 | |
| 893 resize_html(html); | |
| 894 } | |
| 895 } | |
| 896 | |
| 897 static void gtk_html_draw(GtkWidget * widget, GdkRectangle * area) | |
| 898 { | |
| 899 g_return_if_fail(widget != NULL); | |
| 900 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 901 g_return_if_fail(area != NULL); | |
| 902 | |
| 903 if (GTK_WIDGET_DRAWABLE(widget)) | |
| 904 { | |
| 905 expose_html(GTK_HTML(widget), area, TRUE); | |
| 906 gtk_widget_draw_focus(widget); | |
| 907 } | |
| 908 } | |
| 909 | |
| 910 | |
| 911 static gint gtk_html_expose(GtkWidget * widget, GdkEventExpose * event) | |
| 912 { | |
| 913 GtkHtml *html; | |
| 914 | |
| 915 g_return_val_if_fail(widget != NULL, FALSE); | |
| 916 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE); | |
| 917 g_return_val_if_fail(event != NULL, FALSE); | |
| 918 | |
| 919 html = GTK_HTML(widget); | |
| 920 | |
| 921 if (event->window == html->html_area) | |
| 922 { | |
| 923 expose_html(html, &event->area, TRUE); | |
| 924 } | |
| 925 else if (event->count == 0) | |
| 926 { | |
| 927 gtk_widget_draw_focus(widget); | |
| 928 } | |
| 929 | |
| 930 return FALSE; | |
| 1 | 931 |
| 932 } | |
| 933 | |
| 934 | |
| 12 | 935 static gint gtk_html_selection_clear(GtkWidget * widget, |
| 936 GdkEventSelection * event) | |
| 1 | 937 { |
| 12 | 938 GtkHtml *html; |
| 939 | |
| 940 g_return_val_if_fail(widget != NULL, FALSE); | |
| 941 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE); | |
| 942 g_return_val_if_fail(event != NULL, FALSE); | |
| 943 | |
| 944 /* | |
| 945 * Let the selection handling code know that the selection | |
| 946 * * has been changed, since we've overriden the default handler | |
| 947 */ | |
| 948 if (!gtk_selection_clear(widget, event)) | |
| 949 return FALSE; | |
| 950 | |
| 951 html = GTK_HTML(widget); | |
| 952 | |
| 953 if (event->selection == GDK_SELECTION_PRIMARY) | |
| 954 { | |
| 955 if (html->selected_text) | |
| 956 { | |
| 957 GList *hbits = html->html_bits; | |
| 958 GtkHtmlBit *hb; | |
| 959 | |
| 1 | 960 g_free(html->selected_text); |
| 961 html->selected_text = NULL; | |
| 962 html->start_sel = NULL; | |
| 963 html->end_sel = NULL; | |
| 964 html->num_start = 0; | |
| 965 html->num_end = 0; | |
| 12 | 966 while (hbits) |
| 967 { | |
| 968 hb = (GtkHtmlBit *) hbits->data; | |
| 1 | 969 if (hb->was_selected) |
| 970 gtk_html_draw_bit(html, hb, 1); | |
| 971 hbits = hbits->prev; | |
| 972 } | |
| 973 hbits = g_list_last(html->html_bits); | |
| 974 } | |
| 12 | 975 } |
| 976 | |
| 977 return TRUE; | |
| 1 | 978 } |
| 979 | |
| 980 | |
| 981 | |
| 12 | 982 static void gtk_html_selection_get(GtkWidget * widget, |
| 983 GtkSelectionData * selection_data, | |
| 984 guint sel_info, guint32 time) | |
| 1 | 985 { |
| 986 gchar *str; | |
| 12 | 987 gint len; |
| 988 GtkHtml *html; | |
| 989 | |
| 990 g_return_if_fail(widget != NULL); | |
| 991 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 992 | |
| 993 html = GTK_HTML(widget); | |
| 994 | |
| 995 | |
| 1 | 996 if (selection_data->selection != GDK_SELECTION_PRIMARY) |
| 997 return; | |
| 998 | |
| 999 str = html->selected_text; | |
| 1000 | |
| 1001 if (!str) | |
| 1002 return; | |
| 12 | 1003 |
| 1 | 1004 len = strlen(str); |
| 1005 | |
| 12 | 1006 if (sel_info == TARGET_STRING) |
| 1007 { | |
| 1 | 1008 gtk_selection_data_set(selection_data, |
| 12 | 1009 GDK_SELECTION_TYPE_STRING, |
| 1010 8 * sizeof(gchar), (guchar *) str, len); | |
| 1011 } | |
| 1012 else if ((sel_info == TARGET_TEXT) || (sel_info == TARGET_COMPOUND_TEXT)) | |
| 1013 { | |
| 1 | 1014 guchar *text; |
| 1015 GdkAtom encoding; | |
| 1016 gint format; | |
| 1017 gint new_length; | |
| 1018 | |
| 12 | 1019 gdk_string_to_compound_text(str, &encoding, &format, &text, |
| 1020 &new_length); | |
| 1021 gtk_selection_data_set(selection_data, encoding, format, text, | |
| 1022 new_length); | |
| 1023 gdk_free_compound_text(text); | |
| 1 | 1024 } |
| 1025 | |
| 1026 | |
| 1027 | |
| 1028 } | |
| 1029 | |
| 12 | 1030 static void do_select(GtkHtml * html, int x, int y) |
| 1 | 1031 { |
| 1032 GList *hbits = g_list_last(html->html_bits); | |
| 12 | 1033 int epos, |
| 1034 spos; | |
| 1 | 1035 GtkHtmlBit *hb; |
| 12 | 1036 |
| 1 | 1037 if (!hbits) |
| 1038 return; | |
| 12 | 1039 |
| 1040 hb = (GtkHtmlBit *) hbits->data; | |
| 1041 | |
| 1042 while (hbits) | |
| 1043 { | |
| 1044 hb = (GtkHtmlBit *) hbits->data; | |
| 1045 if (hb->type == HTML_BIT_TEXT) | |
| 1 | 1046 break; |
| 1047 hbits = hbits->prev; | |
| 12 | 1048 } |
| 1049 | |
| 1 | 1050 if (!hb) |
| 12 | 1051 return; |
| 1052 | |
| 1053 | |
| 1054 if (y > hb->y) | |
| 1055 { | |
| 1 | 1056 html->num_end = strlen(hb->text) - 1; |
| 1057 html->end_sel = hb; | |
| 12 | 1058 } |
| 1059 else if (y < 0) | |
| 1060 { | |
| 1 | 1061 html->num_end = 0; |
| 12 | 1062 html->end_sel = (GtkHtmlBit *) html->html_bits->data; |
| 1063 } | |
| 1064 else | |
| 1065 while (hbits) | |
| 1066 { | |
| 1067 hb = (GtkHtmlBit *) hbits->data; | |
| 1068 if ((y < hb->y && y > (hb->y - hb->height)) && | |
| 1069 (x > hb->x + hb->width)) | |
| 1070 { | |
| 1071 if (hb->type != HTML_BIT_TEXT) | |
| 1072 { | |
| 1073 html->num_end = 0; | |
| 1074 html->end_sel = hb; | |
| 1075 break; | |
| 1076 } | |
| 1077 | |
| 1078 html->num_end = strlen(hb->text) - 1; | |
| 1 | 1079 html->end_sel = hb; |
| 1080 break; | |
| 1081 } | |
| 12 | 1082 else if ((x > hb->x && x < (hb->x + hb->width)) && |
| 1083 (y < hb->y && y > (hb->y - hb->height))) | |
| 1084 { | |
| 1085 int i, | |
| 1086 len; | |
| 1087 int w = x - hb->x; | |
| 1088 | |
| 1089 if (hb->type != HTML_BIT_TEXT) | |
| 1090 { | |
| 1091 html->num_end = 0; | |
| 1 | 1092 html->end_sel = hb; |
| 1093 break; | |
| 1094 } | |
| 12 | 1095 |
| 1096 len = strlen(hb->text); | |
| 1097 | |
| 1098 for (i = 1; i <= len; i++) | |
| 1099 { | |
| 1100 if (gdk_text_measure(hb->font, hb->text, i) > w) | |
| 1101 { | |
| 1102 html->num_end = i - 1; | |
| 1103 html->end_sel = hb; | |
| 1104 break; | |
| 1105 } | |
| 1106 } | |
| 1107 break; | |
| 1 | 1108 } |
| 12 | 1109 hbits = hbits->prev; |
| 1 | 1110 } |
| 1111 | |
| 1112 if (html->end_sel == NULL) | |
| 1113 return; | |
| 12 | 1114 if (html->start_sel == NULL) |
| 1115 { | |
| 1 | 1116 html->start_sel = html->end_sel; |
| 1117 html->num_start = html->num_end; | |
| 1118 } | |
| 12 | 1119 |
| 1 | 1120 epos = g_list_index(html->html_bits, html->end_sel); |
| 1121 spos = g_list_index(html->html_bits, html->start_sel); | |
| 1122 g_free(html->selected_text); | |
| 1123 html->selected_text = NULL; | |
| 1124 | |
| 12 | 1125 if (epos == spos) |
| 1126 { | |
| 1 | 1127 char *str; |
| 12 | 1128 if (html->start_sel->type != HTML_BIT_TEXT) |
| 1129 { | |
| 1 | 1130 html->selected_text = NULL; |
| 1131 return; | |
| 1132 } | |
| 12 | 1133 if (html->num_end == html->num_start) |
| 1134 { | |
| 1 | 1135 str = g_malloc(2); |
| 12 | 1136 if (strlen(html->start_sel->text)) |
| 1 | 1137 str[0] = html->start_sel->text[html->num_end]; |
| 1138 else | |
| 12 | 1139 str[0] = 0; |
| 1 | 1140 str[1] = 0; |
| 1141 gtk_html_draw_bit(html, html->start_sel, 0); | |
| 1142 html->selected_text = str; | |
| 12 | 1143 } |
| 1144 else | |
| 1145 { | |
| 79 | 1146 size_t st, |
| 12 | 1147 en; |
| 1 | 1148 char *str; |
| 12 | 1149 if (html->num_end > html->num_start) |
| 1150 { | |
| 1 | 1151 en = html->num_end; |
| 1152 st = html->num_start; | |
| 12 | 1153 } |
| 1154 else | |
| 1155 { | |
| 1 | 1156 en = html->num_start; |
| 1157 st = html->num_end; | |
| 1158 } | |
| 1159 | |
| 1160 str = g_malloc(en - st + 2); | |
| 1161 strncpy(str, html->start_sel->text + st, (en - st + 1)); | |
| 1162 str[en - st + 1] = 0; | |
| 12 | 1163 gtk_html_draw_bit(html, html->start_sel, 0); |
| 1 | 1164 html->selected_text = str; |
| 12 | 1165 |
| 1 | 1166 } |
| 12 | 1167 } |
| 1168 else | |
| 1169 { | |
| 1170 GtkHtmlBit *shb, | |
| 1171 *ehb; | |
| 79 | 1172 size_t en, |
| 12 | 1173 st; |
| 1174 int len, | |
| 1175 nlen; | |
| 1 | 1176 char *str; |
| 12 | 1177 if (epos > spos) |
| 1178 { | |
| 1 | 1179 shb = html->start_sel; |
| 1180 ehb = html->end_sel; | |
| 1181 en = html->num_end; | |
| 1182 st = html->num_start; | |
| 12 | 1183 } |
| 1184 else | |
| 1185 { | |
| 1 | 1186 shb = html->end_sel; |
| 1187 ehb = html->start_sel; | |
| 1188 en = html->num_start; | |
| 1189 st = html->num_end; | |
| 1190 } | |
| 12 | 1191 |
| 1 | 1192 hbits = g_list_find(html->html_bits, shb); |
| 1193 | |
| 1194 if (!hbits) | |
| 1195 return; | |
| 12 | 1196 |
| 1197 if (shb->type == HTML_BIT_TEXT) | |
| 1198 { | |
| 1 | 1199 len = strlen(shb->text) - st + 1; |
| 1200 str = g_malloc(len); | |
| 1201 strcpy(str, shb->text + st); | |
| 1202 str[len - 1] = 0; | |
| 1203 gtk_html_draw_bit(html, shb, 0); | |
| 12 | 1204 if (shb->newline) |
| 1205 { | |
| 1206 len += 1; | |
| 1 | 1207 str = g_realloc(str, len); |
| 1208 str[len - 2] = '\n'; | |
| 1209 str[len - 1] = 0; | |
| 1210 } | |
| 12 | 1211 } |
| 1212 else | |
| 1213 { | |
| 1 | 1214 len = 1; |
| 1215 str = g_malloc(1); | |
| 1216 str[0] = 0; | |
| 1217 } | |
| 12 | 1218 if (hbits->next == NULL) |
| 1219 { | |
| 1 | 1220 html->selected_text = str; |
| 1221 return; | |
| 1222 } | |
| 1223 | |
| 12 | 1224 |
| 1225 hbits = hbits->next; | |
| 1226 while (1) | |
| 1227 { /* | |
| 1228 * Yah I know is dangerous :P | |
| 1229 */ | |
| 1230 hb = (GtkHtmlBit *) hbits->data; | |
| 1231 if (hb->type != HTML_BIT_TEXT) | |
| 1232 { | |
| 1 | 1233 if (hb == ehb) |
| 1234 break; | |
| 1235 hbits = hbits->next; | |
| 1236 continue; | |
| 1237 } | |
| 12 | 1238 if (hb != ehb) |
| 1239 { | |
| 1 | 1240 nlen = len + strlen(hb->text); |
| 1241 str = g_realloc(str, nlen); | |
| 1242 strcpy(str + (len - 1), hb->text); | |
| 1243 len = nlen; | |
| 1244 str[len - 1] = 0; | |
| 1245 gtk_html_draw_bit(html, hb, 0); | |
| 12 | 1246 if (hb->newline) |
| 1247 { | |
| 1248 len += 1; | |
| 1 | 1249 str = g_realloc(str, len); |
| 1250 str[len - 2] = '\n'; | |
| 1251 str[len - 1] = 0; | |
| 1252 } | |
| 12 | 1253 } |
| 1254 else | |
| 1255 { | |
| 1 | 1256 nlen = len + en + 1; |
| 1257 str = g_realloc(str, nlen); | |
| 1258 strncpy(str + (len - 1), hb->text, en + 1); | |
| 1259 len = nlen; | |
| 1260 str[len - 1] = 0; | |
| 12 | 1261 |
| 1 | 1262 gtk_html_draw_bit(html, hb, 0); |
| 12 | 1263 if (hb->newline && en == strlen(hb->text)) |
| 1264 { | |
| 1265 len += 1; | |
| 1 | 1266 str = g_realloc(str, len); |
| 1267 str[len - 2] = '\n'; | |
| 1268 str[len - 1] = 0; | |
| 1269 } | |
| 1270 break; | |
| 1271 } | |
| 1272 hbits = hbits->next; | |
| 1273 } | |
| 1274 html->selected_text = str; | |
| 1275 } | |
| 1276 | |
| 1277 } | |
| 1278 | |
| 12 | 1279 static gint scroll_timeout(GtkHtml * html) |
| 1 | 1280 { |
| 12 | 1281 GdkEventMotion event; |
| 1282 gint x, | |
| 1283 y; | |
| 1284 GdkModifierType mask; | |
| 1 | 1285 |
| 1286 html->timer = 0; | |
| 12 | 1287 gdk_window_get_pointer(html->html_area, &x, &y, &mask); |
| 1288 | |
| 1 | 1289 if (mask & GDK_BUTTON1_MASK) |
| 1290 { | |
| 1291 event.is_hint = 0; | |
| 1292 event.x = x; | |
| 1293 event.y = y; | |
| 1294 event.state = mask; | |
| 1295 | |
| 12 | 1296 gtk_html_motion_notify(GTK_WIDGET(html), &event); |
| 1 | 1297 } |
| 1298 | |
| 1299 return FALSE; | |
| 1300 | |
| 1301 } | |
| 1302 | |
| 1303 | |
| 12 | 1304 static gint gtk_html_tooltip_paint_window(GtkHtml * html) |
| 1 | 1305 { |
| 1306 GtkStyle *style; | |
| 12 | 1307 gint y, |
| 1308 baseline_skip, | |
| 1309 gap; | |
| 1 | 1310 |
| 1311 style = html->tooltip_window->style; | |
| 1312 | |
| 1313 gap = (style->font->ascent + style->font->descent) / 4; | |
| 1314 if (gap < 2) | |
| 1315 gap = 2; | |
| 1316 baseline_skip = style->font->ascent + style->font->descent + gap; | |
| 1317 | |
| 1318 if (!html->tooltip_hb) | |
| 1319 return FALSE; | |
| 1320 | |
| 1321 gtk_paint_flat_box(style, html->tooltip_window->window, | |
| 12 | 1322 GTK_STATE_NORMAL, GTK_SHADOW_OUT, |
| 1323 NULL, GTK_WIDGET(html->tooltip_window), "tooltip", | |
| 1324 0, 0, -1, -1); | |
| 1 | 1325 |
| 1326 y = style->font->ascent + 4; | |
| 1327 | |
| 12 | 1328 gtk_paint_string(style, html->tooltip_window->window, |
| 1329 GTK_STATE_NORMAL, | |
| 1330 NULL, GTK_WIDGET(html->tooltip_window), "tooltip", | |
| 1331 4, y, "HTML Link:"); | |
| 1 | 1332 y += baseline_skip; |
| 12 | 1333 gtk_paint_string(style, html->tooltip_window->window, |
| 1334 GTK_STATE_NORMAL, | |
| 1335 NULL, GTK_WIDGET(html->tooltip_window), "tooltip", | |
| 1336 4, y, html->tooltip_hb->url); | |
| 1337 | |
| 1 | 1338 return FALSE; |
| 1339 | |
| 1340 | |
| 1341 } | |
| 1342 | |
| 1343 static gint gtk_html_tooltip_timeout(gpointer data) | |
| 1344 { | |
| 12 | 1345 GtkHtml *html = (GtkHtml *) data; |
| 1346 | |
| 1347 | |
| 1 | 1348 GDK_THREADS_ENTER(); |
| 1349 | |
| 12 | 1350 if (html->tooltip_hb && GTK_WIDGET_DRAWABLE(GTK_WIDGET(html))) |
| 1351 { | |
| 1 | 1352 GtkWidget *widget; |
| 1353 GtkStyle *style; | |
| 12 | 1354 gint gap, |
| 1355 x, | |
| 1356 y, | |
| 1357 w, | |
| 1358 h, | |
| 1359 scr_w, | |
| 1360 scr_h, | |
| 1361 baseline_skip; | |
| 1 | 1362 |
| 1363 if (html->tooltip_window) | |
| 1364 gtk_widget_destroy(html->tooltip_window); | |
| 12 | 1365 |
| 1366 html->tooltip_window = gtk_window_new(GTK_WINDOW_POPUP); | |
| 1367 gtk_widget_set_app_paintable(html->tooltip_window, TRUE); | |
| 1368 gtk_window_set_policy(GTK_WINDOW(html->tooltip_window), FALSE, FALSE, | |
| 1369 TRUE); | |
| 1370 gtk_widget_set_name(html->tooltip_window, "gtk-tooltips"); | |
| 1371 gtk_signal_connect_object(GTK_OBJECT(html->tooltip_window), | |
| 1372 "expose_event", | |
| 1373 GTK_SIGNAL_FUNC | |
| 1374 (gtk_html_tooltip_paint_window), | |
| 1375 GTK_OBJECT(html)); | |
| 1376 gtk_signal_connect_object(GTK_OBJECT(html->tooltip_window), "draw", | |
| 1377 GTK_SIGNAL_FUNC | |
| 1378 (gtk_html_tooltip_paint_window), | |
| 1379 GTK_OBJECT(html)); | |
| 1380 | |
| 1381 gtk_widget_ensure_style(html->tooltip_window); | |
| 1 | 1382 style = html->tooltip_window->style; |
| 12 | 1383 |
| 1 | 1384 widget = GTK_WIDGET(html); |
| 1385 | |
| 12 | 1386 scr_w = gdk_screen_width(); |
| 1387 scr_h = gdk_screen_height(); | |
| 1 | 1388 |
| 1389 gap = (style->font->ascent + style->font->descent) / 4; | |
| 1390 if (gap < 2) | |
| 1391 gap = 2; | |
| 1392 baseline_skip = style->font->ascent + style->font->descent + gap; | |
| 1393 | |
|
353
a4df8f1cc61a
[gaim-migrate @ 363]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
349
diff
changeset
|
1394 w = 8 + MAX(gdk_string_width(style->font, _("HTML Link:")), |
| 12 | 1395 gdk_string_width(style->font, html->tooltip_hb->url)); |
| 1396 ; | |
| 1 | 1397 h = 8 - gap; |
| 12 | 1398 h += (baseline_skip * 2); |
| 1399 | |
| 1400 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
| 1401 /* | |
| 1402 * gdk_window_get_origin (widget->window, NULL, &y); | |
| 1403 */ | |
| 1404 if (GTK_WIDGET_NO_WINDOW(widget)) | |
| 1 | 1405 y += widget->allocation.y; |
| 1406 | |
| 1407 x -= ((w >> 1) + 4); | |
| 1408 | |
| 1409 if ((x + w) > scr_w) | |
| 1410 x -= (x + w) - scr_w; | |
| 1411 else if (x < 0) | |
| 1412 x = 0; | |
| 1413 | |
| 1414 if ((y + h + 4) > scr_h) | |
| 12 | 1415 y = |
| 1416 y - html->tooltip_hb->font->ascent + | |
| 1417 html->tooltip_hb->font->descent; | |
| 1 | 1418 else |
| 12 | 1419 y = |
| 1420 y + html->tooltip_hb->font->ascent + | |
| 1421 html->tooltip_hb->font->descent; | |
| 1422 | |
| 1423 gtk_widget_set_usize(html->tooltip_window, w, h); | |
| 1424 gtk_widget_popup(html->tooltip_window, x, y); | |
| 1425 | |
| 1 | 1426 } |
| 1427 | |
| 1428 html->tooltip_timer = -1; | |
| 12 | 1429 |
| 1 | 1430 GDK_THREADS_LEAVE(); |
| 1431 | |
| 1432 return FALSE; | |
| 1433 } | |
| 1434 | |
| 1435 | |
| 12 | 1436 static gint gtk_html_leave_notify(GtkWidget * widget, GdkEventCrossing * event) |
| 1 | 1437 { |
| 12 | 1438 GtkHtml *html; |
| 1439 | |
| 1440 html = GTK_HTML(widget); | |
| 1441 | |
| 1442 if (html->tooltip_timer != -1) | |
| 1443 gtk_timeout_remove(html->tooltip_timer); | |
| 1444 if (html->tooltip_window) | |
| 1445 { | |
| 1446 gtk_widget_destroy(html->tooltip_window); | |
| 1447 html->tooltip_window = NULL; | |
| 1448 } | |
| 1449 | |
| 1450 | |
| 1451 html->tooltip_hb = NULL; | |
| 1452 return TRUE; | |
| 1 | 1453 } |
| 1454 | |
| 1455 | |
| 12 | 1456 static gint gtk_html_motion_notify(GtkWidget * widget, GdkEventMotion * event) |
| 1 | 1457 { |
| 12 | 1458 int x, |
| 1459 y; | |
| 1460 gint width, | |
| 1461 height; | |
| 1462 GdkModifierType state; | |
| 1463 int realx, | |
| 1464 realy; | |
| 1465 GtkHtml *html = GTK_HTML(widget); | |
| 1466 | |
| 1467 if (event->is_hint) | |
| 1468 gdk_window_get_pointer(event->window, &x, &y, &state); | |
| 1469 else | |
| 1470 { | |
| 1471 x = event->x; | |
| 1472 y = event->y; | |
| 1473 state = event->state; | |
| 1474 } | |
| 1475 | |
| 1476 gdk_window_get_size(html->html_area, &width, &height); | |
| 1477 | |
| 1 | 1478 realx = x; |
| 1479 realy = y + html->yoffset; | |
| 1480 | |
| 1481 | |
| 12 | 1482 if (state & GDK_BUTTON1_MASK) |
| 1483 { | |
| 1484 if (realx != html->start_sel_x || realy != html->start_sel_y) | |
| 1485 { | |
| 1 | 1486 char *tmp = NULL; |
| 1487 | |
| 12 | 1488 if (y < 0 || y > height) |
| 1489 { | |
| 1 | 1490 int diff; |
| 12 | 1491 if (html->timer == 0) |
| 1492 { | |
| 1 | 1493 html->timer = gtk_timeout_add(100, |
| 12 | 1494 (GtkFunction) scroll_timeout, |
| 1495 html); | |
| 1 | 1496 if (y < 0) |
| 1497 diff = y / 2; | |
| 1498 else | |
| 1499 diff = (y - height) / 2; | |
| 1500 | |
| 1501 if (html->vadj->value + diff > | |
| 12 | 1502 html->vadj->upper - height + 20) |
| 1 | 1503 gtk_adjustment_set_value(html->vadj, |
| 12 | 1504 html->vadj->upper - height + |
| 1505 20); | |
| 1 | 1506 else |
| 1507 gtk_adjustment_set_value(html->vadj, | |
| 12 | 1508 html->vadj->value + diff); |
| 1 | 1509 |
| 1510 } | |
| 1511 } | |
| 12 | 1512 |
| 1 | 1513 if (html->selected_text != NULL) |
| 1514 tmp = g_strdup(html->selected_text); | |
| 1515 do_select(html, realx, realy); | |
| 12 | 1516 if (tmp) |
| 1517 { | |
| 1518 if (!html->selected_text || strcmp(tmp, html->selected_text)) | |
| 1519 { | |
| 1 | 1520 GtkHtmlBit *hb; |
| 1521 GList *hbits = html->html_bits; | |
| 12 | 1522 while (hbits) |
| 1523 { | |
| 1524 hb = (GtkHtmlBit *) hbits->data; | |
| 1 | 1525 if (hb->was_selected) |
| 1526 gtk_html_draw_bit(html, hb, 0); | |
| 1527 hbits = hbits->next; | |
| 1528 } | |
| 1529 } | |
| 1530 g_free(tmp); | |
| 1531 } | |
| 1532 } | |
| 12 | 1533 } |
| 1534 else | |
| 1535 { | |
| 1 | 1536 GtkHtmlBit *hb; |
| 1537 GList *urls; | |
| 1538 | |
| 1539 urls = html->urls; | |
| 12 | 1540 while (urls) |
| 1541 { | |
| 1542 hb = (GtkHtmlBit *) urls->data; | |
| 1 | 1543 if ((realx > hb->x && realx < (hb->x + hb->width)) && |
| 12 | 1544 (realy < hb->y && realy > (hb->y - hb->height))) |
| 1545 { | |
| 26 | 1546 GdkCursor *cursor = NULL; |
| 1547 | |
| 12 | 1548 if (html->tooltip_hb != hb) |
| 1549 { | |
| 1 | 1550 html->tooltip_hb = hb; |
| 1551 if (html->tooltip_timer != -1) | |
| 1552 gtk_timeout_remove(html->tooltip_timer); | |
| 12 | 1553 if (html->tooltip_window) |
| 1554 { | |
| 1 | 1555 gtk_widget_destroy(html->tooltip_window); |
| 1556 html->tooltip_window = NULL; | |
| 1557 } | |
| 12 | 1558 html->tooltip_timer = |
| 1559 gtk_timeout_add(HTML_TOOLTIP_DELAY, | |
| 1560 gtk_html_tooltip_timeout, html); | |
| 1 | 1561 } |
| 26 | 1562 |
| 1563 cursor = gdk_cursor_new(GDK_HAND2); | |
| 1564 gdk_window_set_cursor(html->html_area, cursor); | |
| 1565 gdk_cursor_destroy(cursor); | |
| 1566 | |
| 1 | 1567 return TRUE; |
| 1568 } | |
| 12 | 1569 urls = urls->next; |
| 1 | 1570 } |
| 1571 if (html->tooltip_timer != -1) | |
| 1572 gtk_timeout_remove(html->tooltip_timer); | |
| 12 | 1573 if (html->tooltip_window) |
| 1574 { | |
| 1 | 1575 gtk_widget_destroy(html->tooltip_window); |
| 1576 html->tooltip_window = NULL; | |
| 1577 } | |
| 12 | 1578 |
| 1579 | |
| 1580 html->tooltip_hb = NULL; | |
| 1 | 1581 gdk_window_set_cursor(html->html_area, NULL); |
| 1582 | |
| 1583 | |
| 1584 } | |
| 1585 | |
| 1586 return TRUE; | |
| 1587 } | |
| 1588 | |
| 12 | 1589 static gint gtk_html_button_release(GtkWidget * widget, GdkEventButton * event) |
| 1 | 1590 { |
| 12 | 1591 GtkHtml *html; |
| 1592 | |
| 1593 html = GTK_HTML(widget); | |
| 1594 | |
| 1595 if (html->frozen > 0) | |
| 1596 return TRUE; | |
| 1597 | |
| 1598 if (event->button == 1) | |
| 1599 { | |
| 1600 int realx, | |
| 1601 realy; | |
| 1602 GtkHtmlBit *hb; | |
| 1603 GList *urls = html->urls; | |
| 1604 | |
| 1605 realx = event->x; | |
| 1606 realy = event->y + html->yoffset; | |
| 1607 if (realx != html->start_sel_x || realy != html->start_sel_y) | |
| 1608 { | |
| 1609 if (gtk_selection_owner_set(widget, | |
| 1610 GDK_SELECTION_PRIMARY, event->time)) | |
| 1611 { | |
| 1612 } | |
| 1613 else | |
| 1614 { | |
| 1615 } | |
| 1616 } | |
| 1617 else | |
| 1618 { | |
| 1619 if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == | |
| 1620 widget->window) | |
| 1 | 1621 gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, |
| 12 | 1622 event->time); |
| 1623 | |
| 1624 | |
| 1625 while (urls) | |
| 1626 { | |
| 1627 void open_url_nw(GtkWidget * w, char *url); | |
| 1628 hb = (GtkHtmlBit *) urls->data; | |
| 1 | 1629 if ((realx > hb->x && realx < (hb->x + hb->width)) && |
| 12 | 1630 (realy < hb->y && realy > (hb->y - hb->height))) |
| 1631 { | |
| 1632 open_url_nw(NULL, hb->url); | |
| 1633 // else | |
| 1634 // open_url(NULL, hb->url); | |
| 1 | 1635 break; |
| 1636 } | |
| 1637 urls = urls->next; | |
| 1638 } | |
| 1639 } | |
| 1640 } | |
| 1641 return TRUE; | |
| 1642 } | |
| 1643 | |
| 1644 | |
| 1645 | |
| 12 | 1646 static gint gtk_html_button_press(GtkWidget * widget, GdkEventButton * event) |
| 1 | 1647 { |
| 12 | 1648 GtkHtml *html; |
| 1649 gfloat value; | |
| 1650 | |
| 1651 | |
| 1652 html = GTK_HTML(widget); | |
| 1653 value = html->vadj->value; | |
| 1654 | |
| 1655 if (html->frozen > 0) | |
| 1656 return TRUE; | |
| 1657 | |
| 1658 if (event->button == 4) | |
| 1659 { | |
| 1 | 1660 value -= html->vadj->step_increment; |
| 1661 if (value < html->vadj->lower) | |
| 1662 value = html->vadj->lower; | |
| 12 | 1663 gtk_adjustment_set_value(html->vadj, value); |
| 1664 } | |
| 1665 else if (event->button == 5) | |
| 1666 { | |
| 1 | 1667 value += html->vadj->step_increment; |
| 1668 if (value > html->vadj->upper) | |
| 1669 value = html->vadj->upper; | |
| 12 | 1670 gtk_adjustment_set_value(html->vadj, value); |
| 1671 | |
| 1672 } | |
| 1673 else if (event->button == 1) | |
| 1674 { | |
| 1675 GList *hbits = g_list_last(html->html_bits); | |
| 1676 int realx, | |
| 1677 realy; | |
| 1 | 1678 GtkHtmlBit *hb; |
| 1679 | |
| 1680 realx = event->x; | |
| 1681 realy = event->y + html->yoffset; | |
| 1682 | |
| 1683 html->start_sel_x = realx; | |
| 1684 html->start_sel_y = realy; | |
| 1685 | |
| 1686 if (!hbits) | |
| 1687 return TRUE; | |
| 1688 | |
| 12 | 1689 if (html->selected_text) |
| 1690 { | |
| 1 | 1691 g_free(html->selected_text); |
| 1692 html->selected_text = NULL; | |
| 1693 html->start_sel = NULL; | |
| 1694 html->end_sel = NULL; | |
| 1695 html->num_start = 0; | |
| 1696 html->num_end = 0; | |
| 12 | 1697 while (hbits) |
| 1698 { | |
| 1699 hb = (GtkHtmlBit *) hbits->data; | |
| 1 | 1700 if (hb->was_selected) |
| 1701 gtk_html_draw_bit(html, hb, 1); | |
| 1702 hbits = hbits->prev; | |
| 1703 } | |
| 1704 hbits = g_list_last(html->html_bits); | |
| 1705 } | |
| 1706 | |
| 12 | 1707 hb = (GtkHtmlBit *) hbits->data; |
| 1708 if (realy > hb->y) | |
| 1709 { | |
| 1 | 1710 if (hb->text) |
| 1711 html->num_start = strlen(hb->text) - 1; | |
| 1712 else | |
| 12 | 1713 html->num_start = 0; |
| 1 | 1714 html->start_sel = hb; |
| 12 | 1715 } |
| 1716 else | |
| 1717 while (hbits) | |
| 1718 { | |
| 1719 hb = (GtkHtmlBit *) hbits->data; | |
| 1720 if ((realy < hb->y && realy > (hb->y - hb->height)) && | |
| 1721 (realx > hb->x + hb->width)) | |
| 1722 { | |
| 1723 if (hb->type != HTML_BIT_TEXT) | |
| 1724 { | |
| 1725 html->num_end = 0; | |
| 1726 html->end_sel = hb; | |
| 1727 break; | |
| 1728 } | |
| 1729 | |
| 1730 if (hb->text) | |
| 1731 html->num_start = strlen(hb->text) - 1; | |
| 1732 else | |
| 1733 html->num_start = 0; | |
| 1734 | |
| 1735 html->start_sel = hb; | |
| 1 | 1736 break; |
| 1737 } | |
| 12 | 1738 else if ((realx > hb->x && realx < (hb->x + hb->width)) && |
| 1739 (realy < hb->y && realy > (hb->y - hb->height))) | |
| 1740 { | |
| 1741 int i, | |
| 1742 len; | |
| 1743 int w = realx - hb->x; | |
| 1744 | |
| 1745 if (hb->type != HTML_BIT_TEXT) | |
| 1746 { | |
| 1747 html->num_end = 0; | |
| 1748 html->end_sel = hb; | |
| 1749 break; | |
| 1750 } | |
| 1751 | |
| 1752 if (hb->text) | |
| 1753 len = strlen(hb->text); | |
| 1754 else | |
| 1755 len = 0; | |
| 1756 | |
| 1757 for (i = 1; i <= len; i++) | |
| 1758 { | |
| 1759 if (gdk_text_measure(hb->font, hb->text, i) > w) | |
| 1760 { | |
| 1761 html->num_start = i - 1; | |
| 1762 html->start_sel = hb; | |
| 1763 break; | |
| 1764 } | |
| 1765 } | |
| 1 | 1766 break; |
| 1767 } | |
| 12 | 1768 hbits = hbits->prev; |
| 1 | 1769 } |
| 12 | 1770 } |
| 1771 else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) | |
| 1772 { | |
| 1 | 1773 GtkHtmlBit *hb = NULL; |
| 12 | 1774 int realx, |
| 1775 realy; | |
| 1776 GList *urls; | |
| 1777 | |
| 1 | 1778 realx = event->x; |
| 1779 realy = event->y + html->yoffset; | |
| 12 | 1780 |
| 1 | 1781 urls = html->urls; |
| 12 | 1782 while (urls) |
| 1783 { | |
| 1784 hb = (GtkHtmlBit *) urls->data; | |
| 1 | 1785 if ((realx > hb->x && realx < (hb->x + hb->width)) && |
| 12 | 1786 (realy < hb->y && realy > (hb->y - hb->height))) |
| 1787 { | |
| 1 | 1788 break; |
| 1789 } | |
| 12 | 1790 urls = urls->next; |
| 1 | 1791 hb = NULL; |
| 1792 } | |
| 12 | 1793 |
| 1794 if (hb != NULL) | |
| 1795 { | |
| 69 | 1796 |
| 1797 GtkWidget *menu, *button; | |
| 1798 | |
| 1799 menu = gtk_menu_new(); | |
| 1800 | |
| 1801 if (web_browser == BROWSER_NETSCAPE) { | |
| 1802 | |
|
353
a4df8f1cc61a
[gaim-migrate @ 363]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
349
diff
changeset
|
1803 button = gtk_menu_item_new_with_label(_("Open URL in existing window")); |
| 69 | 1804 gtk_signal_connect(GTK_OBJECT(button), "activate", |
| 1805 GTK_SIGNAL_FUNC(open_url), hb->url); | |
| 1806 gtk_menu_append(GTK_MENU(menu), button); | |
| 1807 gtk_widget_show(button); | |
| 1808 | |
| 1809 } | |
| 1810 | |
| 1811 | |
|
353
a4df8f1cc61a
[gaim-migrate @ 363]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
349
diff
changeset
|
1812 button = gtk_menu_item_new_with_label(_("Open URL in new window")); |
| 69 | 1813 gtk_signal_connect(GTK_OBJECT(button), "activate", |
| 1814 GTK_SIGNAL_FUNC(open_url_nw), hb->url); | |
| 1815 gtk_menu_append(GTK_MENU(menu), button); | |
| 1816 gtk_widget_show(button); | |
| 1817 | |
| 1818 if (web_browser == BROWSER_NETSCAPE) { | |
| 1819 | |
|
353
a4df8f1cc61a
[gaim-migrate @ 363]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
349
diff
changeset
|
1820 button = gtk_menu_item_new_with_label(_("Add URL as bookmark")); |
| 69 | 1821 gtk_signal_connect(GTK_OBJECT(button), "activate", |
| 1822 GTK_SIGNAL_FUNC(add_bookmark), hb->url); | |
| 1823 gtk_menu_append(GTK_MENU(menu), button); | |
| 1824 gtk_widget_show(button); | |
| 1825 | |
| 1826 } | |
| 1827 | |
| 1828 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
| 1829 event->button, event->time); | |
| 1830 | |
| 12 | 1831 } |
| 1 | 1832 } |
| 12 | 1833 |
| 1 | 1834 return TRUE; |
| 1835 } | |
| 1836 | |
| 1837 | |
| 12 | 1838 static void gtk_html_draw_bit(GtkHtml * html, GtkHtmlBit * hb, int redraw) |
| 1 | 1839 { |
| 12 | 1840 int mypos, |
| 1841 epos, | |
| 1842 spos; | |
| 1843 GdkGC *gc = html->gc; | |
| 1 | 1844 int shift; |
| 12 | 1845 GtkStateType selected_state; |
| 1846 GtkWidget *widget = GTK_WIDGET(html); | |
| 1 | 1847 GdkRectangle area; |
| 1848 | |
| 1849 if (html->frozen > 0) | |
| 1850 return; | |
| 1851 | |
| 12 | 1852 if (hb->type == HTML_BIT_TEXT) |
| 1853 { | |
| 1 | 1854 |
| 716 | 1855 if (!(hb->text)) |
| 1 | 1856 return; |
|
720
8b3412f3ac2a
[gaim-migrate @ 730]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
716
diff
changeset
|
1857 /* this is possible, don't comment it out >:P */ |
|
8b3412f3ac2a
[gaim-migrate @ 730]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
716
diff
changeset
|
1858 if (!strlen(hb->text)) |
|
8b3412f3ac2a
[gaim-migrate @ 730]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
716
diff
changeset
|
1859 return; |
| 12 | 1860 |
| 1 | 1861 mypos = g_list_index(html->html_bits, hb); |
| 1862 epos = g_list_index(html->html_bits, html->end_sel); | |
| 1863 spos = g_list_index(html->html_bits, html->start_sel); | |
| 1864 | |
| 12 | 1865 if (((html->end_sel == NULL) || (html->start_sel == NULL)) || |
| 1866 ((epos < mypos) && (spos < mypos)) || | |
| 1867 ((epos > mypos) && (spos > mypos))) | |
| 1868 { | |
| 1869 selected_state = GTK_STATE_NORMAL; | |
| 1870 } | |
| 1871 else | |
| 1872 { | |
| 1 | 1873 selected_state = GTK_STATE_SELECTED; |
| 1874 } | |
| 1875 | |
| 1876 | |
| 1877 gdk_text_extents(hb->font, hb->text, 1, &shift, NULL, NULL, NULL, NULL); | |
| 1878 | |
| 12 | 1879 if (selected_state == GTK_STATE_SELECTED) |
| 1880 { | |
| 1881 int schar = 0, | |
| 1882 echar = 0; | |
| 1883 int startx = 0, | |
| 1884 xwidth = 0; | |
| 1885 | |
| 1886 if (epos > spos || | |
| 1887 (epos == spos && html->num_end >= html->num_start)) | |
| 1888 { | |
| 1889 if (mypos == epos) | |
| 1890 { | |
| 1 | 1891 echar = html->num_end; |
| 12 | 1892 xwidth = |
| 1893 gdk_text_width(hb->font, hb->text, html->num_end + 1); | |
| 1894 } | |
| 1895 else | |
| 1896 { | |
| 1 | 1897 echar = strlen(hb->text); |
| 1898 xwidth = hb->width; | |
| 1899 } | |
| 12 | 1900 if (mypos == spos) |
| 1901 { | |
| 1 | 1902 schar = html->num_start; |
| 12 | 1903 startx = |
| 1904 gdk_text_width(hb->font, hb->text, html->num_start); | |
| 1 | 1905 xwidth -= startx; |
| 1906 } | |
| 12 | 1907 } |
| 1908 else | |
| 1909 { | |
| 1910 if (mypos == spos) | |
| 1911 { | |
| 1 | 1912 echar = html->num_start; |
| 12 | 1913 xwidth = |
| 1914 gdk_text_width(hb->font, hb->text, | |
| 1915 html->num_start + 1); | |
| 1916 } | |
| 1917 else | |
| 1918 { | |
| 1 | 1919 echar = strlen(hb->text); |
| 1920 xwidth = hb->width; | |
| 1921 } | |
| 12 | 1922 if (mypos == epos) |
| 1923 { | |
| 1 | 1924 schar = html->num_end; |
| 12 | 1925 startx = |
| 1926 gdk_text_width(hb->font, hb->text, html->num_end); | |
| 1 | 1927 xwidth -= startx; |
| 1928 } | |
| 1929 } | |
| 1930 | |
| 1931 if (!redraw && echar == hb->sel_e && schar == hb->sel_s) | |
| 1932 return; | |
| 12 | 1933 |
| 1 | 1934 hb->sel_e = echar; |
| 1935 hb->sel_s = schar; | |
| 12 | 1936 |
| 1 | 1937 startx += hb->x; |
| 1938 | |
| 1939 | |
| 12 | 1940 area.x = hb->x - html->xoffset; |
| 1941 area.y = hb->y - hb->height + 3 - html->yoffset; | |
| 1942 area.width = hb->width + 2; | |
| 1943 area.height = hb->height; | |
| 1944 clear_area(html, &area); | |
| 1945 | |
| 1946 gtk_paint_flat_box(widget->style, html->html_area, | |
| 1947 selected_state, GTK_SHADOW_NONE, | |
| 1948 NULL, widget, "text", | |
| 1949 startx, | |
| 1950 hb->y - hb->height + 3 - html->yoffset, | |
| 1951 xwidth + 2, hb->height); | |
| 1952 hb->was_selected = 1; | |
| 1953 } | |
| 1954 else if (hb->was_selected) | |
| 1955 { | |
| 1956 area.x = hb->x - html->xoffset; | |
| 1957 area.y = hb->y - hb->height + 3 - html->yoffset; | |
| 1958 area.width = hb->width + 2; | |
| 1959 area.height = hb->height; | |
| 1960 clear_area(html, &area); | |
| 1961 | |
| 1962 hb->sel_e = -1; | |
| 1963 hb->sel_s = -1; | |
| 1964 | |
| 1 | 1965 hb->was_selected = 0; |
| 1966 } | |
| 12 | 1967 |
| 1968 | |
| 1969 | |
| 1970 | |
| 1971 if (selected_state == GTK_STATE_SELECTED && (mypos == epos | |
| 1972 || mypos == spos)) | |
| 1973 { | |
| 1 | 1974 char *s = hb->text; |
| 12 | 1975 int num = 0, |
| 1976 width = 0, | |
| 1977 fsel = 0, | |
| 1978 esel = strlen(hb->text); | |
| 1979 int lbearing, | |
| 1980 rbearing, | |
| 1981 w; | |
| 1982 | |
| 1983 if (epos > spos || | |
| 1984 (epos == spos && html->num_end >= html->num_start)) | |
| 1985 { | |
| 1 | 1986 if (mypos == epos) |
| 1987 esel = html->num_end; | |
| 1988 if (mypos == spos) | |
| 1989 fsel = html->num_start; | |
| 12 | 1990 } |
| 1991 else | |
| 1992 { | |
| 1 | 1993 if (mypos == spos) |
| 1994 esel = html->num_start; | |
| 12 | 1995 if (mypos == epos) |
| 1996 fsel = html->num_end; | |
| 1 | 1997 } |
| 1998 | |
| 12 | 1999 while (*s) |
| 2000 { | |
| 1 | 2001 |
| 2002 if (num < fsel || num > esel) | |
| 2003 selected_state = GTK_STATE_NORMAL; | |
| 2004 else | |
| 2005 selected_state = GTK_STATE_SELECTED; | |
| 2006 if (hb->fore != NULL) | |
| 2007 gdk_gc_set_foreground(gc, hb->fore); | |
| 2008 else | |
| 12 | 2009 gdk_gc_set_foreground(gc, |
| 2010 &widget->style->fg[selected_state]); | |
| 1 | 2011 if (hb->back != NULL) |
| 2012 gdk_gc_set_background(gc, hb->back); | |
| 2013 else | |
| 12 | 2014 gdk_gc_set_background(gc, |
| 2015 &widget->style->bg[selected_state]); | |
| 1 | 2016 |
| 2017 | |
| 2018 gdk_gc_set_font(gc, hb->font); | |
| 2019 | |
| 12 | 2020 gdk_text_extents(hb->font, s, 1, &lbearing, &rbearing, &w, NULL, |
| 2021 NULL); | |
| 2022 | |
| 2023 gdk_draw_text(html->html_area, hb->font, gc, | |
| 2024 shift + hb->x + width, hb->y - html->yoffset, s, | |
| 2025 1); | |
| 2026 | |
| 2027 if (hb->uline) | |
| 2028 gdk_draw_line(html->html_area, gc, shift + hb->x + width, | |
| 2029 hb->y - html->yoffset, | |
| 2030 shift + hb->x + width + w, | |
| 2031 hb->y - html->yoffset); | |
| 1 | 2032 |
| 2033 if (hb->strike) | |
| 12 | 2034 gdk_draw_line(html->html_area, gc, shift + hb->x + width, |
| 2035 hb->y - html->yoffset - (hb->height / 3), | |
| 2036 shift + hb->x + width + w, | |
| 2037 hb->y - html->yoffset - (hb->height / 3)); | |
| 1 | 2038 |
| 2039 width += w; | |
| 12 | 2040 |
| 1 | 2041 s++; |
| 2042 num++; | |
| 2043 } | |
| 2044 | |
| 2045 | |
| 12 | 2046 } |
| 2047 else | |
| 2048 { | |
| 2049 /*my stuff here*/ | |
| 2050 | |
| 2051 if(!hb->was_selected) | |
| 2052 { | |
| 2053 area.x = hb->x - html->xoffset; | |
| 2054 area.y = hb->y - hb->height + 3 - html->yoffset; | |
| 2055 area.width = hb->width + 2; | |
| 2056 area.height = hb->height; | |
| 2057 clear_area(html, &area); | |
| 2058 } | |
| 2059 | |
| 2060 /*end my stuff*/ | |
| 2061 | |
| 1 | 2062 |
|
674
b68c592829a6
[gaim-migrate @ 684]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
669
diff
changeset
|
2063 if (hb->text && hb->back != NULL && selected_state != GTK_STATE_SELECTED) { |
|
635
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2064 int wid = gdk_string_width(hb->font, hb->text), |
|
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2065 hei = gdk_text_height(hb->font, "C", 1); |
|
629
ce8d8608d05b
[gaim-migrate @ 639]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
627
diff
changeset
|
2066 gdk_gc_set_foreground(gc, hb->back); |
|
635
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2067 gdk_draw_rectangle(html->html_area, gc, TRUE /* filled */, |
|
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2068 shift + hb->x, |
|
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2069 hb->y - html->yoffset - hei - 5, |
|
2ad1a8234ef1
[gaim-migrate @ 645]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
632
diff
changeset
|
2070 wid, hei + hei); |
|
629
ce8d8608d05b
[gaim-migrate @ 639]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
627
diff
changeset
|
2071 } |
|
ce8d8608d05b
[gaim-migrate @ 639]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
627
diff
changeset
|
2072 |
| 1 | 2073 if (hb->fore != NULL) |
| 2074 gdk_gc_set_foreground(gc, hb->fore); | |
| 2075 else | |
| 12 | 2076 gdk_gc_set_foreground(gc, &widget->style->fg[selected_state]); |
| 1 | 2077 if (hb->back != NULL) |
| 2078 gdk_gc_set_background(gc, hb->back); | |
| 2079 else | |
| 2080 gdk_gc_set_background(gc, &widget->style->bg[selected_state]); | |
| 2081 | |
| 2082 | |
| 2083 gdk_gc_set_font(gc, hb->font); | |
| 2084 | |
| 12 | 2085 |
| 2086 gdk_draw_string(html->html_area, hb->font, gc, shift + hb->x, | |
| 2087 hb->y - html->yoffset, hb->text); | |
| 1 | 2088 if (hb->uline) |
| 12 | 2089 gdk_draw_line(html->html_area, gc, shift + hb->x, |
| 2090 hb->y - html->yoffset, | |
| 2091 hb->x + gdk_string_measure(hb->font, hb->text), | |
| 2092 hb->y - html->yoffset); | |
| 1 | 2093 |
| 2094 if (hb->strike) | |
| 12 | 2095 gdk_draw_line(html->html_area, gc, shift + hb->x, |
| 2096 hb->y - html->yoffset - (hb->height / 3), | |
| 2097 hb->x + gdk_string_measure(hb->font, hb->text), | |
| 2098 hb->y - html->yoffset - (hb->height / 3)); | |
| 1 | 2099 |
| 2100 } | |
| 12 | 2101 } |
| 2102 else if (hb->type == HTML_BIT_SEP) | |
| 2103 { | |
| 2104 | |
| 2105 gdk_draw_line(html->html_area, gc, hb->x + 2, | |
| 2106 hb->y - html->yoffset - (hb->height / 2 - 1), | |
| 2107 hb->x + hb->width, | |
| 2108 hb->y - html->yoffset - (hb->height / 2 - 1)); | |
| 2109 | |
| 2110 } | |
| 2111 else if (hb->type == HTML_BIT_PIXMAP) | |
| 2112 { | |
| 1 | 2113 gdk_gc_set_background(gc, &widget->style->base[GTK_STATE_NORMAL]); |
| 12 | 2114 gdk_draw_pixmap(html->html_area, gc, hb->pm, 0, 0, hb->x, |
|
492
56399273ed8d
[gaim-migrate @ 502]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
481
diff
changeset
|
2115 hb->y - html->yoffset - (hb->height) + 4, -1, -1); |
| 1 | 2116 } |
| 2117 } | |
| 2118 | |
| 2119 | |
| 2120 | |
| 12 | 2121 gint compare_types(GtkHtmlBit * hb, GtkHtmlBit * hb2) |
| 1 | 2122 { |
| 12 | 2123 /* |
| 2124 * In this function, it's OK to accidently return a | |
| 2125 * * 0, but will cause problems on an accidental 1 | |
| 2126 */ | |
| 1 | 2127 |
| 2128 if (!hb || !hb2) | |
| 2129 return 0; | |
| 12 | 2130 |
| 2131 | |
| 1 | 2132 if (hb->uline != hb2->uline) |
| 2133 return 0; | |
| 2134 if (hb->strike != hb2->strike) | |
| 12 | 2135 return 0; |
| 2136 if (hb->font && hb2->font) | |
| 2137 { | |
| 1 | 2138 if (!gdk_font_equal(hb->font, hb2->font)) |
| 2139 return 0; | |
| 12 | 2140 } |
| 2141 else if (hb->font && !hb2->font) | |
| 2142 { | |
| 1 | 2143 return 0; |
| 12 | 2144 } |
| 2145 else if (!hb->font && hb2->font) | |
| 2146 { | |
| 1 | 2147 return 0; |
| 2148 } | |
| 2149 if (hb->type != hb2->type) | |
| 2150 return 0; | |
| 12 | 2151 |
| 2152 if (hb->fore && hb2->fore) | |
| 2153 { | |
| 1 | 2154 if (!gdk_color_equal(hb->fore, hb2->fore)) |
| 2155 return 0; | |
| 12 | 2156 } |
| 2157 else if (hb->fore && !hb2->fore) | |
| 2158 { | |
| 1 | 2159 return 0; |
| 12 | 2160 } |
| 2161 else if (!hb->fore && hb2->fore) | |
| 2162 { | |
| 1 | 2163 return 0; |
| 2164 } | |
| 2165 | |
| 12 | 2166 if (hb->back && hb2->back) |
| 2167 { | |
| 1 | 2168 if (!gdk_color_equal(hb->back, hb2->back)) |
| 2169 return 0; | |
| 12 | 2170 } |
| 2171 else if (hb->back && !hb2->back) | |
| 2172 { | |
| 1 | 2173 return 0; |
| 12 | 2174 } |
| 2175 else if (!hb->back && hb2->back) | |
| 2176 { | |
| 1 | 2177 return 0; |
| 2178 } | |
| 2179 | |
| 2180 if ((hb->url != NULL && hb2->url == NULL) || | |
| 12 | 2181 (hb->url == NULL && hb2->url != NULL)) |
| 1 | 2182 return 0; |
| 12 | 2183 |
| 2184 if (hb->url != NULL && hb2->url != NULL) | |
| 1 | 2185 if (strcasecmp(hb->url, hb2->url)) |
| 2186 return 0; | |
| 12 | 2187 |
| 1 | 2188 return 1; |
| 2189 } | |
| 2190 | |
| 12 | 2191 static gint html_bit_is_onscreen(GtkHtml * html, GtkHtmlBit * hb) |
| 1 | 2192 { |
| 12 | 2193 gint width, |
| 2194 height; | |
| 1 | 2195 |
| 2196 gdk_window_get_size(html->html_area, &width, &height); | |
| 12 | 2197 |
| 2198 if (hb->y < html->yoffset) | |
| 2199 { | |
| 1 | 2200 return 0; |
| 2201 } | |
| 2202 | |
| 12 | 2203 if ((hb->y - hb->height) > (html->yoffset + height)) |
| 2204 { | |
| 1 | 2205 return 0; |
| 2206 } | |
| 2207 return 1; | |
| 2208 } | |
| 2209 | |
| 12 | 2210 static void draw_cursor(GtkHtml * html) |
| 1 | 2211 { |
| 12 | 2212 if (html->editable && |
| 2213 html->cursor_hb && | |
| 2214 GTK_WIDGET_DRAWABLE(html) && | |
| 2215 html_bit_is_onscreen(html, html->cursor_hb)) | |
| 2216 { | |
| 2217 gint x, | |
| 2218 y; | |
| 1 | 2219 gint width; |
| 2220 | |
| 2221 GdkFont *font = html->cursor_hb->font; | |
| 2222 | |
| 12 | 2223 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL, |
| 2224 NULL, &width, NULL, NULL); | |
| 2225 | |
| 2226 gdk_gc_set_foreground(html->gc, | |
| 2227 >K_WIDGET(html)->style->text[GTK_STATE_NORMAL]); | |
| 1 | 2228 |
| 2229 y = html->cursor_hb->y - html->yoffset; | |
| 2230 x = html->cursor_hb->x + width; | |
| 2231 | |
| 2232 | |
| 12 | 2233 gdk_draw_line(html->html_area, html->gc, x, y, x, y - font->ascent); |
| 1 | 2234 |
| 2235 } | |
| 2236 } | |
| 2237 | |
| 12 | 2238 static void undraw_cursor(GtkHtml * html) |
| 1 | 2239 { |
| 12 | 2240 if (html->editable && |
| 2241 html->cursor_hb && | |
| 2242 GTK_WIDGET_DRAWABLE(html) && | |
| 2243 html_bit_is_onscreen(html, html->cursor_hb)) | |
| 2244 { | |
| 2245 gint x, | |
| 2246 y; | |
| 1 | 2247 gint width; |
| 12 | 2248 GdkRectangle area; |
| 2249 | |
| 1 | 2250 GdkFont *font = html->cursor_hb->font; |
| 2251 | |
| 12 | 2252 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL, |
| 2253 NULL, &width, NULL, NULL); | |
| 1 | 2254 |
| 2255 y = html->cursor_hb->y - html->yoffset; | |
| 2256 x = html->cursor_hb->x + width; | |
| 2257 | |
| 2258 area.x = x; | |
| 2259 area.y = y - font->ascent; | |
| 2260 area.height = font->ascent + 1; | |
| 2261 area.width = 1; | |
| 2262 | |
| 2263 | |
| 12 | 2264 clear_area(html, &area); |
| 1 | 2265 |
| 2266 gtk_html_draw_bit(html, html->cursor_hb, 1); | |
| 12 | 2267 |
| 2268 | |
| 2269 } | |
| 1 | 2270 } |
| 2271 | |
| 2272 | |
| 12 | 2273 static void expose_html(GtkHtml * html, GdkRectangle * area, gboolean cursor) |
| 1 | 2274 { |
| 12 | 2275 GList *hbits; |
| 2276 GtkHtmlBit *hb; | |
| 2277 gint width, | |
| 2278 height; | |
| 2279 gint realy; | |
| 2280 | |
| 2281 | |
| 2282 if (html->frozen > 0) | |
| 2283 return; | |
| 2284 | |
| 2285 | |
| 2286 hbits = html->html_bits; | |
| 1 | 2287 |
| 2288 gdk_window_get_size(html->html_area, &width, &height); | |
| 2289 | |
| 12 | 2290 realy = area->y + html->yoffset; |
| 2291 | |
| 2292 clear_area(html, area); | |
| 2293 | |
| 2294 while (hbits) | |
| 2295 { | |
| 2296 | |
| 2297 hb = (GtkHtmlBit *) hbits->data; | |
| 1 | 2298 |
| 2299 if (html_bit_is_onscreen(html, hb)) | |
| 12 | 2300 gtk_html_draw_bit(html, hb, 1); |
| 2301 | |
| 2302 | |
| 2303 hbits = hbits->next; | |
| 2304 } | |
| 1 | 2305 } |
| 2306 | |
| 12 | 2307 static void resize_html(GtkHtml * html) |
| 1 | 2308 { |
| 2309 GList *hbits = html->html_bits; | |
| 2310 GList *html_bits = html->html_bits; | |
| 12 | 2311 GtkHtmlBit *hb, |
| 2312 *hb2; | |
| 1 | 2313 char *str; |
| 2314 gint height; | |
| 2315 | |
| 12 | 2316 if (!hbits) |
| 2317 return; | |
| 2318 | |
| 2319 | |
| 2320 html->html_bits = NULL; | |
| 2321 | |
| 2322 html->current_x = 0; | |
| 1 | 2323 html->current_y = 0; |
| 2324 | |
| 12 | 2325 html->vadj->upper = 0; |
| 2326 | |
| 2327 gtk_html_freeze(html); | |
| 2328 | |
| 2329 while (hbits) | |
| 2330 { | |
| 2331 hb = (GtkHtmlBit *) hbits->data; | |
| 2332 if (hb->type == HTML_BIT_SEP) | |
| 2333 { | |
| 2334 | |
| 1 | 2335 gtk_html_add_seperator(html); |
| 2336 | |
| 2337 g_free(hb); | |
| 2338 | |
| 2339 hbits = hbits->next; | |
| 2340 continue; | |
| 2341 } | |
| 12 | 2342 if (hb->type == HTML_BIT_PIXMAP) |
| 2343 { | |
| 1 | 2344 |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2345 gtk_html_add_pixmap(html, hb->pm, hb->fit, hb->newline); |
| 1 | 2346 |
| 2347 g_free(hb); | |
| 2348 | |
| 2349 hbits = hbits->next; | |
| 2350 continue; | |
| 2351 } | |
| 12 | 2352 |
| 2353 if (hb->newline) | |
| 2354 { | |
| 1 | 2355 int i; |
| 2356 | |
| 12 | 2357 if (!hb->text) |
| 2358 { | |
| 1 | 2359 hb->text = g_malloc(1); |
| 2360 hb->text[0] = 0; | |
| 2361 } | |
| 12 | 2362 for (i = 0; i < hb->newline; i++) |
| 2363 { | |
| 2364 str = hb->text; | |
| 1 | 2365 hb->text = g_strconcat(str, "\n", NULL); |
|
506
58af37870fdd
[gaim-migrate @ 516]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
499
diff
changeset
|
2366 if (str) g_free(str); |
| 1 | 2367 } |
| 2368 } | |
| 2369 | |
| 12 | 2370 if (hbits->next) |
| 2371 { | |
| 2372 hb2 = (GtkHtmlBit *) hbits->next->data; | |
| 2373 } | |
| 2374 else | |
| 2375 { | |
| 2376 hb2 = NULL; | |
| 2377 } | |
| 2378 | |
| 2379 | |
| 2380 | |
| 2381 if (!hb->newline && compare_types(hb, hb2)) | |
| 2382 { | |
| 1 | 2383 str = hb2->text; |
| 2384 hb2->text = g_strconcat(hb->text, hb2->text, NULL); | |
|
537
d050f88321a1
[gaim-migrate @ 547]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
536
diff
changeset
|
2385 if (str) g_free(str); |
| 1 | 2386 hb2 = NULL; |
| 12 | 2387 } |
| 2388 else if (hb->text) | |
| 2389 { | |
| 1 | 2390 gtk_html_add_text(html, hb->font, hb->fore, hb->back, |
| 12 | 2391 hb->text, strlen(hb->text), hb->uline, hb->strike, |
| 2392 hb->url); | |
| 1 | 2393 } |
| 2394 | |
| 12 | 2395 |
| 2396 | |
| 2397 /* | |
| 2398 * Font stays, so do colors (segfaults if I free) | |
| 2399 */ | |
| 1 | 2400 if (hb->fore) |
| 2401 gdk_color_free(hb->fore); | |
| 2402 if (hb->back) | |
| 2403 gdk_color_free(hb->back); | |
| 2404 if (hb->text) | |
| 2405 g_free(hb->text); | |
| 2406 if (hb->url) | |
| 2407 g_free(hb->url); | |
| 2408 | |
| 12 | 2409 g_free(hb); |
| 1 | 2410 |
| 2411 hbits = hbits->next; | |
| 2412 } | |
| 2413 | |
| 12 | 2414 g_list_free(html_bits); |
| 2415 | |
| 2416 | |
| 2417 gtk_html_thaw(html); | |
| 2418 | |
| 1 | 2419 gdk_window_get_size(html->html_area, NULL, &height); |
| 12 | 2420 gtk_adjustment_set_value(html->vadj, html->vadj->upper - height); |
| 1 | 2421 |
| 2422 } | |
| 2423 | |
| 12 | 2424 static GdkGC *create_bg_gc(GtkHtml * html) |
| 1 | 2425 { |
| 12 | 2426 GdkGCValues values; |
| 2427 | |
| 2428 values.tile = GTK_WIDGET(html)->style->bg_pixmap[GTK_STATE_NORMAL]; | |
| 2429 values.fill = GDK_TILED; | |
| 2430 | |
| 2431 return gdk_gc_new_with_values(html->html_area, &values, | |
| 2432 GDK_GC_FILL | GDK_GC_TILE); | |
| 1 | 2433 } |
| 2434 | |
| 12 | 2435 static void clear_area(GtkHtml * html, GdkRectangle * area) |
| 1 | 2436 { |
| 12 | 2437 GtkWidget *widget = GTK_WIDGET(html); |
| 2438 gint x, | |
| 2439 y; | |
| 2440 | |
| 2441 | |
| 2442 if (html->transparent) | |
| 2443 { | |
| 1 | 2444 if (html->pm == NULL) |
| 2445 html->pm = get_desktop_pixmap(widget); | |
| 2446 | |
| 12 | 2447 if (html->pm == NULL) |
| 2448 return; | |
| 2449 | |
| 2450 if (html->bg_gc == NULL) | |
| 2451 { | |
| 2452 GdkGCValues values; | |
| 2453 | |
| 2454 values.tile = html->pm; | |
| 2455 values.fill = GDK_TILED; | |
| 2456 | |
| 2457 html->bg_gc = gdk_gc_new_with_values(html->html_area, &values, | |
| 2458 GDK_GC_FILL | GDK_GC_TILE); | |
| 2459 | |
| 2460 } | |
| 2461 | |
| 1 | 2462 gdk_window_get_deskrelative_origin(html->html_area, &x, &y); |
| 2463 | |
| 12 | 2464 gdk_draw_pixmap(html->html_area, html->bg_gc, html->pm, |
| 2465 x + area->x, y + area->y, area->x, area->y, area->width, | |
| 2466 area->height); | |
| 1 | 2467 |
| 2468 return; | |
| 2469 | |
| 2470 } | |
| 12 | 2471 if (html->bg_gc) |
| 2472 { | |
| 2473 | |
| 2474 gint width, | |
| 2475 height; | |
| 2476 | |
| 2477 gdk_window_get_size(widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, | |
| 2478 &height); | |
| 2479 | |
| 2480 gdk_gc_set_ts_origin(html->bg_gc, | |
| 2481 (-html->xoffset) % width, | |
| 2482 (-html->yoffset) % height); | |
| 2483 | |
| 2484 gdk_draw_rectangle(html->html_area, html->bg_gc, TRUE, | |
| 2485 area->x, area->y, area->width, area->height); | |
| 2486 } | |
| 2487 else | |
| 2488 gdk_window_clear_area(html->html_area, area->x, area->y, area->width, | |
| 2489 area->height); | |
| 1 | 2490 } |
| 2491 | |
| 2492 | |
| 2493 | |
| 2494 | |
| 12 | 2495 static void gtk_html_destroy(GtkObject * object) |
| 1 | 2496 { |
| 12 | 2497 GtkHtml *html; |
| 2498 | |
| 2499 g_return_if_fail(object != NULL); | |
| 2500 g_return_if_fail(GTK_IS_HTML(object)); | |
| 2501 | |
| 2502 html = (GtkHtml *) object; | |
| 2503 | |
| 2504 | |
| 2505 gtk_signal_disconnect_by_data(GTK_OBJECT(html->hadj), html); | |
| 2506 gtk_signal_disconnect_by_data(GTK_OBJECT(html->vadj), html); | |
| 2507 | |
| 2508 if (html->timer) | |
| 2509 { | |
| 2510 gtk_timeout_remove(html->timer); | |
| 2511 html->timer = 0; | |
| 1 | 2512 } |
| 2513 | |
| 12 | 2514 if (html->tooltip_timer) |
| 2515 { | |
| 2516 gtk_timeout_remove(html->tooltip_timer); | |
| 1 | 2517 html->tooltip_timer = -1; |
| 2518 } | |
| 2519 | |
| 12 | 2520 |
| 2521 GTK_OBJECT_CLASS(parent_class)->destroy(object); | |
| 2522 | |
| 1 | 2523 } |
| 2524 | |
| 12 | 2525 static void gtk_html_finalize(GtkObject * object) |
| 1 | 2526 { |
| 12 | 2527 GList *hbits; |
| 2528 GtkHtml *html; | |
| 1 | 2529 GtkHtmlBit *hb; |
| 2530 | |
| 2531 | |
| 12 | 2532 g_return_if_fail(object != NULL); |
| 2533 g_return_if_fail(GTK_IS_HTML(object)); | |
| 2534 | |
| 2535 html = (GtkHtml *) object; | |
| 2536 | |
| 2537 gtk_object_unref(GTK_OBJECT(html->hadj)); | |
| 2538 gtk_object_unref(GTK_OBJECT(html->vadj)); | |
| 2539 | |
| 2540 hbits = html->html_bits; | |
| 2541 | |
| 2542 while (hbits) | |
| 2543 { | |
| 2544 hb = (GtkHtmlBit *) hbits->data; | |
| 2545 if (hb->fore) | |
| 2546 gdk_color_free(hb->fore); | |
| 2547 if (hb->back) | |
| 2548 gdk_color_free(hb->back); | |
| 2549 if (hb->text) | |
| 2550 g_free(hb->text); | |
| 2551 if (hb->url) | |
| 2552 g_free(hb->url); | |
| 2553 if (hb->pm) | |
| 2554 gdk_pixmap_unref(hb->pm); | |
| 2555 | |
| 2556 g_free(hb); | |
| 2557 hbits = hbits->next; | |
| 2558 } | |
| 2559 if (html->html_bits) | |
| 2560 g_list_free(html->html_bits); | |
| 2561 | |
| 2562 if (html->urls) | |
| 2563 g_list_free(html->urls); | |
| 2564 | |
| 2565 if (html->selected_text) | |
| 2566 g_free(html->selected_text); | |
| 2567 | |
| 2568 if (html->gc) | |
| 2569 gdk_gc_destroy(html->gc); | |
| 2570 | |
| 2571 if (html->bg_gc) | |
| 2572 gdk_gc_destroy(html->bg_gc); | |
| 1 | 2573 |
| 2574 if (html->tooltip_window) | |
| 2575 gtk_widget_destroy(html->tooltip_window); | |
| 12 | 2576 |
| 2577 GTK_OBJECT_CLASS(parent_class)->finalize(object); | |
| 1 | 2578 } |
| 2579 | |
| 12 | 2580 static void gtk_html_realize(GtkWidget * widget) |
| 1 | 2581 { |
| 12 | 2582 GtkHtml *html; |
| 2583 GdkWindowAttr attributes; | |
| 2584 gint attributes_mask; | |
| 2585 | |
| 2586 g_return_if_fail(widget != NULL); | |
| 2587 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 2588 | |
| 2589 html = GTK_HTML(widget); | |
| 2590 GTK_WIDGET_SET_FLAGS(html, GTK_REALIZED); | |
| 2591 | |
| 2592 attributes.window_type = GDK_WINDOW_CHILD; | |
| 2593 attributes.x = widget->allocation.x; | |
| 2594 attributes.y = widget->allocation.y; | |
| 2595 attributes.width = widget->allocation.width; | |
| 2596 attributes.height = widget->allocation.height; | |
| 2597 attributes.wclass = GDK_INPUT_OUTPUT; | |
| 2598 attributes.visual = gtk_widget_get_visual(widget); | |
| 2599 attributes.colormap = gtk_widget_get_colormap(widget); | |
| 2600 attributes.event_mask = gtk_widget_get_events(widget); | |
| 2601 attributes.event_mask |= (GDK_EXPOSURE_MASK | | |
| 2602 GDK_BUTTON_PRESS_MASK | | |
| 2603 GDK_BUTTON_RELEASE_MASK | | |
| 2604 GDK_BUTTON_MOTION_MASK | | |
| 2605 GDK_ENTER_NOTIFY_MASK | | |
| 2606 GDK_LEAVE_NOTIFY_MASK | | |
| 2607 GDK_POINTER_MOTION_MASK | | |
| 2608 GDK_POINTER_MOTION_HINT_MASK | | |
| 2609 GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK); | |
| 2610 | |
| 2611 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; | |
| 2612 | |
| 2613 widget->window = | |
| 2614 gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, | |
| 2615 attributes_mask); | |
| 2616 gdk_window_set_user_data(widget->window, html); | |
| 2617 | |
| 2618 attributes.x = (widget->style->klass->xthickness + BORDER_WIDTH); | |
| 2619 attributes.y = (widget->style->klass->ythickness + BORDER_WIDTH); | |
| 2620 attributes.width = | |
| 2621 MAX(1, (gint) widget->allocation.width - (gint) attributes.x * 2); | |
| 2622 attributes.height = | |
| 2623 MAX(1, (gint) widget->allocation.height - (gint) attributes.y * 2); | |
| 2624 | |
| 2625 html->html_area = | |
| 2626 gdk_window_new(widget->window, &attributes, attributes_mask); | |
| 2627 gdk_window_set_user_data(html->html_area, html); | |
| 2628 | |
| 2629 widget->style = gtk_style_attach(widget->style, widget->window); | |
| 2630 | |
| 2631 /* | |
| 2632 * Can't call gtk_style_set_background here because it's handled specially | |
| 2633 */ | |
| 2634 gdk_window_set_background(widget->window, | |
| 2635 &widget->style->base[GTK_STATE_NORMAL]); | |
| 2636 gdk_window_set_background(html->html_area, | |
| 2637 &widget->style->base[GTK_STATE_NORMAL]); | |
| 2638 | |
| 2639 if (widget->style->bg_pixmap[GTK_STATE_NORMAL]) | |
| 2640 html->bg_gc = create_bg_gc(html); | |
| 2641 | |
| 2642 html->gc = gdk_gc_new(html->html_area); | |
| 2643 gdk_gc_set_exposures(html->gc, TRUE); | |
| 2644 gdk_gc_set_foreground(html->gc, &widget->style->text[GTK_STATE_NORMAL]); | |
| 2645 | |
| 2646 gdk_window_show(html->html_area); | |
| 1 | 2647 |
| 2648 } | |
| 2649 | |
| 12 | 2650 static void gtk_html_style_set(GtkWidget * widget, GtkStyle * previous_style) |
| 1 | 2651 { |
| 12 | 2652 GtkHtml *html; |
| 2653 | |
| 2654 g_return_if_fail(widget != NULL); | |
| 2655 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 2656 | |
| 2657 html = GTK_HTML(widget); | |
| 2658 if (GTK_WIDGET_REALIZED(widget)) | |
| 2659 { | |
| 2660 gdk_window_set_background(widget->window, | |
| 2661 &widget->style->base[GTK_STATE_NORMAL]); | |
| 2662 gdk_window_set_background(html->html_area, | |
| 2663 &widget->style->base[GTK_STATE_NORMAL]); | |
| 2664 | |
| 2665 if (html->bg_gc) | |
| 2666 { | |
| 2667 gdk_gc_destroy(html->bg_gc); | |
| 2668 html->bg_gc = NULL; | |
| 2669 } | |
| 2670 | |
| 2671 if (widget->style->bg_pixmap[GTK_STATE_NORMAL]) | |
| 2672 { | |
| 2673 html->bg_gc = create_bg_gc(html); | |
| 2674 } | |
| 2675 | |
| 2676 } | |
| 1 | 2677 } |
| 2678 | |
| 12 | 2679 static void gtk_html_unrealize(GtkWidget * widget) |
| 1 | 2680 { |
| 12 | 2681 GtkHtml *html; |
| 2682 | |
| 2683 g_return_if_fail(widget != NULL); | |
| 2684 g_return_if_fail(GTK_IS_HTML(widget)); | |
| 2685 | |
| 2686 html = GTK_HTML(widget); | |
| 2687 | |
| 2688 gdk_window_set_user_data(html->html_area, NULL); | |
| 2689 gdk_window_destroy(html->html_area); | |
| 2690 html->html_area = NULL; | |
| 2691 | |
| 2692 gdk_gc_destroy(html->gc); | |
| 2693 html->gc = NULL; | |
| 2694 | |
| 2695 if (html->bg_gc) | |
| 2696 { | |
| 2697 gdk_gc_destroy(html->bg_gc); | |
| 2698 html->bg_gc = NULL; | |
| 2699 } | |
| 2700 | |
| 2701 if (GTK_WIDGET_CLASS(parent_class)->unrealize) | |
| 2702 (*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget); | |
| 1 | 2703 } |
| 2704 | |
| 2705 | |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2706 void gtk_html_add_pixmap(GtkHtml * html, GdkPixmap * pm, int fit, int newline) |
| 1 | 2707 { |
| 12 | 2708 GtkHtmlBit *last_hb; |
| 2709 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1); | |
| 2710 GdkWindowPrivate *private = (GdkWindowPrivate *) pm; | |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2711 int width, height; |
| 12 | 2712 |
| 2713 last_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data; | |
| 1 | 2714 |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2715 /* wrap pixmaps */ |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2716 gdk_window_get_size(html->html_area, &width, &height); |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2717 if ((html->current_x + private->width) >= width) { |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2718 html->current_x = 0; |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2719 } |
|
499
3ebd3ca4c3d4
[gaim-migrate @ 509]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
492
diff
changeset
|
2720 |
| 1 | 2721 hb->fit = fit; |
|
542
872d68495410
[gaim-migrate @ 552]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
540
diff
changeset
|
2722 html->current_x += 2; |
| 1 | 2723 hb->x = html->current_x; |
| 2724 hb->y = html->current_y; | |
| 12 | 2725 if (fit) |
| 1 | 2726 hb->height = last_hb->height; |
| 2727 else | |
| 2728 hb->height = private->height; | |
| 2729 hb->type = HTML_BIT_PIXMAP; | |
| 2730 hb->width = private->width; | |
| 2731 hb->text = NULL; | |
| 2732 hb->url = NULL; | |
| 2733 hb->fore = NULL; | |
| 2734 hb->back = NULL; | |
| 2735 hb->font = NULL; | |
| 12 | 2736 hb->uline = 0; |
| 2737 hb->strike = 0; | |
| 1 | 2738 hb->was_selected = 0; |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2739 hb->newline = newline; |
| 12 | 2740 hb->pm = pm; |
| 2741 | |
| 2742 if (html->current_x == BORDER_WIDTH) | |
| 2743 { | |
|
540
f586c3819574
[gaim-migrate @ 550]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
537
diff
changeset
|
2744 html->current_y += hb->height + 3; |
|
f586c3819574
[gaim-migrate @ 550]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
537
diff
changeset
|
2745 hb->y += hb->height + 3; |
| 1 | 2746 } |
| 2747 | |
| 2748 | |
|
542
872d68495410
[gaim-migrate @ 552]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
540
diff
changeset
|
2749 html->current_x += hb->width + 1; |
| 12 | 2750 |
| 1 | 2751 gtk_html_draw_bit(html, hb, 1); |
| 2752 | |
|
536
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2753 if (hb->newline) |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2754 html->current_x = 0; |
|
c9f994ea5833
[gaim-migrate @ 546]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
526
diff
changeset
|
2755 |
| 1 | 2756 html->html_bits = g_list_append(html->html_bits, hb); |
| 2757 | |
| 2758 | |
| 2759 } | |
| 2760 | |
| 12 | 2761 static void gtk_html_add_seperator(GtkHtml * html) |
| 1 | 2762 { |
| 12 | 2763 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1); |
| 2764 gint width, | |
| 2765 height; | |
| 2766 | |
| 1 | 2767 html->current_x = 0; |
| 2768 html->current_y += 5; | |
| 2769 | |
| 12 | 2770 gdk_window_get_size(html->html_area, &width, &height); |
| 2771 | |
| 1 | 2772 hb->x = html->current_x; |
| 2773 hb->y = html->current_y; | |
| 2774 hb->height = 5; | |
| 2775 hb->type = HTML_BIT_SEP; | |
| 12 | 2776 hb->width = |
| 2777 width - | |
| 2778 GTK_SCROLLED_WINDOW(GTK_WIDGET(html)->parent)->vscrollbar->allocation. | |
| 2779 width - 10; | |
| 1 | 2780 hb->text = NULL; |
| 2781 hb->url = NULL; | |
| 2782 hb->fore = NULL; | |
| 2783 hb->back = NULL; | |
| 2784 hb->font = NULL; | |
| 12 | 2785 hb->uline = 0; |
| 2786 hb->strike = 0; | |
| 1 | 2787 hb->was_selected = 0; |
| 12 | 2788 hb->newline = 0; |
| 2789 hb->pm = NULL; | |
| 1 | 2790 |
| 2791 gtk_html_draw_bit(html, hb, 1); | |
| 2792 | |
| 2793 html->html_bits = g_list_append(html->html_bits, hb); | |
| 2794 | |
| 2795 } | |
| 2796 | |
| 2797 | |
| 12 | 2798 static void gtk_html_add_text(GtkHtml * html, |
| 2799 GdkFont * cfont, | |
| 2800 GdkColor * fore, | |
| 2801 GdkColor * back, | |
| 2802 char *chars, | |
| 2803 gint length, gint uline, gint strike, char *url) | |
| 1 | 2804 { |
| 12 | 2805 char *nextline = NULL, |
| 2806 *c, | |
| 2807 *text, | |
| 2808 *tmp; | |
| 2809 GdkGC *gc; | |
| 2810 int nl = 0, | |
| 2811 nl2 = 0; | |
| 2812 int maxwidth; | |
| 2813 gint lb; | |
| 2814 GList *hbits; | |
| 79 | 2815 size_t num = 0; |
| 2816 int i, | |
| 12 | 2817 height; |
| 2818 GtkHtmlBit *hb; | |
| 2819 gint hwidth, | |
| 2820 hheight; | |
| 2821 | |
| 2822 if (length == 1 && chars[0] == '\n') | |
| 2823 { | |
| 2824 GtkHtmlBit *h; | |
| 2825 hbits = g_list_last(html->html_bits); | |
| 2826 if (!hbits) | |
| 2827 return; | |
| 2828 /* | |
| 2829 * I realize this loses a \n sometimes | |
| 2830 * * if it's the first thing in the widget. | |
| 2831 * * so fucking what. | |
| 2832 */ | |
| 2833 | |
| 2834 h = (GtkHtmlBit *) hbits->data; | |
| 2835 h->newline++; | |
| 2836 if (html->current_x > 0) | |
| 2837 html->current_x = 0; | |
| 2838 else | |
|
540
f586c3819574
[gaim-migrate @ 550]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
537
diff
changeset
|
2839 html->current_y += cfont->ascent + cfont->descent + 5; |
| 12 | 2840 return; |
| 2841 } | |
| 2842 | |
| 2843 | |
| 2844 | |
| 2845 c = text = g_malloc(length + 2); | |
| 2846 strncpy(text, chars, length); | |
| 2847 text[length] = 0; | |
| 2848 | |
| 2849 | |
| 2850 gc = html->gc; | |
| 2851 | |
| 2852 if (gc == NULL) | |
| 2853 gc = html->gc = gdk_gc_new(html->html_area); | |
| 2854 | |
| 2855 gdk_gc_set_font(gc, cfont); | |
| 2856 | |
| 2857 | |
| 2858 while (*c) | |
| 2859 { | |
| 2860 if (*c == '\n') | |
| 2861 { | |
| 2862 if (*(c + 1) == '\0') | |
| 2863 { | |
| 2864 nl = 1; | |
| 2865 length--; | |
| 2866 c[0] = '\0'; | |
| 2867 break; | |
| 2868 } | |
| 2869 if (*c) | |
| 2870 { | |
| 2871 gtk_html_add_text(html, cfont, fore, back, text, num + 1, uline, | |
| 2872 strike, url); | |
| 2873 tmp = text; | |
| 2874 length -= (num + 1); | |
| 2875 text = g_malloc(length + 2); | |
| 2876 strncpy(text, (c + 1), length); | |
| 2877 text[length] = 0; | |
| 2878 c = text; | |
| 2879 num = 0; | |
| 2880 g_free(tmp); | |
| 1 | 2881 continue; |
| 12 | 2882 } |
| 2883 } | |
| 2884 | |
| 2885 num++; | |
| 2886 c++; | |
| 2887 } | |
| 2888 | |
| 2889 /* | |
| 2890 * Note, yG is chosen because G is damn high, and y is damn low, | |
| 2891 */ | |
| 2892 /* | |
| 2893 * it should be just fine. :) | |
| 2894 */ | |
| 2895 | |
| 2896 gdk_window_get_size(html->html_area, &hwidth, &hheight); | |
| 2897 | |
| 2898 num = strlen(text); | |
| 2899 | |
| 2900 while (GTK_WIDGET(html)->allocation.width < 20) | |
| 2901 { | |
| 2902 while (gtk_events_pending()) | |
| 1 | 2903 gtk_main_iteration(); |
| 2904 } | |
| 2905 | |
| 12 | 2906 maxwidth = (hwidth - html->current_x - 8); |
| 2907 /* | |
| 2908 * HTK_SCROLLED_WINDOW(GTK_WIDGET(layout)->parent)->vscrollbar->allocation.width) - 8; | |
| 2909 */ | |
| 2910 | |
| 2911 while (gdk_text_measure(cfont, text, num) > maxwidth) | |
| 2912 { | |
| 2913 if (num > 1) | |
| 2914 num--; | |
| 2915 else | |
| 2916 { | |
| 26 | 2917 if (html->current_x != 0) { |
| 2918 html->current_x = 0; | |
| 2919 if (nl) { | |
| 2920 text[length] = '\n'; | |
| 2921 length++; | |
| 2922 } | |
| 2923 gtk_html_add_text(html, cfont, fore, back, text, length, uline, strike, url); | |
| 2924 g_free(text); | |
| 2925 return; | |
| 2926 } else { | |
| 2927 num = strlen (text); | |
| 2928 break; | |
| 1 | 2929 } |
| 2930 } | |
| 2931 | |
| 2932 } | |
| 2933 | |
| 12 | 2934 height = cfont->ascent + cfont->descent + 2; |
| 2935 | |
| 2936 | |
| 2937 if ((int) (html->vadj->upper - html->current_y) < (int) (height * 2)) | |
| 2938 { | |
| 2939 int val; | |
| 2940 val = (height * 2) + html->current_y; | |
| 2941 html->vadj->upper = val; | |
| 2942 adjust_adj(html, html->vadj); | |
| 1 | 2943 } |
| 2944 | |
| 12 | 2945 |
| 2946 if (html->current_x == 0) | |
| 2947 { | |
|
540
f586c3819574
[gaim-migrate @ 550]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
537
diff
changeset
|
2948 html->current_y += height + 3; |
| 12 | 2949 gdk_text_extents(cfont, text, 1, &lb, NULL, NULL, NULL, NULL); |
| 2950 html->current_x += (2 - lb); | |
| 2951 } | |
| 2952 else if ((hbits = g_list_last(html->html_bits)) != NULL) | |
| 2953 { | |
| 2954 int diff, | |
| 2955 y; | |
| 2956 hb = (GtkHtmlBit *) hbits->data; | |
| 2957 if (height > hb->height) | |
| 2958 { | |
| 1 | 2959 diff = height - hb->height; |
| 2960 y = hb->y; | |
| 2961 html->current_y += diff; | |
| 12 | 2962 while (hbits) |
| 2963 { | |
| 2964 hb = (GtkHtmlBit *) hbits->data; | |
| 1 | 2965 if (hb->y != y) |
| 12 | 2966 break; |
|
492
56399273ed8d
[gaim-migrate @ 502]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
481
diff
changeset
|
2967 if (hb->type != HTML_BIT_PIXMAP) |
|
56399273ed8d
[gaim-migrate @ 502]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
481
diff
changeset
|
2968 hb->height = height; |
| 12 | 2969 hb->y += diff; ////////////my thing here ///////////////// |
| 2970 gtk_html_draw_bit(html, hb, FALSE); | |
| 2971 | |
| 2972 hbits = hbits->prev; | |
| 1 | 2973 } |
| 2974 } | |
| 2975 } | |
| 2976 | |
| 2977 | |
| 2978 | |
| 2979 | |
| 12 | 2980 if (num != strlen(text)) |
| 2981 { | |
| 2982 /* | |
| 2983 * This is kinda cheesy but it may make things | |
| 2984 * * much better lookin | |
| 2985 */ | |
| 26 | 2986 |
| 2987 for (i=2; (num - i > 0); i++) { | |
| 2988 if (text[num - i] == ' ') { | |
| 12 | 2989 num = num - (i - 1); |
| 1 | 2990 nl2 = 1; |
| 2991 break; | |
| 2992 } | |
| 2993 } | |
| 2994 | |
| 2995 nextline = g_malloc(length - num + 2); | |
| 12 | 2996 strncpy(nextline, (char *) (text + num), length - num); |
| 1 | 2997 nextline[length - num] = 0; |
| 12 | 2998 if (nl) |
| 2999 { | |
| 1 | 3000 nextline[length - num] = '\n'; |
| 3001 nextline[length - num + 1] = 0; | |
| 3002 nl = 0; | |
| 3003 } | |
| 3004 | |
| 3005 | |
| 3006 text[num] = 0; | |
| 3007 } | |
| 3008 | |
| 3009 | |
| 52 | 3010 if (url != NULL) { |
| 53 | 3011 fore = get_color(3355647, gdk_window_get_colormap(html->html_area)); |
| 52 | 3012 } |
| 1 | 3013 |
| 3014 hb = g_new0(GtkHtmlBit, 1); | |
| 3015 | |
| 3016 hb->text = g_strdup(text); | |
| 3017 | |
| 52 | 3018 if (fore) |
| 3019 hb->fore = gdk_color_copy(fore); | |
| 3020 else | |
| 3021 hb->fore = NULL; | |
| 49 | 3022 |
| 1 | 3023 if (back) |
| 3024 hb->back = gdk_color_copy(back); | |
| 3025 else | |
| 3026 hb->back = NULL; | |
| 3027 hb->font = cfont; | |
| 3028 hb->uline = uline; | |
| 3029 hb->strike = strike; | |
| 3030 hb->height = height; | |
| 3031 gdk_text_extents(cfont, text, num, &lb, NULL, &hb->width, NULL, NULL); | |
| 3032 hb->x = html->current_x; | |
| 3033 hb->y = html->current_y; | |
| 12 | 3034 hb->type = HTML_BIT_TEXT; |
| 3035 hb->pm = NULL; | |
| 3036 if (url != NULL) | |
| 3037 { | |
| 1 | 3038 uline = 1; |
| 3039 hb->uline = 1; | |
| 3040 hb->url = g_strdup(url); | |
| 12 | 3041 } |
| 3042 else | |
| 3043 { | |
| 1 | 3044 hb->url = NULL; |
| 3045 } | |
| 3046 html->current_x += hb->width; | |
| 3047 | |
| 3048 html->html_bits = g_list_append(html->html_bits, hb); | |
| 12 | 3049 if (url != NULL) |
| 3050 { | |
| 3051 html->urls = g_list_append(html->urls, hb); | |
| 3052 } | |
| 3053 | |
| 3054 | |
| 3055 | |
| 3056 gtk_html_draw_bit(html, hb, 1); | |
| 3057 | |
| 3058 if (nl || nl2) | |
| 3059 { | |
| 3060 if (nl) | |
| 3061 hb->newline = 1; | |
| 3062 html->current_x = 0; | |
| 3063 } | |
| 3064 else | |
| 3065 hb->newline = 0; | |
| 3066 | |
| 3067 | |
| 3068 if (nextline != NULL) | |
| 3069 { | |
| 3070 gtk_html_add_text(html, cfont, fore, back, nextline, strlen(nextline), | |
| 3071 uline, strike, url); | |
| 3072 g_free(nextline); | |
| 3073 } | |
| 3074 | |
| 3075 g_free(text); | |
| 137 | 3076 if (url != NULL) |
| 3077 g_free(fore); | |
| 1 | 3078 } |
| 3079 | |
| 12 | 3080 static char * html_strtok( char * input, char delim ) |
| 1 | 3081 { |
| 12 | 3082 static char * end; |
| 3083 static char * curr_offset; | |
| 3084 int i; | |
| 3085 int num_quotes=0; | |
| 3086 | |
| 3087 if( input != NULL) | |
| 3088 { | |
| 3089 curr_offset = input; | |
| 3090 end = input+strlen(input); | |
| 3091 } | |
| 3092 else | |
| 3093 { | |
| 3094 if( curr_offset + strlen(curr_offset) < end ) | |
| 3095 { | |
| 3096 curr_offset += strlen(curr_offset) + 1; | |
| 3097 } | |
| 3098 else | |
| 3099 { | |
| 3100 return NULL; | |
| 3101 } | |
| 3102 } | |
| 3103 for( i=0; curr_offset+i < end && | |
| 3104 (curr_offset[i] != delim || num_quotes != 0) | |
| 3105 ; i++ ) | |
| 3106 { | |
| 3107 if( curr_offset[i] == '\"' ) | |
| 3108 { | |
| 3109 num_quotes = (num_quotes+1)%2; | |
| 3110 } | |
| 3111 } | |
| 3112 curr_offset[i] = '\0'; | |
| 3113 return curr_offset; | |
| 3114 } | |
| 3115 | |
| 3116 | |
| 3117 void gtk_html_append_text(GtkHtml * html, char *text, gint options) | |
| 3118 { | |
| 3119 GdkColormap *map; | |
| 1 | 3120 GdkFont *cfont; |
| 12 | 3121 GdkRectangle area; |
| 3122 char ws[BUF_LONG], | |
| 3123 tag[BUF_LONG], | |
| 3124 *c, | |
| 3125 *url = NULL; | |
| 3126 gint intag = 0, | |
| 3127 wpos = 0, | |
|
481
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3128 tpos = 0; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3129 static gint colorv, |
| 12 | 3130 bold = 0, |
| 3131 italic = 0, | |
| 3132 fixed = 0, | |
| 3133 uline = 0, | |
| 3134 strike = 0, | |
|
481
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3135 title = 0, |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3136 height; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3137 static struct font_state *current = NULL, |
| 12 | 3138 *tmp; |
|
481
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3139 static struct font_state def_state = { 3, 0, 0, "", NULL, NULL, NULL }; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3140 |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3141 if (text == NULL) { |
|
740
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3142 bold = 0; |
|
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3143 italic = 0; |
|
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3144 fixed = 0; |
|
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3145 uline = 0; |
|
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3146 strike = 0; |
|
01d3c96867e2
[gaim-migrate @ 750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
737
diff
changeset
|
3147 title = 0; |
|
481
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3148 while (current->next) |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3149 { |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3150 if (current->ownbg) |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3151 g_free(current->bgcol); |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3152 if (current->owncolor) |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3153 g_free(current->color); |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3154 tmp = current; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3155 current = current->next; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3156 g_free(tmp); |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3157 } |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3158 return; |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3159 } |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3160 |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
3161 if (!current) current = &def_state; |
| 12 | 3162 map = gdk_window_get_colormap(html->html_area); |
| 3163 cfont = getfont(current->font, bold, italic, fixed, current->size); | |
| 1 | 3164 c = text; |
| 3165 | |
| 3166 | |
| 12 | 3167 while (*c) |
| 3168 { | |
| 3169 if (*c == '<') | |
| 3170 { | |
| 3171 if (!intag) | |
| 3172 { | |
| 3173 ws[wpos] = 0; | |
| 3174 if (wpos) | |
| 3175 { | |
| 3176 if (title) | |
| 3177 { | |
| 3178 if (html->title) | |
| 3179 g_free(html->title); | |
| 3180 html->title = g_strdup(ws); | |
| 3181 } | |
| 3182 else | |
| 3183 gtk_html_add_text(html, cfont, current->color, | |
| 3184 current->bgcol, ws, strlen(ws), uline, | |
| 3185 strike, url); | |
| 3186 } | |
| 3187 wpos = 0; | |
| 3188 intag = 1; | |
| 3189 } | |
| 3190 else | |
| 3191 { | |
| 3192 /* | |
| 3193 * Assuming you NEVER have nested tags | |
| 3194 * * (and I mean <tag <tag>> by this, not | |
| 3195 * * <tag><tag2></tag2><tag>.. | |
| 3196 */ | |
| 3197 tag[tpos] = 0; | |
| 3198 gtk_html_add_text(html, cfont, current->color, current->bgcol, | |
| 3199 "<", 1, 0, 0, NULL); | |
| 3200 gtk_html_add_text(html, cfont, current->color, current->bgcol, | |
| 3201 tag, strlen(tag), 0, 0, NULL); | |
| 1 | 3202 tpos = 0; |
| 12 | 3203 |
| 3204 tag[0] = *c; | |
| 1 | 3205 } |
| 12 | 3206 } |
| 3207 else if (*c == '>') | |
| 3208 { | |
| 3209 if (intag) | |
| 3210 { | |
| 3211 tag[tpos] = 0; | |
| 1 | 3212 if (!strcasecmp(tag, "B")) |
| 3213 bold = 1; | |
| 732 | 3214 else if (!strcasecmp(tag, "STRIKE") || !strcasecmp(tag, "S")) |
| 1 | 3215 strike = 1; |
| 3216 else if (!strcasecmp(tag, "I")) | |
| 3217 italic = 1; | |
| 3218 else if (!strcasecmp(tag, "U")) | |
| 3219 uline = 1; | |
| 3220 else if (!strcasecmp(tag, "PRE")) | |
| 3221 fixed = 1; | |
| 3222 else if (!strcasecmp(tag, "HR")) | |
| 3223 gtk_html_add_seperator(html); | |
| 3224 else if (!strcasecmp(tag, "/B")) | |
| 3225 bold = 0; | |
| 732 | 3226 else if (!strcasecmp(tag, "/STRIKE") || !strcasecmp(tag, "/S")) |
| 1 | 3227 strike = 0; |
| 3228 else if (!strcasecmp(tag, "/I")) | |
| 3229 italic = 0; | |
| 3230 else if (!strcasecmp(tag, "/U")) | |
| 3231 uline = 0; | |
| 3232 else if (!strcasecmp(tag, "/PRE")) | |
| 3233 fixed = 0; | |
| 3234 else if (!strcasecmp(tag, "TITLE")) | |
| 3235 title = 1; | |
| 3236 else if (!strcasecmp(tag, "/TITLE")) | |
| 3237 title = 0; | |
| 12 | 3238 else if (!strncasecmp(tag, "IMG", 3)) |
| 3239 { | |
| 549 | 3240 GdkPixmap *legend_i; |
| 3241 GdkBitmap *legend_m; | |
| 3242 | |
| 3243 if (strstr(tag, "SRC=\"aol_icon.gif\"") != NULL) | |
| 3244 { | |
| 3245 legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, aol_icon_xpm); | |
| 3246 gtk_html_add_pixmap(html, legend_i, 0, 0); | |
| 3247 } | |
| 3248 | |
| 3249 if (strstr(tag, "SRC=\"admin_icon.gif\"") != NULL) | |
| 3250 { | |
| 3251 legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, admin_icon_xpm); | |
| 3252 gtk_html_add_pixmap(html, legend_i, 0, 0); | |
| 3253 } | |
| 3254 if (strstr(tag, "SRC=\"dt_icon.gif\"") != NULL) | |
| 3255 { | |
| 3256 legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, dt_icon_xpm); | |
| 3257 gtk_html_add_pixmap(html, legend_i, 0, 0); | |
| 3258 } | |
| 3259 if (strstr(tag, "SRC=\"free_icon.gif\"") != NULL) | |
| 3260 { | |
| 3261 legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, free_icon_xpm); | |
| 3262 gtk_html_add_pixmap(html, legend_i, 0, 0); | |
| 3263 } | |
| 12 | 3264 } |
| 3265 else if (!strcasecmp(tag, "H3")) | |
| 3266 { | |
| 1 | 3267 current = push_state(current); |
| 3268 current->size = 4; | |
| 12 | 3269 } |
| 3270 else if (!strcasecmp(tag, "/H3")) | |
| 3271 { | |
| 3272 gtk_html_add_text(html, cfont, current->color, | |
| 3273 current->bgcol, "\n", 1, 0, 0, NULL); | |
| 3274 | |
| 3275 if (current->next) | |
| 3276 { | |
| 1 | 3277 if (current->ownbg) |
| 3278 g_free(current->bgcol); | |
| 3279 if (current->owncolor) | |
| 3280 g_free(current->color); | |
| 12 | 3281 tmp = current; |
| 3282 current = current->next; | |
| 3283 g_free(tmp); | |
| 1 | 3284 } |
| 12 | 3285 } |
| 3286 else if (!strcasecmp(tag, "TABLE")) | |
| 3287 { | |
| 3288 } | |
| 3289 else if (!strcasecmp(tag, "/TABLE")) | |
| 3290 { | |
| 3291 } | |
| 3292 else if (!strcasecmp(tag, "TR")) | |
| 3293 { | |
| 3294 } | |
| 3295 else if (!strcasecmp(tag, "/TR")) | |
| 3296 { | |
| 3297 } | |
| 3298 else if (!strcasecmp(tag, "/TD")) | |
| 3299 { | |
| 3300 } | |
| 3301 else if (!strcasecmp(tag, "TD")) | |
| 3302 { | |
| 3303 gtk_html_add_text(html, cfont, current->color, | |
| 3304 current->bgcol, " ", 2, 0, 0, NULL); | |
| 3305 } | |
| 3306 else if (!strncasecmp(tag, "A ", 2)) | |
| 3307 { | |
| 1 | 3308 char *d; |
| 3309 char *temp = d = g_strdup(tag); | |
| 3310 int flag = 0; | |
| 12 | 3311 strtok(tag, " "); |
| 3312 while ((d = strtok(NULL, " "))) | |
| 3313 { | |
| 1 | 3314 if (strlen(d) < 7) |
| 3315 break; | |
| 12 | 3316 if (!strncasecmp(d, "HREF=\"", strlen("HREF=\""))) |
| 3317 { | |
| 3318 d += strlen("HREF=\""); | |
| 1 | 3319 d[strlen(d) - 1] = 0; |
| 3320 url = g_malloc(strlen(d) + 1); | |
| 3321 strcpy(url, d); | |
| 3322 flag = 1; | |
| 12 | 3323 } |
| 3324 } | |
| 1 | 3325 g_free(temp); |
| 12 | 3326 if (!flag) |
| 3327 { | |
| 3328 gtk_html_add_text(html, cfont, current->color, | |
| 3329 current->bgcol, "<", 1, 0, 0, NULL); | |
| 3330 gtk_html_add_text(html, cfont, current->color, | |
| 3331 current->bgcol, tag, strlen(tag), 0, | |
| 3332 0, NULL); | |
| 3333 gtk_html_add_text(html, cfont, current->color, | |
| 3334 current->bgcol, ">", 1, 0, 0, NULL); | |
| 1 | 3335 } |
| 12 | 3336 } |
| 3337 else if (!strcasecmp(tag, "/A")) | |
| 3338 { | |
| 3339 if (url) | |
| 3340 { | |
| 1 | 3341 g_free(url); |
| 3342 url = NULL; | |
| 3343 } | |
| 12 | 3344 } |
| 3345 else if (!strncasecmp(tag, "FONT", strlen("FONT"))) | |
| 3346 { | |
| 3347 char *d; | |
| 3348 /* | |
| 3349 * Push a new state onto the stack, based on the old state | |
| 3350 */ | |
| 3351 current = push_state(current); | |
| 3352 html_strtok(tag, ' '); | |
| 3353 while ((d = html_strtok(NULL, ' '))) | |
| 3354 { | |
| 3355 if (!strncasecmp(d, "COLOR=", strlen("COLOR="))) | |
| 3356 { | |
| 3357 d += strlen("COLOR="); | |
| 3358 if (*d == '\"') | |
| 3359 { | |
| 3360 d++; | |
| 3361 } | |
| 3362 if (*d == '#') | |
| 3363 d++; | |
| 3364 if (d[strlen(d) - 1] == '\"') | |
| 3365 d[strlen(d) - 1] = 0; | |
| 3366 if (sscanf(d, "%x", &colorv) | |
| 3367 && !(options & HTML_OPTION_NO_COLOURS)) | |
| 3368 { | |
|
677
05f6f7dabb7e
[gaim-migrate @ 687]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
674
diff
changeset
|
3369 current->color = get_color(colorv, map); |
|
05f6f7dabb7e
[gaim-migrate @ 687]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
674
diff
changeset
|
3370 current->owncolor = 1; |
| 12 | 3371 } |
| 3372 else | |
| 3373 { | |
| 1 | 3374 } |
| 12 | 3375 } |
| 3376 if (!strncasecmp(d, "FACE=", strlen("FACE="))) | |
| 3377 { | |
| 3378 d += strlen("FACE="); | |
| 3379 if (*d == '\"') | |
| 3380 { | |
| 3381 d++; | |
| 3382 } | |
| 1 | 3383 if (d[strlen(d) - 1] == '\"') |
| 3384 d[strlen(d) - 1] = 0; | |
| 12 | 3385 strcpy(current->font, d); |
| 3386 } | |
| 3387 else if (!strncasecmp(d, "BACK=", strlen("BACK="))) | |
| 3388 { | |
| 3389 d += strlen("BACK="); | |
| 3390 if (*d == '\"') | |
| 3391 d++; | |
| 3392 if (*d == '#') | |
| 3393 d++; | |
| 3394 if (d[strlen(d) - 1] == '\"') | |
| 3395 d[strlen(d) - 1] = 0; | |
| 3396 if (sscanf(d, "%x", &colorv) | |
| 3397 && !(options & HTML_OPTION_NO_COLOURS)) | |
| 3398 { | |
| 1 | 3399 current->bgcol = get_color(colorv, map); |
| 3400 current->ownbg = 1; | |
| 12 | 3401 } |
| 3402 else | |
| 3403 { | |
| 3404 } | |
| 3405 } | |
| 3406 else if (!strncasecmp(d, "SIZE=", strlen("SIZE="))) | |
| 3407 { | |
| 3408 d += strlen("SIZE="); | |
| 3409 if (*d == '\"') | |
| 3410 d++; | |
| 3411 if (*d == '+') | |
| 3412 d++; | |
| 3413 if (sscanf(d, "%d", &colorv)) | |
| 3414 { | |
| 3415 current->size = colorv; | |
| 3416 } | |
| 3417 else | |
| 3418 { | |
| 1 | 3419 } |
| 12 | 3420 } |
| 3421 else if (strncasecmp(d, "PTSIZE=", strlen("PTSIZE="))) | |
| 3422 { | |
| 3423 } | |
| 1 | 3424 } |
| 12 | 3425 } |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3426 else if (!strncasecmp(tag, "BODY", strlen("BODY"))) |
| 12 | 3427 { |
| 3428 | |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3429 char *d; |
|
632
21c63b26c604
[gaim-migrate @ 642]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
629
diff
changeset
|
3430 current = push_state(current); |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3431 html_strtok(tag, ' '); |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3432 while ((d = html_strtok(NULL, ' '))) |
| 12 | 3433 { |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3434 if (!strncasecmp(d, "BGCOLOR=", strlen("BGCOLOR="))) |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3435 { |
|
677
05f6f7dabb7e
[gaim-migrate @ 687]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
674
diff
changeset
|
3436 d += strlen("BGCOLOR="); |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3437 if (*d == '\"') |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3438 d++; |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3439 if (*d == '#') |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3440 d++; |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3441 if (d[strlen(d) - 1] == '\"') |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3442 d[strlen(d) - 1] = 0; |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3443 if (sscanf(d, "%x", &colorv) |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3444 && !(options & HTML_OPTION_NO_COLOURS)) |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3445 { |
|
677
05f6f7dabb7e
[gaim-migrate @ 687]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
674
diff
changeset
|
3446 if (colorv != 0xffffff || |
|
669
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3447 !(display_options & OPT_DISP_IGN_WHITE)) { |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3448 current->bgcol = get_color(colorv, map); |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3449 current->ownbg = 1; |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3450 } |
|
e871081839d0
[gaim-migrate @ 679]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
667
diff
changeset
|
3451 } |
|
667
45ed2ca0756e
[gaim-migrate @ 677]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
666
diff
changeset
|
3452 } |
| 12 | 3453 } |
| 3454 } | |
| 3455 else if (!strncasecmp(tag, "/FONT", strlen("/FONT"))) | |
| 3456 { | |
| 3457 /* | |
| 3458 * Pop a font state off the list if possible, freeing | |
| 3459 * any resources it used | |
| 3460 */ | |
| 3461 if (current->next) | |
| 3462 { | |
| 1 | 3463 if (current->ownbg) |
| 3464 g_free(current->bgcol); | |
| 3465 if (current->owncolor) | |
| 3466 g_free(current->color); | |
| 12 | 3467 tmp = current; |
| 3468 current = current->next; | |
| 3469 g_free(tmp); | |
| 3470 } | |
| 3471 | |
| 3472 } | |
| 3473 else if (!strcasecmp(tag, "/BODY")) | |
| 3474 { | |
| 3475 if (current->next) | |
| 3476 { | |
| 3477 if (current->ownbg) | |
| 3478 g_free(current->bgcol); | |
| 3479 if (current->owncolor) | |
| 3480 g_free(current->color); | |
| 3481 tmp = current; | |
| 3482 current = current->next; | |
| 1 | 3483 g_free(tmp); |
| 12 | 3484 } /* |
| 3485 * tags we ignore below | |
| 3486 */ | |
| 3487 } | |
| 3488 else if (!strncasecmp(tag, "BR", 2)) | |
| 3489 { | |
| 3490 gtk_html_add_text(html, cfont, current->color, | |
| 3491 current->bgcol, "\n", 1, 0, 0, NULL); | |
| 3492 } | |
| 3493 else if (strncasecmp(tag, "HTML", 4) | |
| 3494 && strncasecmp(tag, "/HTML", 5) | |
| 3495 && strncasecmp(tag, "BODY", 4) | |
| 3496 && strncasecmp(tag, "/BODY", 5) | |
|
627
da0a1238874d
[gaim-migrate @ 637]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
604
diff
changeset
|
3497 && (strncasecmp(tag, "P", 1) || tag[1] != '>') |
|
da0a1238874d
[gaim-migrate @ 637]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
604
diff
changeset
|
3498 && (strncasecmp(tag, "/P", 2) || tag[3] != '>') |
| 12 | 3499 && strncasecmp(tag, "HEAD", 4) |
| 3500 && strncasecmp(tag, "/HEAD", 5)) | |
| 3501 { | |
| 3502 if (tpos) | |
| 3503 { | |
| 3504 gtk_html_add_text(html, cfont, current->color, | |
| 3505 current->bgcol, "<", 1, 0, 0, NULL); | |
| 3506 gtk_html_add_text(html, cfont, current->color, | |
| 3507 current->bgcol, tag, strlen(tag), 0, | |
| 3508 0, NULL); | |
| 3509 gtk_html_add_text(html, cfont, current->color, | |
| 3510 current->bgcol, ">", 1, 0, 0, NULL); | |
| 1 | 3511 |
| 3512 } | |
| 3513 } | |
| 12 | 3514 cfont = getfont(current->font, bold, italic, fixed, current->size); |
| 3515 tpos = 0; | |
| 1 | 3516 intag = 0; |
| 3517 } | |
| 12 | 3518 else |
| 3519 { | |
| 1 | 3520 ws[wpos++] = *c; |
| 3521 } | |
| 12 | 3522 } |
| 3523 else if (!intag && *c == '&') | |
| 3524 { | |
| 3525 if (!strncasecmp(c, "&", 5)) | |
| 3526 { | |
| 3527 ws[wpos++] = '&'; | |
| 3528 c += 4; | |
| 3529 } | |
| 3530 else if (!strncasecmp(c, "<", 4)) | |
| 3531 { | |
| 3532 ws[wpos++] = '<'; | |
| 3533 c += 3; | |
| 3534 } | |
| 3535 else if (!strncasecmp(c, ">", 4)) | |
| 3536 { | |
| 3537 ws[wpos++] = '>'; | |
| 3538 c += 3; | |
| 3539 } | |
| 3540 else if (!strncasecmp(c, " ", 6)) | |
| 3541 { | |
| 3542 ws[wpos++] = ' '; | |
| 3543 c += 5; | |
| 3544 } | |
|
526
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3545 else if (!strncasecmp(c, "©", 6)) |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3546 { |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3547 ws[wpos++] = '©'; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3548 c += 5; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3549 } |
|
737
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3550 else if (!strncasecmp(c, """, 6)) |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3551 { |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3552 ws[wpos++] = '\"'; |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3553 c += 5; |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3554 } |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3555 else if (!strncasecmp(c, "®", 5)) |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3556 { |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3557 ws[wpos++] = 174; |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3558 c += 4; |
|
c3a920cee3fc
[gaim-migrate @ 747]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
732
diff
changeset
|
3559 } |
|
526
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3560 else if (*(c + 1) == '#') |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3561 { |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3562 int pound = 0; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3563 debug_print("got &#;\n"); |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3564 if (sscanf(c, "&#%d;", £) > 0) { |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3565 ws[wpos++] = (char)pound; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3566 c += 2; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3567 while (isdigit(*c)) c++; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3568 if (*c != ';') c--; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3569 } else { |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3570 ws[wpos++] = *c; |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3571 } |
|
5bf71b39cba2
[gaim-migrate @ 536]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
523
diff
changeset
|
3572 } |
| 12 | 3573 else |
| 3574 { | |
| 3575 ws[wpos++] = *c; | |
| 3576 } | |
| 3577 } | |
| 3578 else | |
| 3579 { | |
| 3580 if (intag) | |
| 3581 { | |
| 3582 tag[tpos++] = *c; | |
| 3583 } | |
| 3584 else | |
| 3585 { | |
| 3586 ws[wpos++] = *c; | |
| 1 | 3587 } |
| 3588 } | |
| 3589 c++; | |
| 3590 } | |
| 12 | 3591 ws[wpos] = 0; |
| 3592 tag[tpos] = 0; | |
| 3593 if (wpos) | |
| 3594 { | |
| 3595 gtk_html_add_text(html, cfont, current->color, current->bgcol, ws, | |
| 3596 strlen(ws), uline, strike, url); | |
| 1 | 3597 } |
| 12 | 3598 if (tpos) |
| 3599 { | |
| 3600 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1, | |
| 3601 0, 0, NULL); | |
| 3602 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag, | |
| 3603 strlen(tag), 0, 0, NULL); | |
|
523
023c3851db0a
[gaim-migrate @ 533]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
506
diff
changeset
|
3604 /* gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1, |
| 12 | 3605 0, 0, NULL); |
|
523
023c3851db0a
[gaim-migrate @ 533]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
506
diff
changeset
|
3606 */ } |
| 12 | 3607 |
| 3608 | |
| 3609 | |
| 3610 gdk_window_get_size(html->html_area, NULL, &height); | |
| 3611 area.height = height; | |
| 1 | 3612 gtk_adjustment_set_value(html->vadj, html->vadj->upper - area.height); |
| 3613 | |
| 12 | 3614 return; |
| 1 | 3615 } |
| 3616 | |
| 3617 | |
| 12 | 3618 static void adjust_adj(GtkHtml * html, GtkAdjustment * adj) |
| 1 | 3619 { |
| 12 | 3620 gint height; |
| 3621 | |
| 3622 gdk_window_get_size(html->html_area, NULL, &height); | |
| 3623 | |
| 3624 adj->step_increment = MIN(adj->upper, (float) SCROLL_PIXELS); | |
| 3625 adj->page_increment = MIN(adj->upper, height - (float) KEY_SCROLL_PIXELS); | |
| 3626 adj->page_size = MIN(adj->upper, height); | |
| 3627 adj->value = MIN(adj->value, adj->upper - adj->page_size); | |
| 3628 adj->value = MAX(adj->value, 0.0); | |
| 3629 | |
| 3630 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed"); | |
| 1 | 3631 } |
| 3632 | |
| 3633 | |
| 12 | 3634 static void scroll_down(GtkHtml * html, gint diff0) |
| 1 | 3635 { |
| 12 | 3636 GdkRectangle rect; |
| 3637 gint width, | |
| 3638 height; | |
| 3639 | |
| 3640 html->yoffset += diff0; | |
| 3641 | |
| 3642 gdk_window_get_size(html->html_area, &width, &height); | |
| 3643 | |
| 3644 if (html->transparent) | |
| 3645 { | |
| 1 | 3646 rect.x = 0; |
| 3647 rect.y = 0; | |
| 3648 rect.width = width; | |
| 3649 rect.height = height; | |
| 12 | 3650 } |
| 3651 else | |
| 3652 { | |
| 3653 | |
| 1 | 3654 |
| 3655 if (height > diff0 && !html->transparent) | |
| 12 | 3656 gdk_draw_pixmap(html->html_area, |
| 3657 html->gc, | |
| 3658 html->html_area, | |
| 3659 0, diff0, 0, 0, width, height - diff0); | |
| 3660 | |
| 3661 rect.x = 0; | |
| 3662 rect.y = MAX(0, height - diff0); | |
| 3663 rect.width = width; | |
| 3664 rect.height = MIN(height, diff0); | |
| 1 | 3665 } |
| 12 | 3666 |
| 3667 expose_html(html, &rect, FALSE); | |
| 3668 gtk_html_draw_focus((GtkWidget *) html); | |
| 1 | 3669 |
| 3670 } | |
| 3671 | |
| 12 | 3672 static void scroll_up(GtkHtml * html, gint diff0) |
| 1 | 3673 { |
| 12 | 3674 GdkRectangle rect; |
| 3675 gint width, | |
| 3676 height; | |
| 3677 | |
| 1 | 3678 html->yoffset -= diff0; |
| 3679 | |
| 3680 | |
| 12 | 3681 gdk_window_get_size(html->html_area, &width, &height); |
| 3682 | |
| 3683 if (html->transparent) | |
| 3684 { | |
| 1 | 3685 rect.x = 0; |
| 3686 rect.y = 0; | |
| 3687 rect.width = width; | |
| 3688 rect.height = height; | |
| 12 | 3689 } |
| 3690 else | |
| 3691 { | |
| 3692 | |
| 1 | 3693 if (height > diff0) |
| 12 | 3694 gdk_draw_pixmap(html->html_area, |
| 3695 html->gc, | |
| 3696 html->html_area, | |
| 3697 0, 0, 0, diff0, width, height - diff0); | |
| 3698 | |
| 3699 rect.x = 0; | |
| 3700 rect.y = 0; | |
| 3701 rect.width = width; | |
| 3702 rect.height = MIN(height, diff0); | |
| 1 | 3703 } |
| 3704 | |
| 12 | 3705 expose_html(html, &rect, FALSE); |
| 3706 gtk_html_draw_focus((GtkWidget *) html); | |
| 1 | 3707 |
| 3708 } | |
| 3709 | |
| 3710 | |
| 3711 | |
| 12 | 3712 static void gtk_html_adjustment(GtkAdjustment * adjustment, GtkHtml * html) |
| 1 | 3713 { |
| 12 | 3714 g_return_if_fail(adjustment != NULL); |
| 3715 g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment)); | |
| 3716 g_return_if_fail(html != NULL); | |
| 3717 g_return_if_fail(GTK_IS_HTML(html)); | |
| 3718 | |
| 3719 /* | |
| 3720 * Just ignore it if we haven't been size-allocated and realized yet | |
| 3721 */ | |
| 3722 if (html->html_area == NULL) | |
| 3723 return; | |
| 3724 | |
| 3725 if (adjustment == html->hadj) | |
| 3726 { | |
| 3727 g_warning("horizontal scrolling not implemented"); | |
| 3728 } | |
| 3729 else | |
| 3730 { | |
| 3731 gint diff = ((gint) adjustment->value) - html->last_ver_value; | |
| 3732 | |
| 3733 if (diff != 0) | |
| 3734 { | |
| 3735 /* | |
| 3736 * undraw_cursor (text, FALSE); | |
| 3737 */ | |
| 3738 | |
| 3739 if (diff > 0) | |
| 3740 { | |
| 3741 scroll_down(html, diff); | |
| 3742 } | |
| 3743 else | |
| 3744 { /* | |
| 3745 * if (diff < 0) | |
| 3746 */ | |
| 3747 scroll_up(html, -diff); | |
| 3748 } | |
| 3749 /* | |
| 3750 * draw_cursor (text, FALSE); | |
| 3751 */ | |
| 3752 | |
| 3753 html->last_ver_value = adjustment->value; | |
| 3754 } | |
| 3755 } | |
| 1 | 3756 } |
| 12 | 3757 |
| 3758 static gint gtk_html_visibility_notify(GtkWidget * widget, | |
| 3759 GdkEventVisibility * event) | |
| 1 | 3760 { |
| 3761 GtkHtml *html; | |
| 3762 GdkRectangle rect; | |
| 12 | 3763 gint width, |
| 3764 height; | |
| 3765 | |
| 3766 g_return_val_if_fail(widget != NULL, FALSE); | |
| 3767 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE); | |
| 3768 | |
| 3769 html = GTK_HTML(widget); | |
| 3770 | |
| 3771 if (GTK_WIDGET_REALIZED(widget) && html->transparent) | |
| 3772 { | |
| 3773 gdk_window_get_size(html->html_area, &width, &height); | |
| 3774 rect.x = 0; | |
| 3775 rect.y = 0; | |
| 3776 rect.width = width; | |
| 3777 rect.height = height; | |
| 3778 expose_html(html, &rect, FALSE); | |
| 3779 gtk_html_draw_focus((GtkWidget *) html); | |
| 3780 } | |
| 3781 else | |
| 3782 { | |
| 1 | 3783 } |
| 3784 | |
| 3785 | |
| 12 | 3786 return FALSE; |
| 1 | 3787 } |
| 3788 | |
| 3789 | |
| 3790 | |
| 12 | 3791 static void gtk_html_disconnect(GtkAdjustment * adjustment, GtkHtml * html) |
| 1 | 3792 { |
| 12 | 3793 g_return_if_fail(adjustment != NULL); |
| 3794 g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment)); | |
| 3795 g_return_if_fail(html != NULL); | |
| 3796 g_return_if_fail(GTK_IS_HTML(html)); | |
| 3797 | |
| 3798 if (adjustment == html->hadj) | |
| 3799 gtk_html_set_adjustments(html, NULL, html->vadj); | |
| 3800 if (adjustment == html->vadj) | |
| 3801 gtk_html_set_adjustments(html, html->hadj, NULL); | |
| 1 | 3802 } |
| 3803 | |
| 12 | 3804 static void move_cursor_ver(GtkHtml * html, int count) |
| 1 | 3805 { |
| 3806 GList *hbits = g_list_find(html->html_bits, html->cursor_hb); | |
| 12 | 3807 GtkHtmlBit *hb = NULL, |
| 3808 *hb2 = NULL; | |
| 1 | 3809 gint y; |
| 79 | 3810 size_t len, |
| 12 | 3811 len2 = 0; |
| 3812 | |
| 1 | 3813 undraw_cursor(html); |
| 3814 | |
| 3815 if (!html->html_bits) | |
| 3816 return; | |
| 12 | 3817 |
| 1 | 3818 if (!html->cursor_hb) |
| 12 | 3819 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data; |
| 1 | 3820 |
| 3821 hb = html->cursor_hb; | |
| 3822 | |
| 3823 len = html->cursor_pos; | |
| 3824 hbits = hbits->prev; | |
| 12 | 3825 while (hbits) |
| 3826 { | |
| 3827 hb2 = (GtkHtmlBit *) hbits->data; | |
| 1 | 3828 |
| 3829 if (hb2->y != hb->y) | |
| 3830 break; | |
| 3831 | |
| 12 | 3832 len += strlen(hb2->text); |
| 3833 | |
| 1 | 3834 hbits = hbits->prev; |
| 3835 } | |
| 3836 | |
| 12 | 3837 hbits = g_list_find(html->html_bits, html->cursor_hb); |
| 3838 | |
| 3839 if (count < 0) | |
| 3840 { | |
| 3841 while (hbits) | |
| 3842 { | |
| 3843 hb2 = (GtkHtmlBit *) hbits->data; | |
| 1 | 3844 |
| 3845 if (hb2->y != hb->y) | |
| 3846 break; | |
| 12 | 3847 |
| 1 | 3848 hbits = hbits->prev; |
| 3849 } | |
| 12 | 3850 if (!hbits) |
| 3851 { | |
| 1 | 3852 draw_cursor(html); |
| 3853 return; | |
| 3854 } | |
| 3855 y = hb2->y; | |
| 3856 hb = hb2; | |
| 12 | 3857 while (hbits) |
| 3858 { | |
| 3859 hb2 = (GtkHtmlBit *) hbits->data; | |
| 1 | 3860 |
| 3861 if (hb2->y != y) | |
| 3862 break; | |
| 3863 | |
| 3864 hb = hb2; | |
| 12 | 3865 |
| 1 | 3866 hbits = hbits->prev; |
| 3867 } | |
| 3868 hbits = g_list_find(html->html_bits, hb); | |
| 12 | 3869 while (hbits) |
| 3870 { | |
| 3871 hb2 = (GtkHtmlBit *) hbits->data; | |
| 3872 | |
| 3873 if (hb->y != hb2->y) | |
| 3874 { | |
| 1 | 3875 html->cursor_hb = hb; |
| 3876 html->cursor_pos = strlen(hb->text); | |
| 12 | 3877 break; |
| 1 | 3878 } |
| 3879 | |
| 3880 | |
| 12 | 3881 if (len < len2 + strlen(hb2->text)) |
| 3882 { | |
| 1 | 3883 html->cursor_hb = hb2; |
| 3884 html->cursor_pos = len - len2; | |
| 3885 break; | |
| 3886 } | |
| 3887 | |
| 3888 len2 += strlen(hb2->text); | |
| 3889 | |
| 3890 hb = hb2; | |
| 3891 | |
| 12 | 3892 hbits = hbits->next; |
| 1 | 3893 } |
| 12 | 3894 } |
| 3895 else | |
| 3896 { | |
| 3897 while (hbits) | |
| 3898 { | |
| 3899 hb2 = (GtkHtmlBit *) hbits->data; | |
| 1 | 3900 |
| 3901 if (hb2->y != hb->y) | |
| 3902 break; | |
| 12 | 3903 |
| 1 | 3904 hbits = hbits->next; |
| 3905 } | |
| 12 | 3906 if (!hbits) |
| 3907 { | |
| 1 | 3908 draw_cursor(html); |
| 3909 return; | |
| 3910 } | |
| 3911 hb = hb2; | |
| 12 | 3912 while (hbits) |
| 3913 { | |
| 3914 hb2 = (GtkHtmlBit *) hbits->data; | |
| 3915 | |
| 3916 if (hb->y != hb2->y) | |
| 3917 { | |
| 1 | 3918 html->cursor_hb = hb; |
| 3919 html->cursor_pos = strlen(hb->text); | |
| 12 | 3920 break; |
| 1 | 3921 } |
| 3922 | |
| 3923 | |
| 12 | 3924 if (len < len2 + strlen(hb2->text)) |
| 3925 { | |
| 1 | 3926 html->cursor_hb = hb2; |
| 3927 html->cursor_pos = len - len2; | |
| 3928 break; | |
| 3929 } | |
| 3930 | |
| 3931 len2 += strlen(hb2->text); | |
| 3932 | |
| 3933 hb = hb2; | |
| 3934 | |
| 12 | 3935 hbits = hbits->next; |
| 1 | 3936 } |
| 3937 } | |
| 3938 | |
| 3939 draw_cursor(html); | |
| 3940 | |
| 3941 } | |
| 3942 | |
| 12 | 3943 static void move_cursor_hor(GtkHtml * html, int count) |
| 1 | 3944 { |
| 3945 GList *hbits = g_list_find(html->html_bits, html->cursor_hb); | |
| 12 | 3946 GtkHtmlBit *hb, |
| 3947 *hb2; | |
| 1 | 3948 |
| 3949 undraw_cursor(html); | |
| 3950 | |
| 3951 if (!html->html_bits) | |
| 3952 return; | |
| 12 | 3953 |
| 1 | 3954 if (!html->cursor_hb) |
| 12 | 3955 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data; |
| 3956 | |
| 3957 html->cursor_pos += count; | |
| 3958 | |
| 3959 if (html->cursor_pos < 0) | |
| 3960 { | |
| 3961 if (hbits->prev) | |
| 3962 { | |
| 1 | 3963 gint diff; |
| 3964 hb = html->cursor_hb; | |
| 12 | 3965 hb2 = (GtkHtmlBit *) hbits->prev->data; |
| 1 | 3966 diff = html->cursor_pos + strlen(hb2->text) + 1; |
| 3967 if (hb->y == hb2->y) | |
| 3968 --diff; | |
| 12 | 3969 |
| 1 | 3970 html->cursor_pos = diff; |
| 12 | 3971 |
| 3972 html->cursor_hb = (GtkHtmlBit *) hbits->prev->data; | |
| 3973 } | |
| 3974 else | |
| 3975 { | |
| 1 | 3976 html->cursor_pos = 0; |
| 3977 } | |
| 12 | 3978 } |
| 79 | 3979 else if ((unsigned) html->cursor_pos > strlen(html->cursor_hb->text)) |
| 12 | 3980 { |
| 3981 if (hbits->next) | |
| 3982 { | |
| 1 | 3983 gint diff; |
| 3984 hb = html->cursor_hb; | |
| 12 | 3985 hb2 = (GtkHtmlBit *) hbits->next->data; |
| 1 | 3986 |
| 3987 diff = html->cursor_pos - strlen(html->cursor_hb->text) - 1; | |
| 3988 if (hb->y == hb2->y) | |
| 12 | 3989 ++diff; |
| 1 | 3990 html->cursor_pos = diff; |
| 12 | 3991 html->cursor_hb = (GtkHtmlBit *) hbits->next->data; |
| 3992 } | |
| 3993 else | |
| 3994 { | |
| 1 | 3995 html->cursor_pos = strlen(html->cursor_hb->text); |
| 3996 } | |
| 3997 | |
| 3998 } | |
| 3999 | |
| 4000 draw_cursor(html); | |
| 4001 } | |
| 4002 | |
| 12 | 4003 static void move_beginning_of_line(GtkHtml * html) |
| 1 | 4004 { |
| 4005 GList *hbits = g_list_find(html->html_bits, html->cursor_hb); | |
| 4006 GtkHtmlBit *hb = NULL; | |
| 12 | 4007 gint y; |
| 4008 | |
| 1 | 4009 undraw_cursor(html); |
| 4010 | |
| 4011 if (!html->html_bits) | |
| 4012 return; | |
| 4013 | |
| 4014 if (!html->cursor_hb) | |
| 12 | 4015 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data; |
| 1 | 4016 |
| 4017 y = html->cursor_hb->y; | |
| 12 | 4018 |
| 4019 while (hbits) | |
| 4020 { | |
| 4021 hb = (GtkHtmlBit *) hbits->data; | |
| 4022 | |
| 4023 if (y != hb->y) | |
| 4024 { | |
| 4025 hb = (GtkHtmlBit *) hbits->next->data; | |
| 1 | 4026 break; |
| 4027 } | |
| 12 | 4028 |
| 1 | 4029 hbits = hbits->prev; |
| 4030 } | |
| 4031 if (!hbits) | |
| 12 | 4032 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data; |
| 1 | 4033 else |
| 4034 html->cursor_hb = hb; | |
| 4035 | |
| 4036 html->cursor_pos = 0; | |
| 4037 | |
| 4038 | |
| 4039 draw_cursor(html); | |
| 4040 | |
| 4041 | |
| 4042 } | |
| 4043 | |
| 12 | 4044 static void move_end_of_line(GtkHtml * html) |
| 1 | 4045 { |
| 4046 GList *hbits = g_list_find(html->html_bits, html->cursor_hb); | |
| 4047 GtkHtmlBit *hb = NULL; | |
| 12 | 4048 gint y; |
| 4049 | |
| 1 | 4050 undraw_cursor(html); |
| 4051 | |
| 4052 if (!html->html_bits) | |
| 4053 return; | |
| 4054 | |
| 4055 if (!html->cursor_hb) | |
| 12 | 4056 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data; |
| 1 | 4057 |
| 4058 y = html->cursor_hb->y; | |
| 12 | 4059 |
| 4060 while (hbits) | |
| 4061 { | |
| 4062 hb = (GtkHtmlBit *) hbits->data; | |
| 4063 | |
| 4064 if (y != hb->y) | |
| 4065 { | |
| 4066 hb = (GtkHtmlBit *) hbits->prev->data; | |
| 1 | 4067 break; |
| 4068 } | |
| 12 | 4069 |
| 1 | 4070 hbits = hbits->next; |
| 4071 } | |
| 4072 if (!hbits) | |
| 12 | 4073 html->cursor_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data; |
| 1 | 4074 else |
| 4075 html->cursor_hb = hb; | |
| 4076 | |
| 4077 html->cursor_pos = strlen(html->cursor_hb->text); | |
| 4078 | |
| 4079 | |
| 4080 draw_cursor(html); | |
| 4081 | |
| 4082 | |
| 4083 } | |
| 4084 | |
| 4085 | |
| 4086 | |
| 12 | 4087 static gint gtk_html_key_press(GtkWidget * widget, GdkEventKey * event) |
| 1 | 4088 { |
| 4089 GtkHtml *html; | |
| 4090 gchar key; | |
| 4091 gint return_val; | |
| 12 | 4092 |
| 4093 g_return_val_if_fail(widget != NULL, FALSE); | |
| 4094 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE); | |
| 4095 g_return_val_if_fail(event != NULL, FALSE); | |
| 4096 | |
| 1 | 4097 return_val = FALSE; |
| 12 | 4098 |
| 4099 html = GTK_HTML(widget); | |
| 4100 | |
| 1 | 4101 key = event->keyval; |
| 4102 return_val = TRUE; | |
| 4103 | |
| 4104 | |
| 12 | 4105 if (html->editable == FALSE) |
| 4106 { | |
| 4107 /* | |
| 4108 * switch (event->keyval) { | |
| 4109 * case GDK_Home: | |
| 4110 * if (event->state & GDK_CONTROL_MASK) | |
| 4111 * scroll_int (text, -text->vadj->value); | |
| 4112 * else | |
| 4113 * return_val = FALSE; | |
| 4114 * break; | |
| 4115 * case GDK_End: | |
| 4116 * if (event->state & GDK_CONTROL_MASK) | |
| 4117 * scroll_int (text, +text->vadj->upper); | |
| 4118 * else | |
| 4119 * return_val = FALSE; | |
| 4120 * break; | |
| 4121 * case GDK_Page_Up: scroll_int (text, -text->vadj->page_increment); break; | |
| 4122 * case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break; | |
| 4123 * case GDK_Up: scroll_int (text, -KEY_SCROLL_PIXELS); break; | |
| 4124 * case GDK_Down: scroll_int (text, +KEY_SCROLL_PIXELS); break; | |
| 4125 * case GDK_Return: | |
| 4126 * if (event->state & GDK_CONTROL_MASK) | |
| 4127 * gtk_signal_emit_by_name (GTK_OBJECT (text), "activate"); | |
| 4128 * else | |
| 4129 * return_val = FALSE; | |
| 4130 * break; | |
| 4131 * default: | |
| 4132 * return_val = FALSE; | |
| 4133 * break; | |
| 4134 * } | |
| 4135 */ | |
| 4136 } | |
| 4137 else | |
| 4138 { | |
| 4139 | |
| 4140 switch (event->keyval) | |
| 4141 { | |
| 1 | 4142 case GDK_Home: |
| 12 | 4143 move_beginning_of_line(html); |
| 1 | 4144 break; |
| 4145 case GDK_End: | |
| 12 | 4146 move_end_of_line(html); |
| 1 | 4147 break; |
| 4148 /* | |
| 12 | 4149 * case GDK_Page_Up: |
| 4150 * move_cursor_page_ver (html, -1); | |
| 4151 * break; | |
| 4152 * case GDK_Page_Down: | |
| 4153 * move_cursor_page_ver (html, +1); | |
| 4154 * break; | |
| 4155 */ | |
| 4156 /* | |
| 4157 * CUA has Ctrl-Up/Ctrl-Down as paragraph up down | |
| 4158 */ | |
| 1 | 4159 case GDK_Up: |
| 12 | 4160 move_cursor_ver(html, -1); |
| 1 | 4161 break; |
| 4162 case GDK_Down: | |
| 12 | 4163 move_cursor_ver(html, +1); |
| 1 | 4164 break; |
| 4165 case GDK_Left: | |
| 12 | 4166 move_cursor_hor(html, -1); |
| 1 | 4167 break; |
| 4168 case GDK_Right: | |
| 12 | 4169 move_cursor_hor(html, +1); |
| 1 | 4170 break; |
| 4171 #if 0 | |
| 4172 case GDK_BackSpace: | |
| 4173 if (event->state & GDK_CONTROL_MASK) | |
| 12 | 4174 gtk_text_delete_backward_word(text); |
| 1 | 4175 else |
| 12 | 4176 gtk_text_delete_backward_character(text); |
| 1 | 4177 break; |
| 4178 case GDK_Clear: | |
| 12 | 4179 gtk_text_delete_line(text); |
| 1 | 4180 break; |
| 4181 case GDK_Insert: | |
| 4182 if (event->state & GDK_SHIFT_MASK) | |
| 4183 { | |
| 4184 extend_selection = FALSE; | |
| 12 | 4185 gtk_editable_paste_clipboard(editable); |
| 1 | 4186 } |
| 4187 else if (event->state & GDK_CONTROL_MASK) | |
| 4188 { | |
| 12 | 4189 gtk_editable_copy_clipboard(editable); |
| 1 | 4190 } |
| 4191 else | |
| 4192 { | |
| 12 | 4193 /* |
| 4194 * gtk_toggle_insert(text) -- IMPLEMENT | |
| 4195 */ | |
| 1 | 4196 } |
| 4197 break; | |
| 4198 case GDK_Delete: | |
| 4199 if (event->state & GDK_CONTROL_MASK) | |
| 12 | 4200 gtk_text_delete_forward_word(text); |
| 1 | 4201 else if (event->state & GDK_SHIFT_MASK) |
| 4202 { | |
| 4203 extend_selection = FALSE; | |
| 12 | 4204 gtk_editable_cut_clipboard(editable); |
| 1 | 4205 } |
| 4206 else | |
| 12 | 4207 gtk_text_delete_forward_character(text); |
| 1 | 4208 break; |
| 4209 case GDK_Tab: | |
| 4210 position = text->point.index; | |
| 12 | 4211 gtk_editable_insert_text(editable, "\t", 1, &position); |
| 1 | 4212 break; |
| 4213 case GDK_Return: | |
| 4214 if (event->state & GDK_CONTROL_MASK) | |
| 12 | 4215 gtk_signal_emit_by_name(GTK_OBJECT(text), "activate"); |
| 1 | 4216 else |
| 4217 { | |
| 4218 position = text->point.index; | |
| 12 | 4219 gtk_editable_insert_text(editable, "\n", 1, &position); |
| 1 | 4220 } |
| 4221 break; | |
| 4222 case GDK_Escape: | |
| 12 | 4223 /* |
| 4224 * Don't insert literally | |
| 4225 */ | |
| 1 | 4226 return_val = FALSE; |
| 4227 break; | |
| 4228 #endif | |
| 4229 default: | |
| 4230 return_val = FALSE; | |
| 4231 | |
| 4232 #if 0 | |
| 12 | 4233 if (event->state & GDK_CONTROL_MASK) |
| 4234 { | |
| 1 | 4235 if ((key >= 'A') && (key <= 'Z')) |
| 4236 key -= 'A' - 'a'; | |
| 4237 | |
| 12 | 4238 if ((key >= 'a') && (key <= 'z') |
| 4239 && control_keys[(int) (key - 'a')]) | |
| 1 | 4240 { |
| 12 | 4241 (*control_keys[(int) (key - 'a')]) (editable, event->time); |
| 1 | 4242 return_val = TRUE; |
| 4243 } | |
| 4244 | |
| 4245 break; | |
| 4246 } | |
| 4247 else if (event->state & GDK_MOD1_MASK) | |
| 4248 { | |
| 4249 if ((key >= 'A') && (key <= 'Z')) | |
| 4250 key -= 'A' - 'a'; | |
| 4251 | |
| 4252 if ((key >= 'a') && (key <= 'z') && alt_keys[(int) (key - 'a')]) | |
| 4253 { | |
| 12 | 4254 (*alt_keys[(int) (key - 'a')]) (editable, event->time); |
| 1 | 4255 return_val = TRUE; |
| 4256 } | |
| 4257 break; | |
| 4258 } | |
| 4259 #endif | |
| 4260 /* | |
| 12 | 4261 * if (event->length > 0) { |
| 4262 * html->cursor_pos++; | |
| 4263 * gtk_editable_insert_text (editable, event->string, event->length, &position); | |
| 4264 * | |
| 4265 * return_val = TRUE; | |
| 4266 * } | |
| 4267 * else | |
| 4268 * return_val = FALSE; | |
| 4269 */ | |
| 1 | 4270 } |
| 4271 | |
| 4272 } | |
| 4273 | |
| 4274 return return_val; | |
| 4275 } | |
| 12 | 4276 |
| 4277 void gtk_html_freeze(GtkHtml * html) | |
| 1 | 4278 { |
| 12 | 4279 g_return_if_fail(html != NULL); |
| 4280 g_return_if_fail(GTK_IS_HTML(html)); | |
| 1 | 4281 |
| 4282 html->frozen++; | |
| 4283 } | |
| 4284 | |
| 12 | 4285 void gtk_html_thaw(GtkHtml * html) |
| 1 | 4286 { |
| 4287 GdkRectangle area; | |
| 12 | 4288 |
| 4289 g_return_if_fail(html != NULL); | |
| 4290 g_return_if_fail(GTK_IS_HTML(html)); | |
| 1 | 4291 |
|
481
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
4292 gtk_html_append_text(html, NULL, 0); |
|
64afc8f41bcb
[gaim-migrate @ 491]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
353
diff
changeset
|
4293 |
| 1 | 4294 html->frozen--; |
| 4295 | |
| 4296 if (html->frozen < 0) | |
| 12 | 4297 html->frozen = 0; |
| 4298 | |
| 4299 if (html->frozen == 0) | |
| 4300 { | |
| 4301 if (html->html_area) | |
| 4302 { | |
| 4303 gint width, | |
| 4304 height; | |
| 1 | 4305 area.x = 0; |
| 4306 area.y = 0; | |
| 4307 | |
| 4308 gdk_window_get_size(html->html_area, &width, &height); | |
| 4309 | |
| 12 | 4310 area.width = width; |
| 4311 area.height = height; | |
| 4312 | |
| 1 | 4313 expose_html(html, &area, TRUE); |
| 4314 } | |
| 4315 } | |
| 4316 } |
