Mercurial > pidgin
annotate src/gtkimhtml.c @ 6104:29ddc42ff402
[gaim-migrate @ 6565]
Make gaim not crash when signing off an account that has had a message
notify window closed for it. Previously Gaim was freeing the widget but
not removing it from the linked list, so gaim attempted to free it again
at sign off.
"There's been a lot of talk, about this next song. Maybe a little too much
talk. This song is not a rebel song. This song is Sunday, Bloody Sunday."
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Sun, 13 Jul 2003 07:58:32 +0000 |
| parents | c99959f1bb73 |
| children | 16fd7811effd |
| rev | line source |
|---|---|
| 1428 | 1 /* |
| 2 * GtkIMHtml | |
| 3 * | |
| 4 * Copyright (C) 2000, Eric Warmenhoven <warmenhoven@yahoo.com> | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or modify | |
| 7 * under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU General Public License | |
| 17 * along with this program; if not, write to the Free Software | |
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 * | |
| 20 */ | |
| 21 | |
|
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
22 #ifdef HAVE_CONFIG_H |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
23 #include <config.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
24 #endif |
| 1428 | 25 #include "gtkimhtml.h" |
| 26 #include <gtk/gtk.h> | |
| 4895 | 27 #include <glib/gerror.h> |
| 4046 | 28 #include <gdk/gdkkeysyms.h> |
| 1428 | 29 #include <string.h> |
| 30 #include <ctype.h> | |
| 31 #include <stdio.h> | |
| 4629 | 32 #include <stdlib.h> |
| 1428 | 33 #include <math.h> |
|
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
34 #ifdef HAVE_LANGINFO_CODESET |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
35 #include <langinfo.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
36 #include <locale.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
37 #endif |
| 1428 | 38 |
| 4417 | 39 #ifdef ENABLE_NLS |
| 40 # include <libintl.h> | |
| 41 # define _(x) gettext(x) | |
| 42 # ifdef gettext_noop | |
| 43 # define N_(String) gettext_noop (String) | |
| 44 # else | |
| 45 # define N_(String) (String) | |
| 46 # endif | |
| 47 #else | |
| 48 # define N_(String) (String) | |
| 49 # define _(x) (x) | |
| 50 #endif | |
| 51 | |
| 4735 | 52 #include <pango/pango-font.h> |
| 53 | |
| 5105 | 54 /* GTK+ < 2.2.2 hack, see ui.h for details. */ |
| 55 #ifndef GTK_WRAP_WORD_CHAR | |
| 56 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD | |
| 57 #endif | |
| 58 | |
| 4735 | 59 #define TOOLTIP_TIMEOUT 500 |
| 60 | |
| 3922 | 61 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a |
| 62 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | |
| 63 #define MAX_FONT_SIZE 7 | |
| 5367 | 64 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
| 3928 | 65 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; |
|
2349
60c716c32c40
[gaim-migrate @ 2362]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2348
diff
changeset
|
66 |
| 4032 | 67 static GtkSmileyTree* |
| 68 gtk_smiley_tree_new () | |
| 69 { | |
| 70 return g_new0 (GtkSmileyTree, 1); | |
| 71 } | |
| 72 | |
| 73 static void | |
| 74 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
| 4263 | 75 GtkIMHtmlSmiley *smiley) |
| 4032 | 76 { |
| 77 GtkSmileyTree *t = tree; | |
| 4263 | 78 const gchar *x = smiley->smile; |
| 4032 | 79 |
| 80 if (!strlen (x)) | |
| 81 return; | |
| 82 | |
| 83 while (*x) { | |
| 84 gchar *pos; | |
| 85 gint index; | |
| 86 | |
| 87 if (!t->values) | |
| 88 t->values = g_string_new (""); | |
| 89 | |
| 90 pos = strchr (t->values->str, *x); | |
| 91 if (!pos) { | |
| 92 t->values = g_string_append_c (t->values, *x); | |
| 93 index = t->values->len - 1; | |
| 94 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
| 95 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
| 96 } else | |
| 97 index = (int) pos - (int) t->values->str; | |
| 98 | |
| 99 t = t->children [index]; | |
| 100 | |
| 101 x++; | |
| 102 } | |
| 103 | |
| 4263 | 104 t->image = smiley; |
| 4032 | 105 } |
| 4041 | 106 |
| 4263 | 107 |
| 4264 | 108 void gtk_smiley_tree_destroy (GtkSmileyTree *tree) |
| 4032 | 109 { |
| 110 GSList *list = g_slist_append (NULL, tree); | |
| 111 | |
| 112 while (list) { | |
| 113 GtkSmileyTree *t = list->data; | |
| 114 gint i; | |
| 115 list = g_slist_remove(list, t); | |
| 116 if (t->values) { | |
| 117 for (i = 0; i < t->values->len; i++) | |
| 118 list = g_slist_append (list, t->children [i]); | |
| 119 g_string_free (t->values, TRUE); | |
| 120 g_free (t->children); | |
| 121 } | |
| 122 g_free (t); | |
| 123 } | |
| 124 } | |
| 125 | |
| 5967 | 126 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
| 127 { | |
| 128 GdkRectangle rect; | |
| 129 | |
| 130 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); | |
| 131 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ | |
| 132 GList *iter = GTK_IMHTML(widget)->scalables; | |
| 133 | |
| 134 while(iter){ | |
| 135 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data); | |
| 136 scale->scale(scale, rect.width, rect.height); | |
| 137 | |
| 138 iter = iter->next; | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 widget->old_rect = rect; | |
| 143 return FALSE; | |
| 144 } | |
| 145 | |
| 146 static gint | |
| 147 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
| 148 { | |
| 149 PangoLayout *layout; | |
| 150 | |
| 151 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
| 152 | |
| 153 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
| 154 | |
| 155 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, | |
| 156 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, | |
| 157 "tooltip", 0, 0, -1, -1); | |
| 158 | |
| 159 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
| 160 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
| 161 | |
| 162 g_object_unref(layout); | |
| 163 return FALSE; | |
| 164 } | |
| 165 | |
| 166 static gint | |
| 167 gtk_imhtml_tip (gpointer data) | |
| 168 { | |
| 169 GtkIMHtml *imhtml = data; | |
| 170 PangoFontMetrics *font; | |
| 171 PangoLayout *layout; | |
| 172 | |
| 173 gint gap, x, y, h, w, scr_w, baseline_skip; | |
| 174 | |
| 175 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
| 176 | |
| 177 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
| 178 imhtml->tip_timer = 0; | |
| 179 return FALSE; | |
| 180 } | |
| 181 | |
| 182 if (imhtml->tip_window){ | |
| 183 gtk_widget_destroy (imhtml->tip_window); | |
| 184 imhtml->tip_window = NULL; | |
| 185 } | |
| 186 | |
| 187 imhtml->tip_timer = 0; | |
| 188 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
| 189 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
| 190 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
| 191 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
| 192 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
| 193 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
| 194 | |
| 195 gtk_widget_ensure_style (imhtml->tip_window); | |
| 196 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
| 197 font = pango_font_get_metrics(pango_context_load_font(pango_layout_get_context(layout), | |
| 198 imhtml->tip_window->style->font_desc), | |
| 199 NULL); | |
| 200 | |
| 201 | |
| 202 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
| 203 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + | |
| 204 pango_font_metrics_get_descent(font))/ 4); | |
| 205 | |
| 206 if (gap < 2) | |
| 207 gap = 2; | |
| 208 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
| 209 pango_font_metrics_get_descent(font)); | |
| 210 w = 8 + scr_w; | |
| 211 h = 8 + baseline_skip; | |
| 212 | |
| 213 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
| 214 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
| 215 y += GTK_WIDGET(imhtml)->allocation.y; | |
| 216 | |
| 217 scr_w = gdk_screen_width(); | |
| 218 | |
| 219 x -= ((w >> 1) + 4); | |
| 220 | |
| 221 if ((x + w) > scr_w) | |
| 222 x -= (x + w) - scr_w; | |
| 223 else if (x < 0) | |
| 224 x = 0; | |
| 225 | |
| 226 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
| 227 pango_font_metrics_get_descent(font)); | |
| 228 | |
| 229 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
| 230 gtk_widget_show (imhtml->tip_window); | |
| 231 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
| 232 | |
| 233 pango_font_metrics_unref(font); | |
| 234 g_object_unref(layout); | |
| 235 | |
| 236 return FALSE; | |
| 237 } | |
| 238 | |
| 239 gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) | |
| 240 { | |
| 241 GtkTextIter iter; | |
| 242 GdkWindow *win = event->window; | |
| 243 int x, y; | |
| 244 char *tip = NULL; | |
| 245 GSList *tags = NULL, *templist = NULL; | |
| 246 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); | |
| 247 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, | |
| 248 event->x, event->y, &x, &y); | |
| 249 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
| 250 tags = gtk_text_iter_get_tags(&iter); | |
| 251 | |
| 252 templist = tags; | |
| 253 while (templist) { | |
| 254 GtkTextTag *tag = templist->data; | |
| 255 tip = g_object_get_data(G_OBJECT(tag), "link_url"); | |
| 256 if (tip) | |
| 257 break; | |
| 258 templist = templist->next; | |
| 259 } | |
| 260 | |
| 261 if (GTK_IMHTML(imhtml)->tip) { | |
| 262 if ((tip == GTK_IMHTML(imhtml)->tip)) { | |
| 263 return FALSE; | |
| 264 } | |
| 265 /* We've left the cell. Remove the timeout and create a new one below */ | |
| 266 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 267 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 268 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 269 } | |
| 270 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 271 if (GTK_IMHTML(imhtml)->tip_timer) | |
| 272 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 273 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 274 } | |
| 275 | |
| 276 if(tip){ | |
| 277 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); | |
| 278 GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, | |
| 279 gtk_imhtml_tip, imhtml); | |
| 280 } | |
| 281 | |
| 282 GTK_IMHTML(imhtml)->tip = tip; | |
| 283 g_slist_free(tags); | |
| 284 return FALSE; | |
| 285 } | |
| 286 | |
| 287 gboolean gtk_leave_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) | |
| 288 { | |
| 289 /* when leaving the widget, clear any current & pending tooltips and restore the cursor */ | |
| 290 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 291 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 292 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 293 } | |
| 294 if (GTK_IMHTML(imhtml)->tip_timer) { | |
| 295 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 296 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 297 } | |
| 298 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 299 | |
| 300 /* propogate the event normally */ | |
| 301 return FALSE; | |
| 302 } | |
| 303 | |
| 6066 | 304 /* |
| 305 * XXX - This should be removed eventually. | |
| 306 * | |
| 307 * This function exists to work around a gross bug in GtkTextView. | |
| 308 * Basically, we short circuit ctrl+a and ctrl+end because they make | |
| 309 * el program go boom. | |
| 310 * | |
| 311 * It's supposed to be fixed in gtk2.2. You can view the bug report at | |
| 312 * http://bugzilla.gnome.org/show_bug.cgi?id=107939 | |
| 313 */ | |
| 314 gboolean gtk_key_pressed_cb(GtkWidget *imhtml, GdkEventKey *event, gpointer data) | |
| 315 { | |
| 316 if (event->state & GDK_CONTROL_MASK) | |
| 317 switch (event->keyval) { | |
| 318 case 'a': | |
| 319 return TRUE; | |
| 320 break; | |
| 321 | |
| 322 case GDK_Home: | |
| 323 return TRUE; | |
| 324 break; | |
| 325 | |
| 326 case GDK_End: | |
| 327 return TRUE; | |
| 328 break; | |
| 329 } | |
| 330 | |
| 331 return FALSE; | |
| 332 } | |
| 333 | |
| 5967 | 334 |
| 4263 | 335 |
| 4032 | 336 static GtkTextViewClass *parent_class = NULL; |
| 337 | |
| 3922 | 338 /* GtkIMHtml has one signal--URL_CLICKED */ |
| 1428 | 339 enum { |
| 340 URL_CLICKED, | |
| 341 LAST_SIGNAL | |
| 342 }; | |
| 343 static guint signals [LAST_SIGNAL] = { 0 }; | |
| 344 | |
| 4032 | 345 static void |
| 346 gtk_imhtml_finalize (GObject *object) | |
| 347 { | |
| 348 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
| 4895 | 349 GList *scalables; |
| 350 | |
| 4138 | 351 g_hash_table_destroy(imhtml->smiley_data); |
| 4032 | 352 gtk_smiley_tree_destroy(imhtml->default_smilies); |
| 4138 | 353 gdk_cursor_unref(imhtml->hand_cursor); |
| 354 gdk_cursor_unref(imhtml->arrow_cursor); | |
| 4735 | 355 if(imhtml->tip_window){ |
| 356 gtk_widget_destroy(imhtml->tip_window); | |
| 357 } | |
| 358 if(imhtml->tip_timer) | |
| 359 gtk_timeout_remove(imhtml->tip_timer); | |
| 360 | |
| 4895 | 361 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
| 362 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
| 363 scale->free(scale); | |
| 364 } | |
| 365 | |
| 366 g_list_free(imhtml->scalables); | |
| 4032 | 367 G_OBJECT_CLASS(parent_class)->finalize (object); |
| 368 } | |
| 1428 | 369 |
| 3922 | 370 /* Boring GTK stuff */ |
| 371 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) | |
| 1428 | 372 { |
| 3922 | 373 GtkObjectClass *object_class; |
| 4032 | 374 GObjectClass *gobject_class; |
| 3922 | 375 object_class = (GtkObjectClass*) class; |
| 4032 | 376 gobject_class = (GObjectClass*) class; |
| 377 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); | |
| 4417 | 378 signals[URL_CLICKED] = g_signal_new("url_clicked", |
| 379 G_TYPE_FROM_CLASS(gobject_class), | |
| 380 G_SIGNAL_RUN_FIRST, | |
| 381 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
| 382 NULL, | |
| 383 0, | |
| 384 g_cclosure_marshal_VOID__POINTER, | |
| 385 G_TYPE_NONE, 1, | |
| 386 G_TYPE_POINTER); | |
| 4032 | 387 gobject_class->finalize = gtk_imhtml_finalize; |
| 1428 | 388 } |
| 389 | |
| 3922 | 390 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
| 1428 | 391 { |
| 3922 | 392 GtkTextIter iter; |
| 393 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
| 394 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
| 395 imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); | |
| 396 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
| 5105 | 397 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
| 3922 | 398 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), FALSE); |
| 399 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); | |
| 400 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), FALSE); | |
| 401 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ | |
| 3465 | 402 |
| 3922 | 403 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
| 404 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ | |
| 405 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); | |
| 406 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
| 407 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
| 408 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
| 409 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
| 410 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
| 411 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
| 3465 | 412 |
| 3922 | 413 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
| 414 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
| 415 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
| 2993 | 416 |
| 4253 | 417 imhtml->show_smileys = TRUE; |
| 418 | |
| 4892 | 419 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 4902 | 420 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
| 4032 | 421 imhtml->default_smilies = gtk_smiley_tree_new(); |
| 4735 | 422 |
| 4944 | 423 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
| 4735 | 424 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
| 4944 | 425 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
| 6066 | 426 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
| 4944 | 427 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
| 4735 | 428 |
| 429 imhtml->tip = NULL; | |
| 430 imhtml->tip_timer = 0; | |
| 431 imhtml->tip_window = NULL; | |
| 4895 | 432 |
| 433 imhtml->scalables = NULL; | |
| 6066 | 434 |
| 435 gtk_text_buffer_create_tag(imhtml->text_buffer, "comment", "invisible", FALSE, NULL); | |
| 2993 | 436 } |
| 437 | |
| 3922 | 438 GtkWidget *gtk_imhtml_new(void *a, void *b) |
| 1428 | 439 { |
| 4635 | 440 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
| 1428 | 441 } |
| 442 | |
| 4635 | 443 GType gtk_imhtml_get_type() |
| 1428 | 444 { |
| 4635 | 445 static GType imhtml_type = 0; |
| 1428 | 446 |
| 447 if (!imhtml_type) { | |
| 4635 | 448 static const GTypeInfo imhtml_info = { |
| 449 sizeof(GtkIMHtmlClass), | |
| 450 NULL, | |
| 451 NULL, | |
| 452 (GClassInitFunc) gtk_imhtml_class_init, | |
| 453 NULL, | |
| 454 NULL, | |
| 1428 | 455 sizeof (GtkIMHtml), |
| 4635 | 456 0, |
| 457 (GInstanceInitFunc) gtk_imhtml_init | |
| 1428 | 458 }; |
| 4635 | 459 |
| 460 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
| 461 "GtkIMHtml", &imhtml_info, 0); | |
| 1428 | 462 } |
| 463 | |
| 464 return imhtml_type; | |
| 465 } | |
| 466 | |
| 4417 | 467 struct url_data { |
| 468 GObject *object; | |
| 469 gchar *url; | |
| 470 }; | |
| 471 | |
| 472 static void url_open(GtkWidget *w, struct url_data *data) { | |
| 473 if(!data) return; | |
| 474 | |
| 475 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); | |
| 476 | |
| 477 g_object_unref(data->object); | |
| 478 g_free(data->url); | |
| 479 g_free(data); | |
| 480 } | |
| 5582 | 481 |
| 4417 | 482 static void url_copy(GtkWidget *w, gchar *url) { |
| 483 GtkClipboard *clipboard; | |
| 484 | |
|
5293
ead927e2543f
[gaim-migrate @ 5665]
Christian Hammond <chipx86@chipx86.com>
parents:
5282
diff
changeset
|
485 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
| 4417 | 486 gtk_clipboard_set_text(clipboard, url, -1); |
| 5582 | 487 |
| 488 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | |
| 489 gtk_clipboard_set_text(clipboard, url, -1); | |
| 4417 | 490 } |
| 491 | |
| 492 /* The callback for an event on a link tag. */ | |
| 5091 | 493 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, char *url) { |
| 4417 | 494 GdkEventButton *event_button = (GdkEventButton *) event; |
| 495 | |
| 3922 | 496 if (event->type == GDK_BUTTON_RELEASE) { |
| 4417 | 497 if (event_button->button == 1) { |
| 498 GtkTextIter start, end; | |
| 499 /* we shouldn't open a URL if the user has selected something: */ | |
| 500 gtk_text_buffer_get_selection_bounds( | |
| 501 gtk_text_iter_get_buffer(arg2), &start, &end); | |
| 502 if(gtk_text_iter_get_offset(&start) != | |
| 503 gtk_text_iter_get_offset(&end)) | |
| 504 return FALSE; | |
| 505 | |
| 506 /* A link was clicked--we emit the "url_clicked" signal | |
| 507 * with the URL as the argument */ | |
| 5091 | 508 g_signal_emit(imhtml, signals[URL_CLICKED], 0, url); |
| 4417 | 509 return FALSE; |
| 510 } else if(event_button->button == 3) { | |
| 4745 | 511 GtkWidget *img, *item, *menu; |
| 4417 | 512 struct url_data *tempdata = g_new(struct url_data, 1); |
| 5091 | 513 tempdata->object = g_object_ref(imhtml); |
| 4417 | 514 tempdata->url = g_strdup(url); |
| 4745 | 515 |
| 5091 | 516 /* Don't want the tooltip around if user right-clicked on link */ |
| 517 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 518 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 519 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 520 } | |
| 521 if (GTK_IMHTML(imhtml)->tip_timer) { | |
| 522 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 523 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 524 } | |
| 525 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 4417 | 526 menu = gtk_menu_new(); |
| 4745 | 527 |
| 4417 | 528 /* buttons and such */ |
| 529 img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); | |
| 4420 | 530 item = gtk_image_menu_item_new_with_mnemonic(_("_Copy Link Location")); |
| 4417 | 531 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 532 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_copy), | |
| 533 url); | |
| 534 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
| 535 | |
| 536 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); | |
| 4420 | 537 item = gtk_image_menu_item_new_with_mnemonic(_("_Open Link in Browser")); |
| 4417 | 538 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 539 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_open), | |
| 540 tempdata); | |
| 541 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
| 4756 | 542 |
| 4417 | 543 gtk_widget_show_all(menu); |
| 4756 | 544 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
| 545 event_button->button, event_button->time); | |
| 4745 | 546 |
| 4417 | 547 return TRUE; |
| 548 } | |
| 1428 | 549 } |
| 4417 | 550 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
| 551 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
| 552 be caught by the regular GtkTextView menu */ | |
| 553 else | |
| 554 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
| 1428 | 555 } |
| 556 | |
| 4298 | 557 /* this isn't used yet |
| 4032 | 558 static void |
| 4263 | 559 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
| 560 GtkIMHtmlSmiley *smiley) | |
| 4032 | 561 { |
| 562 GtkSmileyTree *t = tree; | |
| 4263 | 563 const gchar *x = smiley->smile; |
| 4032 | 564 gint len = 0; |
| 565 | |
| 566 while (*x) { | |
| 567 gchar *pos; | |
| 568 | |
| 569 if (!t->values) | |
| 570 return; | |
| 571 | |
| 572 pos = strchr (t->values->str, *x); | |
| 573 if (pos) | |
| 574 t = t->children [(int) pos - (int) t->values->str]; | |
| 575 else | |
| 576 return; | |
| 577 | |
| 578 x++; len++; | |
| 579 } | |
| 580 | |
|
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
581 if (t->image) { |
| 4032 | 582 t->image = NULL; |
|
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
583 } |
| 4032 | 584 } |
| 4298 | 585 */ |
| 586 | |
| 4032 | 587 |
| 588 static gint | |
| 589 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
| 590 const gchar *text) | |
| 591 { | |
| 592 GtkSmileyTree *t = tree; | |
| 593 const gchar *x = text; | |
| 594 gint len = 0; | |
| 595 | |
| 596 while (*x) { | |
| 597 gchar *pos; | |
| 598 | |
| 599 if (!t->values) | |
| 600 break; | |
| 601 | |
| 602 pos = strchr (t->values->str, *x); | |
| 603 if (pos) | |
| 604 t = t->children [(int) pos - (int) t->values->str]; | |
| 605 else | |
| 606 break; | |
| 607 | |
| 608 x++; len++; | |
| 609 } | |
| 610 | |
| 611 if (t->image) | |
| 612 return len; | |
| 613 | |
| 614 return 0; | |
| 615 } | |
| 616 | |
| 617 void | |
| 4263 | 618 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
| 619 gchar *sml, | |
| 620 GtkIMHtmlSmiley *smiley) | |
| 4032 | 621 { |
| 622 GtkSmileyTree *tree; | |
| 623 g_return_if_fail (imhtml != NULL); | |
| 624 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
| 4263 | 625 |
| 4032 | 626 if (sml == NULL) |
| 627 tree = imhtml->default_smilies; | |
| 628 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
| 629 } else { | |
| 630 tree = gtk_smiley_tree_new(); | |
| 4892 | 631 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
| 4032 | 632 } |
| 633 | |
| 4263 | 634 gtk_smiley_tree_insert (tree, smiley); |
| 4032 | 635 } |
| 636 | |
| 637 static gboolean | |
| 638 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
| 639 GSList *fonts, | |
| 640 const gchar *text, | |
| 641 gint *len) | |
| 642 { | |
| 643 GtkSmileyTree *tree; | |
| 5967 | 644 GtkIMHtmlFontDetail *font; |
| 4032 | 645 char *sml = NULL; |
| 646 | |
| 647 if (fonts) { | |
| 648 font = fonts->data; | |
| 649 sml = font->sml; | |
| 650 } | |
| 651 | |
| 652 if (sml == NULL) | |
| 653 tree = imhtml->default_smilies; | |
| 654 else { | |
| 655 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
| 656 } | |
| 657 if (tree == NULL) | |
| 658 return FALSE; | |
| 659 | |
| 660 *len = gtk_smiley_tree_lookup (tree, text); | |
| 661 return (*len > 0); | |
| 662 } | |
| 663 | |
| 4263 | 664 GdkPixbuf* |
| 4032 | 665 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
| 666 const gchar *sml, | |
| 667 const gchar *text) | |
| 668 { | |
| 669 GtkSmileyTree *t; | |
| 670 const gchar *x = text; | |
| 671 if (sml == NULL) | |
| 672 t = imhtml->default_smilies; | |
| 673 else | |
| 674 t = g_hash_table_lookup(imhtml->smiley_data, sml); | |
| 675 | |
| 676 | |
| 677 if (t == NULL) | |
| 678 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 679 | |
| 680 while (*x) { | |
| 681 gchar *pos; | |
| 682 | |
| 683 if (!t->values) { | |
| 684 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 685 } | |
| 686 | |
| 687 pos = strchr (t->values->str, *x); | |
| 688 if (pos) { | |
| 689 t = t->children [(int) pos - (int) t->values->str]; | |
| 690 } else { | |
| 691 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 692 } | |
| 693 x++; | |
| 694 } | |
| 695 | |
| 4263 | 696 if (!t->image->icon) |
| 697 t->image->icon = gdk_pixbuf_new_from_file(t->image->file, NULL); | |
| 698 | |
| 699 return t->image->icon; | |
| 4032 | 700 } |
| 4793 | 701 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
| 3922 | 702 *tag = g_strndup (string, strlen (x)); \ |
| 703 *len = strlen (x) + 1; \ | |
| 704 return TRUE; \ | |
| 705 } \ | |
| 706 (*type)++ | |
| 1428 | 707 |
| 4793 | 708 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
| 3922 | 709 const gchar *c = string + strlen (x " "); \ |
| 710 gchar e = '"'; \ | |
| 711 gboolean quote = FALSE; \ | |
| 712 while (*c) { \ | |
| 713 if (*c == '"' || *c == '\'') { \ | |
| 714 if (quote && (*c == e)) \ | |
| 715 quote = !quote; \ | |
| 716 else if (!quote) { \ | |
| 717 quote = !quote; \ | |
| 718 e = *c; \ | |
| 719 } \ | |
| 720 } else if (!quote && (*c == '>')) \ | |
| 721 break; \ | |
| 722 c++; \ | |
| 723 } \ | |
| 724 if (*c) { \ | |
| 725 *tag = g_strndup (string, c - string); \ | |
| 726 *len = c - string + 1; \ | |
| 727 return TRUE; \ | |
| 728 } \ | |
| 729 } \ | |
| 730 (*type)++ | |
| 1428 | 731 |
| 732 | |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
733 static gboolean |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
734 gtk_imhtml_is_amp_escape (const gchar *string, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
735 gchar *replace, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
736 gint *length) |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
737 { |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
738 g_return_val_if_fail (string != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
739 g_return_val_if_fail (replace != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
740 g_return_val_if_fail (length != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
741 |
| 4793 | 742 if (!g_ascii_strncasecmp (string, "&", 5)) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
743 *replace = '&'; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
744 *length = 5; |
| 4793 | 745 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
746 *replace = '<'; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
747 *length = 4; |
| 4793 | 748 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
749 *replace = '>'; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
750 *length = 4; |
| 4793 | 751 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
752 *replace = ' '; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
753 *length = 6; |
| 4793 | 754 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
755 *replace = '©'; /* was: '©' */ |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
756 *length = 6; |
| 4793 | 757 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
758 *replace = '\"'; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
759 *length = 6; |
| 4793 | 760 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
761 *replace = '®'; /* was: '®' */ |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
762 *length = 5; |
| 5093 | 763 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
| 764 *replace = '\''; | |
| 765 *length = 6; | |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
766 } else if (*(string + 1) == '#') { |
|
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
767 guint pound = 0; |
| 3004 | 768 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
769 if (*(string + 3 + (gint)log10 (pound)) != ';') |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
770 return FALSE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
771 *replace = (gchar)pound; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
772 *length = 2; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
773 while (isdigit ((gint) string [*length])) (*length)++; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
774 if (string [*length] == ';') (*length)++; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
775 } else { |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
776 return FALSE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
777 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
778 } else { |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
779 return FALSE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
780 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
781 |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
782 return TRUE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
783 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
784 |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
785 static gboolean |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
786 gtk_imhtml_is_tag (const gchar *string, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
787 gchar **tag, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
788 gint *len, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
789 gint *type) |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
790 { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
791 *type = 1; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
792 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
793 if (!strchr (string, '>')) |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
794 return FALSE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
795 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
796 VALID_TAG ("B"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
797 VALID_TAG ("BOLD"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
798 VALID_TAG ("/B"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
799 VALID_TAG ("/BOLD"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
800 VALID_TAG ("I"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
801 VALID_TAG ("ITALIC"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
802 VALID_TAG ("/I"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
803 VALID_TAG ("/ITALIC"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
804 VALID_TAG ("U"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
805 VALID_TAG ("UNDERLINE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
806 VALID_TAG ("/U"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
807 VALID_TAG ("/UNDERLINE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
808 VALID_TAG ("S"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
809 VALID_TAG ("STRIKE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
810 VALID_TAG ("/S"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
811 VALID_TAG ("/STRIKE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
812 VALID_TAG ("SUB"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
813 VALID_TAG ("/SUB"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
814 VALID_TAG ("SUP"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
815 VALID_TAG ("/SUP"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
816 VALID_TAG ("PRE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
817 VALID_TAG ("/PRE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
818 VALID_TAG ("TITLE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
819 VALID_TAG ("/TITLE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
820 VALID_TAG ("BR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
821 VALID_TAG ("HR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
822 VALID_TAG ("/FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
823 VALID_TAG ("/A"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
824 VALID_TAG ("P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
825 VALID_TAG ("/P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
826 VALID_TAG ("H3"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
827 VALID_TAG ("/H3"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
828 VALID_TAG ("HTML"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
829 VALID_TAG ("/HTML"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
830 VALID_TAG ("BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
831 VALID_TAG ("/BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
832 VALID_TAG ("FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
833 VALID_TAG ("HEAD"); |
| 2993 | 834 VALID_TAG ("/HEAD"); |
| 835 VALID_TAG ("BINARY"); | |
| 836 VALID_TAG ("/BINARY"); | |
| 5093 | 837 |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
838 VALID_OPT_TAG ("HR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
839 VALID_OPT_TAG ("FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
840 VALID_OPT_TAG ("BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
841 VALID_OPT_TAG ("A"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
842 VALID_OPT_TAG ("IMG"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
843 VALID_OPT_TAG ("P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
844 VALID_OPT_TAG ("H3"); |
| 5093 | 845 VALID_OPT_TAG ("HTML"); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
846 |
| 5101 | 847 VALID_TAG ("CITE"); |
| 848 VALID_TAG ("/CITE"); | |
| 849 VALID_TAG ("EM"); | |
| 850 VALID_TAG ("/EM"); | |
| 851 VALID_TAG ("STRONG"); | |
| 852 VALID_TAG ("/STRONG"); | |
| 853 | |
| 5104 | 854 VALID_OPT_TAG ("SPAN"); |
| 855 VALID_TAG ("/SPAN"); | |
| 5174 | 856 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
| 5104 | 857 |
| 4793 | 858 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
|
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
859 gchar *e = strstr (string + strlen("!--"), "-->"); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
860 if (e) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
861 *len = e - string + strlen ("-->"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
862 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
863 return TRUE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
864 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
865 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
866 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
867 return FALSE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
868 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
869 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
870 static gchar* |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
871 gtk_imhtml_get_html_opt (gchar *tag, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
872 const gchar *opt) |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
873 { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
874 gchar *t = tag; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
875 gchar *e, *a; |
| 5177 | 876 gchar *val; |
| 877 gint len; | |
| 878 gchar c; | |
| 879 GString *ret; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
880 |
| 4793 | 881 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
882 gboolean quote = FALSE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
883 if (*t == '\0') break; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
884 while (*t && !((*t == ' ') && !quote)) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
885 if (*t == '\"') |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
886 quote = ! quote; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
887 t++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
888 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
889 while (*t && (*t == ' ')) t++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
890 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
891 |
| 4793 | 892 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
893 t += strlen (opt); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
894 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
895 return NULL; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
896 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
897 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
898 if ((*t == '\"') || (*t == '\'')) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
899 e = a = ++t; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
900 while (*e && (*e != *(t - 1))) e++; |
| 2993 | 901 if (*e == '\0') { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
902 return NULL; |
| 5177 | 903 } else |
| 904 val = g_strndup(a, e - a); | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
905 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
906 e = a = t; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
907 while (*e && !isspace ((gint) *e)) e++; |
| 5177 | 908 val = g_strndup(a, e - a); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
909 } |
| 5177 | 910 |
| 911 ret = g_string_new(""); | |
| 912 e = val; | |
| 913 while(*e) { | |
| 914 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
| 915 ret = g_string_append_c(ret, c); | |
| 916 e += len; | |
| 917 } else { | |
| 918 ret = g_string_append_c(ret, *e); | |
| 919 e++; | |
| 920 } | |
| 921 } | |
| 922 | |
| 923 g_free(val); | |
| 924 val = ret->str; | |
| 925 g_string_free(ret, FALSE); | |
| 926 return val; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
927 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
928 |
| 3922 | 929 |
| 930 | |
| 931 #define NEW_TEXT_BIT 0 | |
| 4343 | 932 #define NEW_COMMENT_BIT 2 |
| 4895 | 933 #define NEW_SCALABLE_BIT 1 |
| 3922 | 934 #define NEW_BIT(x) ws [wpos] = '\0'; \ |
| 935 mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \ | |
| 936 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \ | |
| 4895 | 937 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ |
| 3922 | 938 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \ |
| 939 gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \ | |
| 940 if (bold) \ | |
| 941 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \ | |
| 4895 | 942 if (italics) \ |
| 3922 | 943 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \ |
| 944 if (underline) \ | |
| 945 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \ | |
| 946 if (strike) \ | |
| 947 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \ | |
| 948 if (sub) \ | |
| 949 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \ | |
| 950 if (sup) \ | |
| 951 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \ | |
| 952 if (pre) \ | |
| 953 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &iter); \ | |
| 954 if (bg) { \ | |
| 955 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); \ | |
| 956 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
| 957 } \ | |
| 958 if (fonts) { \ | |
| 5967 | 959 GtkIMHtmlFontDetail *fd = fonts->data; \ |
| 3922 | 960 if (fd->fore) { \ |
| 961 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \ | |
| 962 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
| 963 } \ | |
| 964 if (fd->back) { \ | |
| 965 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); \ | |
| 966 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
| 967 } \ | |
| 968 if (fd->face) { \ | |
| 969 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "font", fd->face, NULL); \ | |
| 970 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
| 971 } \ | |
| 972 if (fd->size) { \ | |
| 5118 | 973 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \ |
| 3922 | 974 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
| 975 } \ | |
| 976 } \ | |
| 977 if (url) { \ | |
| 978 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \ | |
| 5012 | 979 g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), g_strdup(url)); \ |
| 3922 | 980 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
| 4735 | 981 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); \ |
| 982 g_object_set_data(G_OBJECT(texttag), "link_url", g_strdup(url)); \ | |
| 983 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
| 3922 | 984 } \ |
| 985 wpos = 0; \ | |
| 986 ws[0] = 0; \ | |
| 987 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
| 4895 | 988 if (x == NEW_SCALABLE_BIT) { \ |
| 989 GdkRectangle rect; \ | |
| 990 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); \ | |
| 991 scalable->add_to(scalable, imhtml, &iter); \ | |
| 992 scalable->scale(scalable, rect.width, rect.height); \ | |
| 993 imhtml->scalables = g_list_append(imhtml->scalables, scalable); \ | |
| 994 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
| 4343 | 995 } \ |
| 6066 | 996 if (x == NEW_COMMENT_BIT) { \ |
| 997 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "comment", &siter, &iter); \ | |
| 998 } \ | |
| 3922 | 999 |
| 4895 | 1000 |
| 1001 | |
| 3922 | 1002 GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, |
| 1003 const gchar *text, | |
| 1004 gint len, | |
| 1005 GtkIMHtmlOptions options) | |
| 1428 | 1006 { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1007 gint pos = 0; |
| 3922 | 1008 GString *str = NULL; |
| 1009 GtkTextIter iter, siter; | |
| 1010 GtkTextMark *mark, *mark2; | |
| 1011 GtkTextTag *texttag; | |
| 1012 gchar *ws; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1013 gchar *tag; |
| 3922 | 1014 gchar *url = NULL; |
| 1015 gchar *bg = NULL; | |
| 4032 | 1016 gint tlen, smilelen, wpos=0; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1017 gint type; |
| 3922 | 1018 const gchar *c; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1019 gchar amp; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1020 |
| 1428 | 1021 guint bold = 0, |
| 1022 italics = 0, | |
| 1023 underline = 0, | |
| 1024 strike = 0, | |
| 1025 sub = 0, | |
| 1026 sup = 0, | |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1027 title = 0, |
| 3922 | 1028 pre = 0; |
| 1428 | 1029 |
| 3922 | 1030 GSList *fonts = NULL; |
| 1428 | 1031 |
| 4612 | 1032 GdkRectangle rect; |
| 1033 int y, height; | |
| 1034 | |
| 4895 | 1035 GtkIMHtmlScalable *scalable = NULL; |
| 1036 | |
| 1428 | 1037 g_return_val_if_fail (imhtml != NULL, NULL); |
| 1038 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | |
| 1039 g_return_val_if_fail (text != NULL, NULL); | |
| 3922 | 1040 g_return_val_if_fail (len != 0, NULL); |
| 1041 | |
| 1042 c = text; | |
| 1043 if (len == -1) | |
| 1044 len = strlen(text); | |
| 1045 ws = g_malloc(len + 1); | |
| 1046 ws[0] = 0; | |
| 1428 | 1047 |
| 1048 if (options & GTK_IMHTML_RETURN_LOG) | |
| 3922 | 1049 str = g_string_new(""); |
| 1428 | 1050 |
| 3922 | 1051 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); |
| 1052 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
| 4612 | 1053 |
| 1054 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
| 1055 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
| 1056 | |
| 1057 if(((y + height) - (rect.y + rect.height)) > height | |
| 1058 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
| 1059 options |= GTK_IMHTML_NO_SCROLL; | |
| 1060 } | |
| 1061 | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1062 while (pos < len) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1063 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1064 c++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1065 pos++; |
| 3922 | 1066 switch (type) |
| 1067 { | |
| 1068 case 1: /* B */ | |
| 1069 case 2: /* BOLD */ | |
| 5101 | 1070 case 54: /* STRONG */ |
| 3922 | 1071 NEW_BIT (NEW_TEXT_BIT); |
| 1072 bold++; | |
| 1073 break; | |
| 1074 case 3: /* /B */ | |
| 1075 case 4: /* /BOLD */ | |
| 5101 | 1076 case 55: /* /STRONG */ |
| 3922 | 1077 NEW_BIT (NEW_TEXT_BIT); |
| 1078 if (bold) | |
| 1079 bold--; | |
| 1080 break; | |
| 1081 case 5: /* I */ | |
| 1082 case 6: /* ITALIC */ | |
| 5101 | 1083 case 52: /* EM */ |
| 3922 | 1084 NEW_BIT (NEW_TEXT_BIT); |
| 1085 italics++; | |
| 1086 break; | |
| 1087 case 7: /* /I */ | |
| 1088 case 8: /* /ITALIC */ | |
| 5101 | 1089 case 53: /* /EM */ |
| 3922 | 1090 NEW_BIT (NEW_TEXT_BIT); |
| 1091 if (italics) | |
| 1092 italics--; | |
| 1093 break; | |
| 1094 case 9: /* U */ | |
| 1095 case 10: /* UNDERLINE */ | |
| 1096 NEW_BIT (NEW_TEXT_BIT); | |
| 1097 underline++; | |
| 1098 break; | |
| 1099 case 11: /* /U */ | |
| 1100 case 12: /* /UNDERLINE */ | |
| 1101 NEW_BIT (NEW_TEXT_BIT); | |
| 1102 if (underline) | |
| 1103 underline--; | |
| 1104 break; | |
| 1105 case 13: /* S */ | |
| 1106 case 14: /* STRIKE */ | |
| 1107 NEW_BIT (NEW_TEXT_BIT); | |
| 1108 strike++; | |
| 1109 break; | |
| 1110 case 15: /* /S */ | |
| 1111 case 16: /* /STRIKE */ | |
| 1112 NEW_BIT (NEW_TEXT_BIT); | |
| 1113 if (strike) | |
| 1114 strike--; | |
| 1115 break; | |
| 1116 case 17: /* SUB */ | |
| 1117 NEW_BIT (NEW_TEXT_BIT); | |
| 1118 sub++; | |
| 1119 break; | |
| 1120 case 18: /* /SUB */ | |
| 1121 NEW_BIT (NEW_TEXT_BIT); | |
| 1122 if (sub) | |
| 1123 sub--; | |
| 1124 break; | |
| 1125 case 19: /* SUP */ | |
| 1126 NEW_BIT (NEW_TEXT_BIT); | |
| 1127 sup++; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1128 break; |
| 3922 | 1129 case 20: /* /SUP */ |
| 1130 NEW_BIT (NEW_TEXT_BIT); | |
| 1131 if (sup) | |
| 1132 sup--; | |
| 1133 break; | |
| 1134 case 21: /* PRE */ | |
| 1135 NEW_BIT (NEW_TEXT_BIT); | |
| 1136 pre++; | |
| 1137 break; | |
| 1138 case 22: /* /PRE */ | |
| 1139 NEW_BIT (NEW_TEXT_BIT); | |
| 1140 if (pre) | |
| 1141 pre--; | |
| 1142 break; | |
| 1143 case 23: /* TITLE */ | |
| 1144 NEW_BIT (NEW_TEXT_BIT); | |
| 1145 title++; | |
| 1146 break; | |
| 1147 case 24: /* /TITLE */ | |
| 1148 if (title) { | |
| 1149 if (options & GTK_IMHTML_NO_TITLE) { | |
| 1150 wpos = 0; | |
| 1151 ws [wpos] = '\0'; | |
| 1152 } | |
| 1153 title--; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1154 } |
| 3922 | 1155 break; |
| 1156 case 25: /* BR */ | |
| 5174 | 1157 case 58: /* BR/ */ |
| 3922 | 1158 ws[wpos] = '\n'; |
| 1159 wpos++; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1160 NEW_BIT (NEW_TEXT_BIT); |
| 3922 | 1161 break; |
| 1162 case 26: /* HR */ | |
| 1163 case 42: /* HR (opt) */ | |
| 1164 ws[wpos++] = '\n'; | |
| 5967 | 1165 scalable = gtk_imhtml_hr_new(); |
| 4895 | 1166 NEW_BIT(NEW_SCALABLE_BIT); |
| 4343 | 1167 ws[wpos++] = '\n'; |
| 3922 | 1168 break; |
| 1169 case 27: /* /FONT */ | |
| 1170 if (fonts) { | |
| 5967 | 1171 GtkIMHtmlFontDetail *font = fonts->data; |
| 3922 | 1172 NEW_BIT (NEW_TEXT_BIT); |
| 1173 fonts = g_slist_remove (fonts, font); | |
| 1174 if (font->face) | |
| 1175 g_free (font->face); | |
| 1176 if (font->fore) | |
| 1177 g_free (font->fore); | |
| 1178 if (font->back) | |
| 1179 g_free (font->back); | |
| 4032 | 1180 if (font->sml) |
| 1181 g_free (font->sml); | |
| 3922 | 1182 g_free (font); |
| 1183 } | |
| 1184 break; | |
| 1185 case 28: /* /A */ | |
| 1186 if (url) { | |
| 1187 NEW_BIT(NEW_TEXT_BIT); | |
| 1188 g_free(url); | |
| 1189 url = NULL; | |
| 2993 | 1190 break; |
| 1191 } | |
| 3922 | 1192 case 29: /* P */ |
| 1193 case 30: /* /P */ | |
| 1194 case 31: /* H3 */ | |
| 1195 case 32: /* /H3 */ | |
| 1196 case 33: /* HTML */ | |
| 1197 case 34: /* /HTML */ | |
| 1198 case 35: /* BODY */ | |
| 1199 case 36: /* /BODY */ | |
| 1200 case 37: /* FONT */ | |
| 1201 case 38: /* HEAD */ | |
| 1202 case 39: /* /HEAD */ | |
| 1203 break; | |
| 1204 case 40: /* BINARY */ | |
| 4895 | 1205 NEW_BIT (NEW_TEXT_BIT); |
| 4997 | 1206 while (pos < len && g_ascii_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) { |
| 1207 c++; | |
| 1208 pos++; | |
| 1209 } | |
| 1210 c = c - tlen; /* Because it will add this later */ | |
| 4895 | 1211 break; |
| 3922 | 1212 case 41: /* /BINARY */ |
| 1213 break; | |
| 1214 case 43: /* FONT (opt) */ | |
| 1215 { | |
| 4032 | 1216 gchar *color, *back, *face, *size, *sml; |
| 5967 | 1217 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
| 3922 | 1218 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
| 1219 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
| 1220 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
| 1221 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
| 4032 | 1222 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
| 1223 if (!(color || back || face || size || sml)) | |
| 3922 | 1224 break; |
| 1225 | |
| 1226 NEW_BIT (NEW_TEXT_BIT); | |
| 1227 | |
| 5967 | 1228 font = g_new0 (GtkIMHtmlFontDetail, 1); |
| 3922 | 1229 if (fonts) |
| 1230 oldfont = fonts->data; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1231 |
| 3922 | 1232 if (color && !(options & GTK_IMHTML_NO_COLOURS)) |
| 1233 font->fore = color; | |
| 1234 else if (oldfont && oldfont->fore) | |
| 1235 font->fore = g_strdup(oldfont->fore); | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1236 |
| 3922 | 1237 if (back && !(options & GTK_IMHTML_NO_COLOURS)) |
| 1238 font->back = back; | |
| 1239 else if (oldfont && oldfont->back) | |
| 1240 font->back = g_strdup(oldfont->back); | |
| 1241 | |
| 1242 if (face && !(options & GTK_IMHTML_NO_FONTS)) | |
| 1243 font->face = face; | |
| 1244 else if (oldfont && oldfont->face) | |
| 1245 font->face = g_strdup(oldfont->face); | |
| 4629 | 1246 if (font->face && (atoi(font->face) > 100)) { |
| 1247 g_free(font->face); | |
| 1248 font->face = g_strdup("100"); | |
| 1249 } | |
| 4032 | 1250 |
| 1251 if (sml) | |
| 1252 font->sml = sml; | |
| 1253 else if (oldfont && oldfont->sml) | |
| 1254 font->sml = g_strdup(oldfont->sml); | |
| 1255 | |
| 3922 | 1256 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
| 1257 if (*size == '+') { | |
| 1258 sscanf (size + 1, "%hd", &font->size); | |
| 1259 font->size += 3; | |
| 1260 } else if (*size == '-') { | |
| 1261 sscanf (size + 1, "%hd", &font->size); | |
| 1262 font->size = MAX (0, 3 - font->size); | |
| 1263 } else if (isdigit (*size)) { | |
| 1264 sscanf (size, "%hd", &font->size); | |
| 1265 } | |
| 6042 | 1266 if (font->size > 100) |
| 1267 font->size = 100; | |
| 3922 | 1268 } else if (oldfont) |
| 1269 font->size = oldfont->size; | |
| 1270 g_free(size); | |
| 1271 fonts = g_slist_prepend (fonts, font); | |
| 1272 } | |
| 1273 break; | |
| 1274 case 44: /* BODY (opt) */ | |
| 1275 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
| 1276 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
| 1277 if (bgcolor) { | |
| 1278 NEW_BIT(NEW_TEXT_BIT); | |
| 1279 if (bg) | |
| 1280 g_free(bg); | |
| 1281 bg = bgcolor; | |
|
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
1282 } |
| 1428 | 1283 } |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1284 break; |
| 3922 | 1285 case 45: /* A (opt) */ |
| 1286 { | |
| 1287 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
| 1288 if (href) { | |
| 1289 NEW_BIT (NEW_TEXT_BIT); | |
| 1290 if (url) | |
| 1291 g_free (url); | |
| 1292 url = href; | |
| 1293 } | |
| 2993 | 1294 } |
| 3922 | 1295 break; |
| 4895 | 1296 case 46: /* IMG (opt) */ |
| 1297 { | |
| 1298 gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); | |
| 1299 gchar *id = gtk_imhtml_get_html_opt (tag, "ID="); | |
| 1300 gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE="); | |
| 1301 gint im_len = datasize?atoi(datasize):0; | |
| 1302 | |
| 1303 if (src && id && im_len && im_len <= len - pos) { | |
| 1304 /* This is an embedded IM image, or is it? */ | |
| 1305 char *tmp = NULL; | |
| 1306 const char *alltext; | |
| 1307 guchar *imagedata = NULL; | |
| 1308 | |
| 1309 GdkPixbufLoader *load; | |
| 1310 GdkPixbuf *imagepb = NULL; | |
| 1311 GError *error = NULL; | |
| 1312 | |
| 1313 tmp = g_strdup_printf("<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize); | |
| 1314 alltext = strstr(c, tmp); | |
| 1315 imagedata = g_memdup(alltext + strlen(tmp), im_len); | |
| 1316 | |
| 1317 g_free(tmp); | |
| 1318 | |
| 1319 load = gdk_pixbuf_loader_new(); | |
| 1320 if (!gdk_pixbuf_loader_write(load, imagedata, im_len, &error)){ | |
| 1321 fprintf(stderr, "IM Image corrupted or unreadable.: %s\n", error->message); | |
| 1322 } else { | |
| 1323 imagepb = gdk_pixbuf_loader_get_pixbuf(load); | |
| 1324 if (imagepb) { | |
| 5967 | 1325 scalable = gtk_imhtml_image_new(imagepb, g_strdup(src)); |
| 4895 | 1326 NEW_BIT(NEW_SCALABLE_BIT); |
| 5012 | 1327 g_object_unref(imagepb); |
| 4895 | 1328 } |
| 1329 } | |
| 1330 | |
| 1331 gdk_pixbuf_loader_close(load, NULL); | |
| 1332 | |
| 1333 | |
| 1334 g_free(imagedata); | |
| 1335 g_free(id); | |
| 1336 g_free(datasize); | |
| 1337 g_free(src); | |
| 1338 | |
| 1339 break; | |
| 1340 } | |
| 1341 g_free(id); | |
| 1342 g_free(datasize); | |
| 1343 g_free(src); | |
| 1344 } | |
| 3922 | 1345 case 47: /* P (opt) */ |
| 1346 case 48: /* H3 (opt) */ | |
| 5093 | 1347 case 49: /* HTML (opt) */ |
| 5101 | 1348 case 50: /* CITE */ |
| 1349 case 51: /* /CITE */ | |
| 5104 | 1350 case 56: /* SPAN */ |
| 1351 case 57: /* /SPAN */ | |
| 2993 | 1352 break; |
| 5174 | 1353 case 59: /* comment */ |
| 3922 | 1354 NEW_BIT (NEW_TEXT_BIT); |
| 6066 | 1355 wpos = g_snprintf (ws, len, "%s", tag); |
| 3922 | 1356 NEW_BIT (NEW_COMMENT_BIT); |
| 1357 break; | |
| 1358 default: | |
| 1359 break; | |
| 2993 | 1360 } |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1361 c += tlen; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1362 pos += tlen; |
| 4138 | 1363 if(tag) |
| 1364 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1365 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1366 ws [wpos++] = amp; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1367 c += tlen; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1368 pos += tlen; |
| 1428 | 1369 } else if (*c == '\n') { |
| 1370 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
| 3922 | 1371 ws[wpos] = '\n'; |
| 1372 wpos++; | |
| 1428 | 1373 NEW_BIT (NEW_TEXT_BIT); |
| 1374 } | |
| 1375 c++; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1376 pos++; |
| 4253 | 1377 } else if (imhtml->show_smileys && (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen))) { |
| 5967 | 1378 GtkIMHtmlFontDetail *fd; |
| 4032 | 1379 gchar *sml = NULL; |
| 1380 if (fonts) { | |
| 1381 fd = fonts->data; | |
| 1382 sml = fd->sml; | |
| 1383 } | |
| 1384 NEW_BIT (NEW_TEXT_BIT); | |
| 1385 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | |
| 4263 | 1386 gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gtk_smiley_tree_image (imhtml, sml, ws)); |
| 4032 | 1387 c += smilelen; |
| 1388 pos += smilelen; | |
| 1389 wpos = 0; | |
| 1390 ws[0] = 0; | |
| 1391 } else if (*c) { | |
| 1428 | 1392 ws [wpos++] = *c++; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1393 pos++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1394 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1395 break; |
| 1428 | 1396 } |
| 1397 } | |
| 3922 | 1398 |
| 1399 NEW_BIT(NEW_TEXT_BIT); | |
| 1428 | 1400 if (url) { |
| 1401 g_free (url); | |
| 3922 | 1402 if (str) |
| 1403 str = g_string_append (str, "</A>"); | |
| 1428 | 1404 } |
| 3922 | 1405 |
| 4032 | 1406 while (fonts) { |
| 5967 | 1407 GtkIMHtmlFontDetail *font = fonts->data; |
| 4032 | 1408 fonts = g_slist_remove (fonts, font); |
| 1409 if (font->face) | |
| 1410 g_free (font->face); | |
| 1411 if (font->fore) | |
| 1412 g_free (font->fore); | |
| 1413 if (font->back) | |
| 1414 g_free (font->back); | |
| 1415 if (font->sml) | |
| 1416 g_free (font->sml); | |
| 1417 g_free (font); | |
| 1418 if (str) | |
| 1419 str = g_string_append (str, "</FONT>"); | |
| 1420 } | |
| 1421 | |
| 3922 | 1422 if (str) { |
| 1428 | 1423 while (bold) { |
| 3922 | 1424 str = g_string_append (str, "</B>"); |
| 1428 | 1425 bold--; |
| 1426 } | |
| 1427 while (italics) { | |
| 3922 | 1428 str = g_string_append (str, "</I>"); |
| 1428 | 1429 italics--; |
| 1430 } | |
| 1431 while (underline) { | |
| 3922 | 1432 str = g_string_append (str, "</U>"); |
| 1428 | 1433 underline--; |
| 1434 } | |
| 1435 while (strike) { | |
| 3922 | 1436 str = g_string_append (str, "</S>"); |
| 1428 | 1437 strike--; |
| 1438 } | |
| 1439 while (sub) { | |
| 3922 | 1440 str = g_string_append (str, "</SUB>"); |
| 1428 | 1441 sub--; |
| 1442 } | |
| 1443 while (sup) { | |
| 3922 | 1444 str = g_string_append (str, "</SUP>"); |
| 1428 | 1445 sup--; |
| 1446 } | |
| 1447 while (title) { | |
| 3922 | 1448 str = g_string_append (str, "</TITLE>"); |
| 1428 | 1449 title--; |
| 1450 } | |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1451 while (pre) { |
| 3922 | 1452 str = g_string_append (str, "</PRE>"); |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1453 pre--; |
|
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1454 } |
| 1428 | 1455 } |
| 4032 | 1456 g_free (ws); |
| 4630 | 1457 if(bg) |
| 1458 g_free(bg); | |
| 4032 | 1459 if (!(options & GTK_IMHTML_NO_SCROLL)) |
| 1460 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
| 1461 0, TRUE, 0.0, 1.0); | |
| 3922 | 1462 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
| 1463 return str; | |
| 1464 } | |
| 1465 | |
| 4892 | 1466 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
| 1467 { | |
| 4288 | 1468 g_hash_table_destroy(imhtml->smiley_data); |
| 1469 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
| 4892 | 1470 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 4902 | 1471 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
| 4288 | 1472 imhtml->default_smilies = gtk_smiley_tree_new(); |
| 1473 } | |
| 3922 | 1474 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
| 4253 | 1475 gboolean show) |
| 1476 { | |
| 1477 imhtml->show_smileys = show; | |
| 1478 } | |
| 3922 | 1479 |
| 1480 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
| 4253 | 1481 gboolean show) |
| 1482 { | |
| 6066 | 1483 GtkTextIter iter; |
| 1484 GtkTextTagTable *table = gtk_text_buffer_get_tag_table(imhtml->text_buffer); | |
| 1485 GtkTextTag *tag = gtk_text_tag_table_lookup(table, "comment"); | |
| 1486 g_object_set(G_OBJECT(tag), "invisible", !show, NULL); | |
| 1487 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
| 1488 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter); | |
| 1489 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "selection_bound", &iter); | |
| 1490 | |
| 4253 | 1491 } |
|
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1492 |
|
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1493 void |
|
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1494 gtk_imhtml_clear (GtkIMHtml *imhtml) |
|
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1495 { |
| 3922 | 1496 GtkTextIter start, end; |
| 2993 | 1497 |
| 3922 | 1498 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
| 1499 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
| 1500 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
|
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1501 } |
|
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
1502 |
| 4046 | 1503 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
| 1504 { | |
| 5282 | 1505 GdkRectangle rect; |
| 1506 GtkTextIter iter; | |
| 4046 | 1507 |
| 5282 | 1508 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
| 1509 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
| 1510 rect.y - rect.height); | |
| 1511 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
| 1512 | |
| 4046 | 1513 } |
| 5282 | 1514 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
| 1515 { | |
| 1516 GdkRectangle rect; | |
| 1517 GtkTextIter iter; | |
| 1518 | |
| 1519 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
| 1520 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
| 1521 rect.y + rect.height); | |
| 1522 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
| 1523 } | |
| 4735 | 1524 |
| 5967 | 1525 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
| 1526 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, gchar *filename) | |
| 4735 | 1527 { |
| 5967 | 1528 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
| 5012 | 1529 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
| 4895 | 1530 |
| 5967 | 1531 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
| 1532 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
| 1533 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
| 5046 | 1534 |
| 1535 im_image->pixbuf = img; | |
| 5012 | 1536 im_image->image = image; |
| 4895 | 1537 im_image->width = gdk_pixbuf_get_width(img); |
| 1538 im_image->height = gdk_pixbuf_get_height(img); | |
| 1539 im_image->mark = NULL; | |
| 5012 | 1540 im_image->filename = filename; |
| 4895 | 1541 |
| 5046 | 1542 g_object_ref(img); |
| 4895 | 1543 return GTK_IMHTML_SCALABLE(im_image); |
| 1544 } | |
| 1545 | |
| 5967 | 1546 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
| 4895 | 1547 { |
| 5967 | 1548 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
| 4895 | 1549 |
| 1550 if(image->width > width || image->height > height){ | |
| 1551 GdkPixbuf *new_image = NULL; | |
| 1552 float factor; | |
| 1553 int new_width = image->width, new_height = image->height; | |
| 1554 | |
| 1555 if(image->width > width){ | |
| 1556 factor = (float)(width)/image->width; | |
| 1557 new_width = width; | |
| 1558 new_height = image->height * factor; | |
| 1559 } | |
| 1560 if(new_height > height){ | |
| 1561 factor = (float)(height)/new_height; | |
| 1562 new_height = height; | |
| 1563 new_width = new_width * factor; | |
| 1564 } | |
| 1565 | |
| 5046 | 1566 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
| 5012 | 1567 gtk_image_set_from_pixbuf(image->image, new_image); |
| 4895 | 1568 g_object_unref(G_OBJECT(new_image)); |
| 1569 } | |
| 1570 } | |
| 1571 | |
| 5012 | 1572 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
| 1573 { | |
| 1574 const gchar *filename = gtk_file_selection_get_filename(sel); | |
| 5967 | 1575 gchar *dirname; |
| 1576 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
| 5012 | 1577 gchar *type = NULL; |
| 5019 | 1578 GError *error = NULL; |
| 5015 | 1579 #if GTK_CHECK_VERSION(2,2,0) |
| 5012 | 1580 GSList *formats = gdk_pixbuf_get_formats(); |
| 5959 | 1581 #endif |
| 5012 | 1582 |
| 5967 | 1583 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
| 1584 /* append a / if needed */ | |
| 1585 if (filename[strlen(filename) - 1] != '/') { | |
| 1586 dirname = g_strconcat(filename, "/", NULL); | |
| 1587 } else { | |
| 1588 dirname = g_strdup(filename); | |
| 1589 } | |
| 1590 gtk_file_selection_set_filename(sel, dirname); | |
| 1591 g_free(dirname); | |
| 5959 | 1592 return; |
| 5967 | 1593 } |
| 5959 | 1594 |
| 1595 #if GTK_CHECK_VERSION(2,2,0) | |
| 5012 | 1596 while(formats){ |
| 1597 GdkPixbufFormat *format = formats->data; | |
| 1598 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
| 1599 gpointer p = extensions; | |
| 1600 | |
| 1601 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
| 1602 gchar *fmt_ext = extensions[0]; | |
| 1603 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
| 1604 | |
| 1605 if(!strcmp(fmt_ext, file_ext)){ | |
| 1606 type = gdk_pixbuf_format_get_name(format); | |
| 1607 break; | |
| 1608 } | |
| 1609 | |
| 1610 extensions++; | |
| 1611 } | |
| 1612 | |
| 1613 g_strfreev(p); | |
| 1614 | |
| 1615 if(type) | |
| 1616 break; | |
| 1617 | |
| 1618 formats = formats->next; | |
| 1619 } | |
| 1620 | |
| 5020 | 1621 g_slist_free(formats); |
| 1622 #else | |
| 1623 /* this is really ugly code, but I think it will work */ | |
| 1624 char *basename = g_path_get_basename(filename); | |
| 1625 char *ext = strrchr(basename, '.'); | |
| 1626 | |
| 1627 if(ext) { | |
| 1628 ext++; | |
| 1629 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
| 1630 type = g_strdup("jpeg"); | |
| 1631 else if(!g_ascii_strcasecmp(ext, "png")) | |
| 1632 type = g_strdup("png"); | |
| 1633 } | |
| 1634 | |
| 1635 g_free(basename); | |
| 1636 #endif | |
| 1637 | |
| 5012 | 1638 /* If I can't find a valid type, I will just tell the user about it and then assume |
| 1639 it's a png */ | |
| 1640 if(!type){ | |
| 1641 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
| 5967 | 1642 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
| 5012 | 1643 type = g_strdup("png"); |
| 1644 } | |
| 1645 | |
| 5046 | 1646 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
| 5012 | 1647 |
| 1648 if(error){ | |
| 1649 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
| 1650 _("Error saving image: %s"), error->message); | |
| 1651 g_error_free(error); | |
| 1652 } | |
| 1653 | |
| 1654 g_free(type); | |
| 1655 } | |
| 1656 | |
| 5967 | 1657 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
| 5012 | 1658 { |
| 5967 | 1659 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
| 5012 | 1660 |
| 1661 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
| 5967 | 1662 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
| 5012 | 1663 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
| 1664 G_CALLBACK(write_img_to_file), sel); | |
| 1665 | |
| 1666 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
| 1667 G_CALLBACK(gtk_widget_destroy), sel); | |
| 1668 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
| 1669 G_CALLBACK(gtk_widget_destroy), sel); | |
| 1670 | |
| 1671 gtk_widget_show(sel); | |
| 1672 } | |
| 1673 | |
| 5967 | 1674 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
| 5012 | 1675 { |
| 1676 GdkEventButton *event_button = (GdkEventButton *) event; | |
| 1677 | |
| 1678 if (event->type == GDK_BUTTON_RELEASE) { | |
| 1679 if(event_button->button == 3) { | |
| 1680 GtkWidget *img, *item, *menu; | |
| 1681 gchar *text = g_strdup_printf(_("_Save Image...")); | |
| 1682 menu = gtk_menu_new(); | |
| 1683 | |
| 1684 /* buttons and such */ | |
| 1685 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
| 1686 item = gtk_image_menu_item_new_with_mnemonic(text); | |
| 1687 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
| 5967 | 1688 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
| 5012 | 1689 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 1690 | |
| 1691 gtk_widget_show_all(menu); | |
| 1692 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
| 1693 event_button->button, event_button->time); | |
| 1694 | |
| 1695 g_free(text); | |
| 1696 return TRUE; | |
| 1697 } | |
| 1698 } | |
| 1699 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
| 1700 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
| 1701 be caught by the regular GtkTextView menu */ | |
| 1702 else | |
| 1703 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
| 1704 | |
| 1705 } | |
| 5967 | 1706 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
| 1707 { | |
| 1708 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
| 1709 | |
| 1710 g_object_unref(image->pixbuf); | |
| 1711 g_free(image->filename); | |
| 1712 g_free(scale); | |
| 1713 } | |
| 1714 | |
| 1715 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
| 1716 { | |
| 1717 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
| 1718 GtkWidget *box = gtk_event_box_new(); | |
| 1719 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
| 1720 | |
| 1721 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
| 1722 | |
| 1723 gtk_widget_show(GTK_WIDGET(image->image)); | |
| 1724 gtk_widget_show(box); | |
| 1725 | |
| 1726 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
| 1727 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
| 1728 } | |
| 1729 | |
| 1730 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
| 1731 { | |
| 1732 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
| 1733 | |
| 1734 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
| 1735 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
| 1736 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
| 1737 | |
| 1738 hr->sep = gtk_hseparator_new(); | |
| 1739 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
| 1740 gtk_widget_show(hr->sep); | |
| 1741 | |
| 1742 return GTK_IMHTML_SCALABLE(hr); | |
| 1743 } | |
| 1744 | |
| 1745 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
| 1746 { | |
| 1747 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width, 2); | |
| 1748 } | |
| 1749 | |
| 1750 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
| 1751 { | |
| 1752 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
| 1753 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
| 1754 | |
| 1755 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); | |
| 1756 } | |
| 1757 | |
| 1758 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
| 1759 { | |
| 1760 /* gtk_widget_destroy(((GtkIMHtmlHr *)scale)->sep); */ | |
| 1761 g_free(scale); | |
| 1762 } |
