Mercurial > pidgin
annotate src/gtkimhtml.c @ 8456:5f8d4ab6d375
[gaim-migrate @ 9186]
"his patch fixes an issue where the gtkimhtml and the
gtkimtoolbar did not know what protocol the
conversation was for so they we're either displaying
core smileys or white boxes with an x through them.
this also make gtkimthml honor the ctrl-{b/u/i} and
ctrl-number prefs." --Gary Kramlich
who continues:
"in the first patch i forgot to adjust the protocol name in
the conversation when an item in the send as menu was
selected. This fixes that."
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Tue, 16 Mar 2004 19:35:17 +0000 |
| parents | b08d8874d933 |
| children | daeeb96cdf8f |
| rev | line source |
|---|---|
| 1428 | 1 /* |
| 2 * GtkIMHtml | |
| 3 * | |
| 8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
| 5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
| 6 * source distribution. | |
| 1428 | 7 * |
| 8 * This program is free software; you can redistribute it and/or modify | |
| 9 * under the terms of the GNU General Public License as published by | |
| 10 * the Free Software Foundation; either version 2 of the License, or | |
| 11 * (at your option) any later version. | |
| 12 * | |
| 13 * This program is distributed in the hope that it will be useful, | |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 * GNU General Public License for more details. | |
| 17 * | |
| 18 * You should have received a copy of the GNU General Public License | |
| 19 * along with this program; if not, write to the Free Software | |
| 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 * | |
| 22 */ | |
| 23 | |
|
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
24 #ifdef HAVE_CONFIG_H |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
25 #include <config.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
26 #endif |
| 8091 | 27 #include "util.h" |
| 1428 | 28 #include "gtkimhtml.h" |
| 7358 | 29 #include "gtksourceiter.h" |
| 1428 | 30 #include <gtk/gtk.h> |
| 4895 | 31 #include <glib/gerror.h> |
| 4046 | 32 #include <gdk/gdkkeysyms.h> |
| 1428 | 33 #include <string.h> |
| 34 #include <ctype.h> | |
| 35 #include <stdio.h> | |
| 4629 | 36 #include <stdlib.h> |
| 1428 | 37 #include <math.h> |
|
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
38 #ifdef HAVE_LANGINFO_CODESET |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
39 #include <langinfo.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
40 #include <locale.h> |
|
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
41 #endif |
| 1428 | 42 |
| 4417 | 43 #ifdef ENABLE_NLS |
| 44 # include <libintl.h> | |
| 45 # define _(x) gettext(x) | |
| 46 # ifdef gettext_noop | |
| 47 # define N_(String) gettext_noop (String) | |
| 48 # else | |
| 49 # define N_(String) (String) | |
| 50 # endif | |
| 51 #else | |
| 52 # define N_(String) (String) | |
| 53 # define _(x) (x) | |
| 54 #endif | |
| 55 | |
| 4735 | 56 #include <pango/pango-font.h> |
| 57 | |
| 5105 | 58 /* GTK+ < 2.2.2 hack, see ui.h for details. */ |
| 59 #ifndef GTK_WRAP_WORD_CHAR | |
| 60 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD | |
| 61 #endif | |
| 62 | |
| 4735 | 63 #define TOOLTIP_TIMEOUT 500 |
| 64 | |
| 8061 | 65 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
| 66 void gtk_imhtml_close_tags(GtkIMHtml *imhtml); | |
| 8091 | 67 static void gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml); |
| 8061 | 68 |
| 3922 | 69 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a |
| 70 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | |
| 71 #define MAX_FONT_SIZE 7 | |
| 5367 | 72 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
| 8380 | 73 static gdouble _point_sizes [] = { .69444444, .8333333, 1, 1.2, 1.44, 1.728, 2.0736}; |
|
2349
60c716c32c40
[gaim-migrate @ 2362]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2348
diff
changeset
|
74 |
| 8061 | 75 enum { |
| 76 TARGET_HTML, | |
| 77 TARGET_UTF8_STRING, | |
| 78 TARGET_COMPOUND_TEXT, | |
| 79 TARGET_STRING, | |
| 80 TARGET_TEXT | |
| 81 }; | |
| 82 | |
| 8091 | 83 enum { |
| 84 DRAG_URL | |
| 85 }; | |
| 86 | |
| 8420 | 87 enum { |
| 88 URL_CLICKED, | |
| 89 BUTTONS_UPDATE, | |
| 90 TOGGLE_FORMAT, | |
| 8427 | 91 CLEAR_FORMAT, |
| 8420 | 92 LAST_SIGNAL |
| 93 }; | |
| 94 static guint signals [LAST_SIGNAL] = { 0 }; | |
| 95 | |
| 8061 | 96 GtkTargetEntry selection_targets[] = { |
| 97 { "text/html", 0, TARGET_HTML }, | |
| 98 { "UTF8_STRING", 0, TARGET_UTF8_STRING }, | |
| 99 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, | |
| 100 { "STRING", 0, TARGET_STRING }, | |
| 101 { "TEXT", 0, TARGET_TEXT}}; | |
| 102 | |
| 8091 | 103 GtkTargetEntry link_drag_drop_targets[] = { |
| 104 {"x-url/ftp", 0, DRAG_URL}, | |
| 105 {"x-url/http", 0, DRAG_URL}, | |
| 106 {"text/uri-list", 0, DRAG_URL}, | |
| 107 {"_NETSCAPE_URL", 0, DRAG_URL}}; | |
| 108 | |
| 4032 | 109 static GtkSmileyTree* |
| 110 gtk_smiley_tree_new () | |
| 111 { | |
| 112 return g_new0 (GtkSmileyTree, 1); | |
| 113 } | |
| 114 | |
| 115 static void | |
| 116 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
| 4263 | 117 GtkIMHtmlSmiley *smiley) |
| 4032 | 118 { |
| 119 GtkSmileyTree *t = tree; | |
| 4263 | 120 const gchar *x = smiley->smile; |
| 4032 | 121 |
| 122 if (!strlen (x)) | |
| 123 return; | |
| 124 | |
| 125 while (*x) { | |
| 126 gchar *pos; | |
| 127 gint index; | |
| 128 | |
| 129 if (!t->values) | |
| 130 t->values = g_string_new (""); | |
| 131 | |
| 132 pos = strchr (t->values->str, *x); | |
| 133 if (!pos) { | |
| 134 t->values = g_string_append_c (t->values, *x); | |
| 135 index = t->values->len - 1; | |
| 136 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
| 137 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
| 138 } else | |
| 7386 | 139 index = GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str); |
| 8061 | 140 |
| 4032 | 141 t = t->children [index]; |
| 8061 | 142 |
| 4032 | 143 x++; |
| 144 } | |
| 8061 | 145 |
| 4263 | 146 t->image = smiley; |
| 4032 | 147 } |
| 4041 | 148 |
| 4263 | 149 |
| 4264 | 150 void gtk_smiley_tree_destroy (GtkSmileyTree *tree) |
| 4032 | 151 { |
| 152 GSList *list = g_slist_append (NULL, tree); | |
| 153 | |
| 154 while (list) { | |
| 155 GtkSmileyTree *t = list->data; | |
| 156 gint i; | |
| 157 list = g_slist_remove(list, t); | |
| 7384 | 158 if (t && t->values) { |
| 4032 | 159 for (i = 0; i < t->values->len; i++) |
| 160 list = g_slist_append (list, t->children [i]); | |
| 161 g_string_free (t->values, TRUE); | |
| 162 g_free (t->children); | |
| 163 } | |
| 164 g_free (t); | |
| 165 } | |
| 166 } | |
| 167 | |
| 5967 | 168 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
| 169 { | |
| 170 GdkRectangle rect; | |
| 171 | |
| 172 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); | |
| 173 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ | |
| 174 GList *iter = GTK_IMHTML(widget)->scalables; | |
| 175 | |
| 176 while(iter){ | |
| 177 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data); | |
| 178 scale->scale(scale, rect.width, rect.height); | |
| 179 | |
| 180 iter = iter->next; | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 widget->old_rect = rect; | |
| 185 return FALSE; | |
| 186 } | |
| 187 | |
| 188 static gint | |
| 189 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
| 190 { | |
| 191 PangoLayout *layout; | |
| 192 | |
| 193 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
| 194 | |
| 195 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
| 196 | |
| 8061 | 197 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, |
| 5967 | 198 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, |
| 199 "tooltip", 0, 0, -1, -1); | |
| 200 | |
| 201 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
| 202 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
| 203 | |
| 204 g_object_unref(layout); | |
| 205 return FALSE; | |
| 206 } | |
| 207 | |
| 208 static gint | |
| 209 gtk_imhtml_tip (gpointer data) | |
| 210 { | |
| 211 GtkIMHtml *imhtml = data; | |
| 212 PangoFontMetrics *font; | |
| 213 PangoLayout *layout; | |
| 214 | |
| 215 gint gap, x, y, h, w, scr_w, baseline_skip; | |
| 216 | |
| 217 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
| 218 | |
| 219 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
| 220 imhtml->tip_timer = 0; | |
| 221 return FALSE; | |
| 222 } | |
| 8061 | 223 |
| 5967 | 224 if (imhtml->tip_window){ |
| 225 gtk_widget_destroy (imhtml->tip_window); | |
| 226 imhtml->tip_window = NULL; | |
| 227 } | |
| 228 | |
| 229 imhtml->tip_timer = 0; | |
| 230 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
| 231 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
| 232 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
| 233 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
| 234 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
| 235 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
| 236 | |
| 237 gtk_widget_ensure_style (imhtml->tip_window); | |
| 238 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
| 239 font = pango_font_get_metrics(pango_context_load_font(pango_layout_get_context(layout), | |
| 8309 | 240 imhtml->tip_window->style->font_desc), |
| 241 NULL); | |
| 242 | |
| 5967 | 243 |
| 244 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
| 8061 | 245 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + |
| 5967 | 246 pango_font_metrics_get_descent(font))/ 4); |
| 247 | |
| 248 if (gap < 2) | |
| 249 gap = 2; | |
| 8061 | 250 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + |
| 5967 | 251 pango_font_metrics_get_descent(font)); |
| 252 w = 8 + scr_w; | |
| 253 h = 8 + baseline_skip; | |
| 254 | |
| 255 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
| 256 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
| 257 y += GTK_WIDGET(imhtml)->allocation.y; | |
| 258 | |
| 259 scr_w = gdk_screen_width(); | |
| 260 | |
| 261 x -= ((w >> 1) + 4); | |
| 262 | |
| 263 if ((x + w) > scr_w) | |
| 264 x -= (x + w) - scr_w; | |
| 265 else if (x < 0) | |
| 266 x = 0; | |
| 267 | |
| 8061 | 268 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + |
| 5967 | 269 pango_font_metrics_get_descent(font)); |
| 270 | |
| 271 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
| 272 gtk_widget_show (imhtml->tip_window); | |
| 273 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
| 274 | |
| 275 pango_font_metrics_unref(font); | |
| 276 g_object_unref(layout); | |
| 277 | |
| 278 return FALSE; | |
| 279 } | |
| 280 | |
| 281 gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) | |
| 8061 | 282 { |
| 5967 | 283 GtkTextIter iter; |
| 284 GdkWindow *win = event->window; | |
| 285 int x, y; | |
| 286 char *tip = NULL; | |
| 287 GSList *tags = NULL, *templist = NULL; | |
| 288 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); | |
| 289 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, | |
| 290 event->x, event->y, &x, &y); | |
| 291 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
| 292 tags = gtk_text_iter_get_tags(&iter); | |
| 293 | |
| 294 templist = tags; | |
| 295 while (templist) { | |
| 296 GtkTextTag *tag = templist->data; | |
| 297 tip = g_object_get_data(G_OBJECT(tag), "link_url"); | |
| 298 if (tip) | |
| 299 break; | |
| 300 templist = templist->next; | |
| 301 } | |
| 8061 | 302 |
| 5967 | 303 if (GTK_IMHTML(imhtml)->tip) { |
| 304 if ((tip == GTK_IMHTML(imhtml)->tip)) { | |
| 305 return FALSE; | |
| 306 } | |
| 307 /* We've left the cell. Remove the timeout and create a new one below */ | |
| 308 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 309 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 310 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 311 } | |
| 8061 | 312 if (GTK_IMHTML(imhtml)->editable) |
| 313 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->text_cursor); | |
| 314 else | |
| 315 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 5967 | 316 if (GTK_IMHTML(imhtml)->tip_timer) |
| 317 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 318 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 319 } | |
| 8061 | 320 |
| 5967 | 321 if(tip){ |
| 8061 | 322 if (!GTK_IMHTML(imhtml)->editable) |
| 323 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); | |
| 324 GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, | |
| 5967 | 325 gtk_imhtml_tip, imhtml); |
| 326 } | |
| 8061 | 327 |
| 5967 | 328 GTK_IMHTML(imhtml)->tip = tip; |
| 329 g_slist_free(tags); | |
| 330 return FALSE; | |
| 331 } | |
| 332 | |
| 333 gboolean gtk_leave_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) | |
| 334 { | |
| 335 /* when leaving the widget, clear any current & pending tooltips and restore the cursor */ | |
| 336 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 337 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 338 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 339 } | |
| 340 if (GTK_IMHTML(imhtml)->tip_timer) { | |
| 341 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 342 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 343 } | |
| 8061 | 344 if (GTK_IMHTML(imhtml)->editable) |
| 345 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->text_cursor); | |
| 346 else | |
| 347 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 5967 | 348 |
| 349 /* propogate the event normally */ | |
| 350 return FALSE; | |
| 351 } | |
| 352 | |
| 6066 | 353 /* |
| 354 * XXX - This should be removed eventually. | |
| 355 * | |
| 8061 | 356 * This function exists to work around a gross bug in GtkTextView. |
| 357 * Basically, we short circuit ctrl+a and ctrl+end because they make | |
| 6066 | 358 * el program go boom. |
| 359 * | |
| 8061 | 360 * It's supposed to be fixed in gtk2.2. You can view the bug report at |
| 6066 | 361 * http://bugzilla.gnome.org/show_bug.cgi?id=107939 |
| 362 */ | |
| 8317 | 363 |
| 364 /* | |
| 365 * I'm adding some keyboard shortcuts too. | |
| 366 */ | |
| 367 | |
| 368 gboolean gtk_key_pressed_cb(GtkIMHtml *imhtml, GdkEventKey *event, gpointer data) | |
| 369 { | |
| 8439 | 370 GObject *object; |
| 8317 | 371 char buf[7]; |
| 372 buf[0] = '\0'; | |
| 373 | |
| 6066 | 374 if (event->state & GDK_CONTROL_MASK) |
| 375 switch (event->keyval) { | |
| 8317 | 376 case 'a': |
| 377 return TRUE; | |
| 378 break; | |
| 379 | |
| 380 case GDK_Home: | |
| 381 return TRUE; | |
| 382 break; | |
| 383 | |
| 384 case GDK_End: | |
| 385 return TRUE; | |
| 386 break; | |
| 387 | |
| 388 case 'b': /* ctrl-b is GDK_Left, which moves backwards. */ | |
| 389 case 'B': | |
| 8420 | 390 if (imhtml->format_functions & GTK_IMHTML_BOLD) { |
| 8456 | 391 if(imhtml->html_shortcuts) { |
| 392 gtk_imhtml_toggle_bold(imhtml); | |
| 393 object = g_object_ref(G_OBJECT(imhtml)); | |
| 394 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); | |
| 395 g_object_unref(object); | |
| 396 } | |
| 8420 | 397 } |
| 8317 | 398 return TRUE; |
| 399 break; | |
| 400 | |
| 401 case 'f': | |
| 402 case 'F': | |
| 403 /*set_toggle(gtkconv->toolbar.font, | |
| 404 !gtk_toggle_button_get_active( | |
| 405 GTK_TOGGLE_BUTTON(gtkconv->toolbar.font)));*/ | |
| 406 | |
| 407 return TRUE; | |
| 408 break; | |
| 409 | |
| 410 case 'i': | |
| 411 case 'I': | |
| 8420 | 412 if (imhtml->format_functions & GTK_IMHTML_ITALIC) |
| 8456 | 413 if(imhtml->html_shortcuts) |
| 414 gtk_imhtml_toggle_italic(imhtml); | |
| 8317 | 415 return TRUE; |
| 416 break; | |
| 417 | |
| 418 case 'u': /* ctrl-u is GDK_Clear, which clears the line. */ | |
| 419 case 'U': | |
| 8420 | 420 if (imhtml->format_functions & GTK_IMHTML_UNDERLINE) |
| 8456 | 421 if(imhtml->html_shortcuts) |
| 422 gtk_imhtml_toggle_underline(imhtml); | |
| 8317 | 423 return TRUE; |
| 424 break; | |
| 425 | |
| 426 case '-': | |
| 8420 | 427 if (imhtml->format_functions & GTK_IMHTML_SHRINK) |
| 428 gtk_imhtml_font_shrink(imhtml); | |
| 8317 | 429 return TRUE; |
| 430 break; | |
| 431 | |
| 432 case '=': | |
| 433 case '+': | |
| 8420 | 434 if (imhtml->format_functions & GTK_IMHTML_GROW) |
| 435 gtk_imhtml_font_grow(imhtml); | |
| 8317 | 436 return TRUE; |
| 437 break; | |
| 438 | |
| 439 case '1': strcpy(buf, ":-)"); break; | |
| 440 case '2': strcpy(buf, ":-("); break; | |
| 441 case '3': strcpy(buf, ";-)"); break; | |
| 442 case '4': strcpy(buf, ":-P"); break; | |
| 443 case '5': strcpy(buf, "=-O"); break; | |
| 444 case '6': strcpy(buf, ":-*"); break; | |
| 445 case '7': strcpy(buf, ">:o"); break; | |
| 446 case '8': strcpy(buf, "8-)"); break; | |
| 447 case '!': strcpy(buf, ":-$"); break; | |
| 448 case '@': strcpy(buf, ":-!"); break; | |
| 449 case '#': strcpy(buf, ":-["); break; | |
| 450 case '$': strcpy(buf, "O:-)"); break; | |
| 451 case '%': strcpy(buf, ":-/"); break; | |
| 452 case '^': strcpy(buf, ":'("); break; | |
| 453 case '&': strcpy(buf, ":-X"); break; | |
| 454 case '*': strcpy(buf, ":-D"); break; | |
| 6066 | 455 } |
| 8456 | 456 if (*buf && imhtml->smiley_shortcuts) { |
| 457 gtk_imhtml_insert_smiley(imhtml, imhtml->protocol_name, buf); | |
| 8317 | 458 return TRUE; |
| 459 } | |
| 6066 | 460 return FALSE; |
| 461 } | |
| 462 | |
|
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
463 #if GTK_CHECK_VERSION(2,2,0) |
| 8061 | 464 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { |
| 465 GtkTextIter start, end; | |
| 466 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
| 467 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 468 char *text; | |
| 469 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | |
| 470 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
| 471 | |
| 472 | |
| 473 if (info == TARGET_HTML) { | |
| 8149 | 474 int len; |
| 8148 | 475 char *selection; |
| 8061 | 476 GString *str = g_string_new(NULL); |
| 477 text = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
| 478 | |
| 479 /* Mozilla asks that we start our text/html with the Unicode byte order mark */ | |
| 480 str = g_string_append_unichar(str, 0xfeff); | |
| 481 str = g_string_append(str, text); | |
| 482 str = g_string_append_unichar(str, 0x0000); | |
| 8148 | 483 selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
| 8061 | 484 gtk_selection_data_set (selection_data, gdk_atom_intern("text/html", FALSE), 16, selection, len); |
| 485 g_string_free(str, TRUE); | |
| 486 g_free(selection); | |
| 487 } else { | |
| 488 text = gtk_text_buffer_get_text(imhtml->text_buffer, &start, &end, FALSE); | |
| 489 gtk_selection_data_set_text(selection_data, text, strlen(text)); | |
| 490 } | |
| 491 g_free(text); | |
| 492 } | |
| 493 | |
| 494 static void gtk_imhtml_primary_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml) | |
| 7749 | 495 { |
| 8061 | 496 GtkTextIter insert; |
| 497 GtkTextIter selection_bound; | |
| 498 | |
| 499 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &insert, | |
| 500 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert")); | |
| 501 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &selection_bound, | |
| 502 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound")); | |
| 503 | |
| 504 if (!gtk_text_iter_equal (&insert, &selection_bound)) | |
| 505 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
| 506 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound"), | |
| 507 &insert); | |
| 7749 | 508 } |
| 7742 | 509 |
| 7749 | 510 static void copy_clipboard_cb(GtkIMHtml *imhtml, GtkClipboard *clipboard) |
| 511 { | |
| 8061 | 512 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), |
| 513 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
| 514 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
| 515 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | |
| 7346 | 516 |
| 8061 | 517 g_signal_stop_emission_by_name(imhtml, "copy-clipboard"); |
| 518 } | |
| 519 | |
| 520 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) | |
| 521 { | |
| 522 char *text; | |
| 523 guint16 c; | |
| 524 GtkIMHtml *imhtml = data; | |
| 7809 | 525 |
| 8123 | 526 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) |
| 8105 | 527 return; |
| 528 | |
| 8061 | 529 if (selection_data->length < 0) { |
| 530 text = gtk_clipboard_wait_for_text(clipboard); | |
|
8128
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
531 |
|
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
532 if (text == NULL) |
|
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
533 return; |
|
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
534 |
| 8061 | 535 } else { |
| 536 text = g_malloc((selection_data->format / 8) * selection_data->length); | |
| 537 memcpy(text, selection_data->data, selection_data->length * (selection_data->format / 8)); | |
| 7766 | 538 } |
| 8061 | 539 |
| 540 memcpy (&c, text, 2); | |
| 541 if (c == 0xfeff) { | |
| 542 /* This is UCS2 */ | |
| 543 char *utf8 = g_convert(text+2, (selection_data->length * (selection_data->format / 8)) - 2, "UTF-8", "UCS-2", NULL, NULL, NULL); | |
| 544 g_free(text); | |
| 545 text = utf8; | |
| 546 } | |
| 547 gtk_imhtml_close_tags(imhtml); | |
| 548 gtk_imhtml_append_text_with_images(imhtml, text, GTK_IMHTML_NO_NEWLINE, NULL); | |
| 549 } | |
| 550 | |
| 551 | |
| 552 static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) | |
| 553 { | |
| 554 | |
| 555 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); | |
| 556 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
| 557 paste_received_cb, imhtml); | |
| 558 g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); | |
| 7766 | 559 } |
| 560 | |
| 7346 | 561 static gboolean button_release_cb(GtkIMHtml *imhtml, GdkEventButton event, gpointer the_foibles_of_man) |
| 562 { | |
| 8061 | 563 GtkClipboard *clipboard; |
| 564 if (event.button == 1) { | |
| 565 if ((clipboard = gtk_widget_get_clipboard (GTK_WIDGET (imhtml), | |
| 566 GDK_SELECTION_PRIMARY))) | |
| 567 gtk_text_buffer_remove_selection_clipboard (imhtml->text_buffer, clipboard); | |
| 568 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY), | |
| 569 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
| 570 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
| 571 (GtkClipboardClearFunc)gtk_imhtml_primary_clipboard_clear, G_OBJECT(imhtml)); | |
| 572 } | |
| 7346 | 573 return FALSE; |
| 574 } | |
|
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
575 #endif |
| 5967 | 576 |
| 4263 | 577 |
| 4032 | 578 static GtkTextViewClass *parent_class = NULL; |
| 579 | |
| 580 static void | |
| 581 gtk_imhtml_finalize (GObject *object) | |
| 582 { | |
| 583 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
| 4895 | 584 GList *scalables; |
| 8061 | 585 |
| 4138 | 586 g_hash_table_destroy(imhtml->smiley_data); |
| 4032 | 587 gtk_smiley_tree_destroy(imhtml->default_smilies); |
| 4138 | 588 gdk_cursor_unref(imhtml->hand_cursor); |
| 589 gdk_cursor_unref(imhtml->arrow_cursor); | |
| 8061 | 590 gdk_cursor_unref(imhtml->text_cursor); |
| 8456 | 591 |
| 4735 | 592 if(imhtml->tip_window){ |
| 593 gtk_widget_destroy(imhtml->tip_window); | |
| 594 } | |
| 595 if(imhtml->tip_timer) | |
| 596 gtk_timeout_remove(imhtml->tip_timer); | |
| 597 | |
| 4895 | 598 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
| 599 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
| 600 scale->free(scale); | |
| 601 } | |
| 7991 | 602 |
| 4895 | 603 g_list_free(imhtml->scalables); |
| 4032 | 604 G_OBJECT_CLASS(parent_class)->finalize (object); |
| 605 } | |
| 1428 | 606 |
| 3922 | 607 /* Boring GTK stuff */ |
| 608 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) | |
| 1428 | 609 { |
| 3922 | 610 GtkObjectClass *object_class; |
| 4032 | 611 GObjectClass *gobject_class; |
| 3922 | 612 object_class = (GtkObjectClass*) class; |
| 4032 | 613 gobject_class = (GObjectClass*) class; |
| 614 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); | |
| 4417 | 615 signals[URL_CLICKED] = g_signal_new("url_clicked", |
| 616 G_TYPE_FROM_CLASS(gobject_class), | |
| 617 G_SIGNAL_RUN_FIRST, | |
| 618 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
| 619 NULL, | |
| 620 0, | |
| 621 g_cclosure_marshal_VOID__POINTER, | |
| 622 G_TYPE_NONE, 1, | |
| 623 G_TYPE_POINTER); | |
| 8420 | 624 signals[BUTTONS_UPDATE] = g_signal_new("format_functions_update", |
| 625 G_TYPE_FROM_CLASS(gobject_class), | |
| 626 G_SIGNAL_RUN_FIRST, | |
| 627 G_STRUCT_OFFSET(GtkIMHtmlClass, buttons_update), | |
| 628 NULL, | |
| 629 0, | |
| 630 g_cclosure_marshal_VOID__POINTER, | |
| 631 G_TYPE_NONE, 1, | |
| 632 G_TYPE_INT); | |
| 633 signals[TOGGLE_FORMAT] = g_signal_new("format_function_toggle", | |
| 634 G_TYPE_FROM_CLASS(gobject_class), | |
| 635 G_SIGNAL_RUN_FIRST, | |
| 636 G_STRUCT_OFFSET(GtkIMHtmlClass, toggle_format), | |
| 637 NULL, | |
| 638 0, | |
| 639 g_cclosure_marshal_VOID__POINTER, | |
| 8427 | 640 G_TYPE_NONE, 1, |
| 8420 | 641 G_TYPE_INT); |
| 8427 | 642 signals[CLEAR_FORMAT] = g_signal_new("format_function_clear", |
| 643 G_TYPE_FROM_CLASS(gobject_class), | |
| 644 G_SIGNAL_RUN_FIRST, | |
| 645 G_STRUCT_OFFSET(GtkIMHtmlClass, clear_format), | |
| 646 NULL, | |
| 647 0, | |
| 648 g_cclosure_marshal_VOID__POINTER, | |
| 649 G_TYPE_NONE, 0); | |
| 4032 | 650 gobject_class->finalize = gtk_imhtml_finalize; |
| 1428 | 651 } |
| 652 | |
| 3922 | 653 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
| 1428 | 654 { |
| 3922 | 655 GtkTextIter iter; |
| 656 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
| 657 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
| 658 imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); | |
| 659 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
| 5105 | 660 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
| 3922 | 661 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
| 8061 | 662 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
| 3922 | 663 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
| 8061 | 664 |
| 3922 | 665 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
| 8061 | 666 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ |
| 3922 | 667 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); |
| 668 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
| 669 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
| 670 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
| 671 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
| 672 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
| 673 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
| 7295 | 674 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
| 8061 | 675 gtk_text_buffer_create_tag(imhtml->text_buffer, "LINK", "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); |
| 3922 | 676 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
| 677 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
| 678 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
| 8061 | 679 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
| 2993 | 680 |
| 4253 | 681 imhtml->show_smileys = TRUE; |
| 6124 | 682 imhtml->show_comments = TRUE; |
| 4253 | 683 |
| 4892 | 684 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 4902 | 685 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
| 4032 | 686 imhtml->default_smilies = gtk_smiley_tree_new(); |
| 4735 | 687 |
| 4944 | 688 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
| 4735 | 689 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
| 4944 | 690 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
| 6066 | 691 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
| 8061 | 692 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
| 8091 | 693 |
| 694 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, | |
| 695 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | |
| 696 GDK_ACTION_COPY); | |
| 697 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | |
| 698 | |
| 8427 | 699 #if 0 /* Remove buggy copy-and-paste for 0.76 */ |
|
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
700 #if GTK_CHECK_VERSION(2,2,0) |
| 7353 | 701 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
| 8061 | 702 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
| 7346 | 703 g_signal_connect(G_OBJECT(imhtml), "button-release-event", G_CALLBACK(button_release_cb), imhtml); |
|
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
704 #endif |
| 8427 | 705 #endif |
| 4944 | 706 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
| 4735 | 707 |
| 708 imhtml->tip = NULL; | |
| 709 imhtml->tip_timer = 0; | |
| 710 imhtml->tip_window = NULL; | |
| 4895 | 711 |
| 8061 | 712 imhtml->edit.bold = NULL; |
| 713 imhtml->edit.italic = NULL; | |
| 714 imhtml->edit.underline = NULL; | |
| 715 imhtml->edit.forecolor = NULL; | |
| 716 imhtml->edit.backcolor = NULL; | |
| 717 imhtml->edit.fontface = NULL; | |
| 718 imhtml->edit.sizespan = NULL; | |
| 719 imhtml->edit.fontsize = 3; | |
| 720 | |
| 721 imhtml->format_spans = NULL; | |
| 722 | |
| 4895 | 723 imhtml->scalables = NULL; |
| 8061 | 724 |
| 725 gtk_imhtml_set_editable(imhtml, FALSE); | |
| 2993 | 726 } |
| 727 | |
| 3922 | 728 GtkWidget *gtk_imhtml_new(void *a, void *b) |
| 1428 | 729 { |
| 4635 | 730 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
| 1428 | 731 } |
| 732 | |
| 4635 | 733 GType gtk_imhtml_get_type() |
| 1428 | 734 { |
| 4635 | 735 static GType imhtml_type = 0; |
| 1428 | 736 |
| 737 if (!imhtml_type) { | |
| 4635 | 738 static const GTypeInfo imhtml_info = { |
| 739 sizeof(GtkIMHtmlClass), | |
| 740 NULL, | |
| 741 NULL, | |
| 742 (GClassInitFunc) gtk_imhtml_class_init, | |
| 743 NULL, | |
| 744 NULL, | |
| 1428 | 745 sizeof (GtkIMHtml), |
| 4635 | 746 0, |
| 747 (GInstanceInitFunc) gtk_imhtml_init | |
| 1428 | 748 }; |
| 4635 | 749 |
| 750 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
| 751 "GtkIMHtml", &imhtml_info, 0); | |
| 1428 | 752 } |
| 753 | |
| 754 return imhtml_type; | |
| 755 } | |
| 756 | |
| 4417 | 757 struct url_data { |
| 758 GObject *object; | |
| 759 gchar *url; | |
| 760 }; | |
| 761 | |
| 762 static void url_open(GtkWidget *w, struct url_data *data) { | |
| 763 if(!data) return; | |
| 8061 | 764 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
| 7988 | 765 |
| 4417 | 766 g_object_unref(data->object); |
| 767 g_free(data->url); | |
| 768 g_free(data); | |
| 769 } | |
| 5582 | 770 |
| 4417 | 771 static void url_copy(GtkWidget *w, gchar *url) { |
| 772 GtkClipboard *clipboard; | |
| 773 | |
|
5293
ead927e2543f
[gaim-migrate @ 5665]
Christian Hammond <chipx86@chipx86.com>
parents:
5282
diff
changeset
|
774 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
| 4417 | 775 gtk_clipboard_set_text(clipboard, url, -1); |
| 5582 | 776 |
| 777 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | |
| 778 gtk_clipboard_set_text(clipboard, url, -1); | |
| 4417 | 779 } |
| 780 | |
| 781 /* The callback for an event on a link tag. */ | |
| 5091 | 782 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, char *url) { |
| 4417 | 783 GdkEventButton *event_button = (GdkEventButton *) event; |
| 8061 | 784 if (GTK_IMHTML(imhtml)->editable) |
| 785 return FALSE; | |
| 3922 | 786 if (event->type == GDK_BUTTON_RELEASE) { |
| 8061 | 787 if (event_button->button == 1) { |
| 4417 | 788 GtkTextIter start, end; |
| 789 /* we shouldn't open a URL if the user has selected something: */ | |
| 790 gtk_text_buffer_get_selection_bounds( | |
| 791 gtk_text_iter_get_buffer(arg2), &start, &end); | |
| 792 if(gtk_text_iter_get_offset(&start) != | |
| 793 gtk_text_iter_get_offset(&end)) | |
| 794 return FALSE; | |
| 795 | |
| 796 /* A link was clicked--we emit the "url_clicked" signal | |
| 797 * with the URL as the argument */ | |
| 5091 | 798 g_signal_emit(imhtml, signals[URL_CLICKED], 0, url); |
| 4417 | 799 return FALSE; |
| 800 } else if(event_button->button == 3) { | |
| 4745 | 801 GtkWidget *img, *item, *menu; |
| 4417 | 802 struct url_data *tempdata = g_new(struct url_data, 1); |
| 5091 | 803 tempdata->object = g_object_ref(imhtml); |
| 4417 | 804 tempdata->url = g_strdup(url); |
| 4745 | 805 |
| 5091 | 806 /* Don't want the tooltip around if user right-clicked on link */ |
| 807 if (GTK_IMHTML(imhtml)->tip_window) { | |
| 808 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
| 809 GTK_IMHTML(imhtml)->tip_window = NULL; | |
| 810 } | |
| 811 if (GTK_IMHTML(imhtml)->tip_timer) { | |
| 812 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
| 813 GTK_IMHTML(imhtml)->tip_timer = 0; | |
| 814 } | |
| 8061 | 815 if (GTK_IMHTML(imhtml)->editable) |
| 816 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | |
| 817 else | |
| 818 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
| 4417 | 819 menu = gtk_menu_new(); |
| 4745 | 820 |
| 4417 | 821 /* buttons and such */ |
| 822 | |
|
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
823 if (!strncmp(url, "mailto:", 7)) |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
824 { |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
825 /* Copy E-Mail Address */ |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
826 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
827 GTK_ICON_SIZE_MENU); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
828 item = gtk_image_menu_item_new_with_mnemonic( |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
829 _("_Copy E-Mail Address")); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
830 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
831 g_signal_connect(G_OBJECT(item), "activate", |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
832 G_CALLBACK(url_copy), url + 7); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
833 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
834 } |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
835 else |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
836 { |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
837 /* Copy Link Location */ |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
838 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
839 GTK_ICON_SIZE_MENU); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
840 item = gtk_image_menu_item_new_with_mnemonic( |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
841 _("_Copy Link Location")); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
842 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
843 g_signal_connect(G_OBJECT(item), "activate", |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
844 G_CALLBACK(url_copy), url); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
845 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
846 |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
847 /* Open Link in Browser */ |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
848 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
849 GTK_ICON_SIZE_MENU); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
850 item = gtk_image_menu_item_new_with_mnemonic( |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
851 _("_Open Link in Browser")); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
852 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
853 g_signal_connect(G_OBJECT(item), "activate", |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
854 G_CALLBACK(url_open), tempdata); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
855 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
856 } |
|
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
857 |
| 4756 | 858 |
| 4417 | 859 gtk_widget_show_all(menu); |
| 4756 | 860 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
| 861 event_button->button, event_button->time); | |
| 4745 | 862 |
| 4417 | 863 return TRUE; |
| 864 } | |
| 1428 | 865 } |
| 4417 | 866 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
| 867 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
| 868 be caught by the regular GtkTextView menu */ | |
| 869 else | |
| 870 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
| 1428 | 871 } |
| 872 | |
| 8091 | 873 static void |
| 874 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
| 875 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) | |
| 876 { | |
| 877 if(gtk_imhtml_get_editable(imhtml) && sd->data){ | |
| 878 gchar **links; | |
| 879 gchar *link; | |
| 880 | |
| 881 gaim_str_strip_cr(sd->data); | |
| 882 | |
| 883 links = g_strsplit(sd->data, "\n", 0); | |
| 884 while((link = *links++) != NULL){ | |
| 885 if(gaim_str_has_prefix(link, "http://") || | |
| 886 gaim_str_has_prefix(link, "https://") || | |
| 887 gaim_str_has_prefix(link, "ftp://")){ | |
| 888 gtk_imhtml_insert_link(imhtml, link, link); | |
| 889 } else if (link=='\0') { | |
| 8177 | 890 /* Ignore blank lines */ |
| 8091 | 891 } else { |
| 8177 | 892 /* Special reasons, aka images being put in via other tag, etc. */ |
| 8091 | 893 } |
| 894 } | |
| 895 | |
| 896 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
| 897 } else { | |
| 898 gtk_drag_finish(dc, FALSE, FALSE, t); | |
| 899 } | |
| 900 } | |
| 901 | |
| 4298 | 902 /* this isn't used yet |
| 4032 | 903 static void |
| 4263 | 904 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
| 905 GtkIMHtmlSmiley *smiley) | |
| 4032 | 906 { |
| 907 GtkSmileyTree *t = tree; | |
| 4263 | 908 const gchar *x = smiley->smile; |
| 4032 | 909 gint len = 0; |
| 910 | |
| 911 while (*x) { | |
| 912 gchar *pos; | |
| 913 | |
| 914 if (!t->values) | |
| 915 return; | |
| 916 | |
| 917 pos = strchr (t->values->str, *x); | |
| 918 if (pos) | |
| 919 t = t->children [(int) pos - (int) t->values->str]; | |
| 920 else | |
| 921 return; | |
| 922 | |
| 923 x++; len++; | |
| 924 } | |
| 925 | |
|
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
926 if (t->image) { |
| 4032 | 927 t->image = NULL; |
|
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
928 } |
| 4032 | 929 } |
| 4298 | 930 */ |
| 931 | |
| 4032 | 932 |
| 933 static gint | |
| 934 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
| 935 const gchar *text) | |
| 936 { | |
| 937 GtkSmileyTree *t = tree; | |
| 938 const gchar *x = text; | |
| 939 gint len = 0; | |
| 940 | |
| 941 while (*x) { | |
| 942 gchar *pos; | |
| 943 | |
| 944 if (!t->values) | |
| 945 break; | |
| 946 | |
| 947 pos = strchr (t->values->str, *x); | |
| 948 if (pos) | |
| 7371 | 949 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
| 4032 | 950 else |
| 951 break; | |
| 952 | |
| 953 x++; len++; | |
| 954 } | |
| 955 | |
| 956 if (t->image) | |
| 957 return len; | |
| 958 | |
| 959 return 0; | |
| 960 } | |
| 961 | |
| 962 void | |
| 4263 | 963 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
| 964 gchar *sml, | |
| 965 GtkIMHtmlSmiley *smiley) | |
| 4032 | 966 { |
| 967 GtkSmileyTree *tree; | |
| 968 g_return_if_fail (imhtml != NULL); | |
| 969 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
| 7371 | 970 |
| 4032 | 971 if (sml == NULL) |
| 972 tree = imhtml->default_smilies; | |
| 973 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
| 974 } else { | |
| 975 tree = gtk_smiley_tree_new(); | |
| 4892 | 976 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
| 4032 | 977 } |
| 978 | |
| 4263 | 979 gtk_smiley_tree_insert (tree, smiley); |
| 4032 | 980 } |
| 981 | |
| 982 static gboolean | |
| 983 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
| 984 GSList *fonts, | |
| 985 const gchar *text, | |
| 986 gint *len) | |
| 987 { | |
| 988 GtkSmileyTree *tree; | |
| 5967 | 989 GtkIMHtmlFontDetail *font; |
| 4032 | 990 char *sml = NULL; |
| 991 | |
| 992 if (fonts) { | |
| 993 font = fonts->data; | |
| 994 sml = font->sml; | |
| 995 } | |
| 996 | |
| 997 if (sml == NULL) | |
| 998 tree = imhtml->default_smilies; | |
| 999 else { | |
| 1000 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
| 1001 } | |
| 1002 if (tree == NULL) | |
| 1003 return FALSE; | |
| 7371 | 1004 |
| 4032 | 1005 *len = gtk_smiley_tree_lookup (tree, text); |
| 1006 return (*len > 0); | |
| 1007 } | |
| 1008 | |
|
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1009 GdkPixbufAnimation * |
| 4032 | 1010 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
| 1011 const gchar *sml, | |
| 1012 const gchar *text) | |
| 1013 { | |
| 1014 GtkSmileyTree *t; | |
| 1015 const gchar *x = text; | |
| 1016 if (sml == NULL) | |
| 1017 t = imhtml->default_smilies; | |
| 7371 | 1018 else |
| 4032 | 1019 t = g_hash_table_lookup(imhtml->smiley_data, sml); |
| 7371 | 1020 |
| 4032 | 1021 |
| 1022 if (t == NULL) | |
| 1023 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 1024 | |
| 1025 while (*x) { | |
| 1026 gchar *pos; | |
| 1027 | |
| 1028 if (!t->values) { | |
| 1029 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 1030 } | |
| 7371 | 1031 |
| 4032 | 1032 pos = strchr (t->values->str, *x); |
| 1033 if (pos) { | |
| 7371 | 1034 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
| 4032 | 1035 } else { |
| 1036 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
| 1037 } | |
| 1038 x++; | |
| 1039 } | |
| 1040 | |
| 4263 | 1041 if (!t->image->icon) |
|
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1042 t->image->icon = gdk_pixbuf_animation_new_from_file(t->image->file, NULL); |
| 4263 | 1043 |
| 1044 return t->image->icon; | |
| 4032 | 1045 } |
| 4793 | 1046 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
| 3922 | 1047 *tag = g_strndup (string, strlen (x)); \ |
| 1048 *len = strlen (x) + 1; \ | |
| 1049 return TRUE; \ | |
| 1050 } \ | |
| 1051 (*type)++ | |
| 1428 | 1052 |
| 4793 | 1053 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
| 3922 | 1054 const gchar *c = string + strlen (x " "); \ |
| 1055 gchar e = '"'; \ | |
| 1056 gboolean quote = FALSE; \ | |
| 1057 while (*c) { \ | |
| 1058 if (*c == '"' || *c == '\'') { \ | |
| 1059 if (quote && (*c == e)) \ | |
| 1060 quote = !quote; \ | |
| 1061 else if (!quote) { \ | |
| 1062 quote = !quote; \ | |
| 1063 e = *c; \ | |
| 1064 } \ | |
| 1065 } else if (!quote && (*c == '>')) \ | |
| 1066 break; \ | |
| 1067 c++; \ | |
| 1068 } \ | |
| 1069 if (*c) { \ | |
| 1070 *tag = g_strndup (string, c - string); \ | |
| 1071 *len = c - string + 1; \ | |
| 1072 return TRUE; \ | |
| 1073 } \ | |
| 1074 } \ | |
| 1075 (*type)++ | |
| 1428 | 1076 |
| 1077 | |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1078 static gboolean |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1079 gtk_imhtml_is_amp_escape (const gchar *string, |
| 7280 | 1080 gchar **replace, |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1081 gint *length) |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1082 { |
| 7287 | 1083 static char buf[7]; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1084 g_return_val_if_fail (string != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1085 g_return_val_if_fail (replace != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1086 g_return_val_if_fail (length != NULL, FALSE); |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1087 |
| 4793 | 1088 if (!g_ascii_strncasecmp (string, "&", 5)) { |
| 7280 | 1089 *replace = "&"; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1090 *length = 5; |
| 4793 | 1091 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
| 7280 | 1092 *replace = "<"; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1093 *length = 4; |
| 4793 | 1094 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
| 7280 | 1095 *replace = ">"; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1096 *length = 4; |
| 4793 | 1097 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
| 7280 | 1098 *replace = " "; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1099 *length = 6; |
| 4793 | 1100 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
| 7280 | 1101 *replace = "©"; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1102 *length = 6; |
| 4793 | 1103 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
| 7280 | 1104 *replace = "\""; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1105 *length = 6; |
| 4793 | 1106 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
| 7280 | 1107 *replace = "®"; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1108 *length = 5; |
| 5093 | 1109 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
| 7280 | 1110 *replace = "\'"; |
| 5093 | 1111 *length = 6; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1112 } else if (*(string + 1) == '#') { |
|
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
1113 guint pound = 0; |
| 3004 | 1114 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
| 7287 | 1115 int buflen; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1116 if (*(string + 3 + (gint)log10 (pound)) != ';') |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1117 return FALSE; |
| 7287 | 1118 buflen = g_unichar_to_utf8((gunichar)pound, buf); |
| 1119 buf[buflen] = '\0'; | |
| 7280 | 1120 *replace = buf; |
|
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1121 *length = 2; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1122 while (isdigit ((gint) string [*length])) (*length)++; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1123 if (string [*length] == ';') (*length)++; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1124 } else { |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1125 return FALSE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1126 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1127 } else { |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1128 return FALSE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1129 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1130 |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1131 return TRUE; |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1132 } |
|
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1133 |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1134 static gboolean |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1135 gtk_imhtml_is_tag (const gchar *string, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1136 gchar **tag, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1137 gint *len, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1138 gint *type) |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1139 { |
| 8061 | 1140 char *close; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1141 *type = 1; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1142 |
| 8118 | 1143 |
| 8061 | 1144 if (!(close = strchr (string, '>'))) |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1145 return FALSE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1146 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1147 VALID_TAG ("B"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1148 VALID_TAG ("BOLD"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1149 VALID_TAG ("/B"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1150 VALID_TAG ("/BOLD"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1151 VALID_TAG ("I"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1152 VALID_TAG ("ITALIC"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1153 VALID_TAG ("/I"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1154 VALID_TAG ("/ITALIC"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1155 VALID_TAG ("U"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1156 VALID_TAG ("UNDERLINE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1157 VALID_TAG ("/U"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1158 VALID_TAG ("/UNDERLINE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1159 VALID_TAG ("S"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1160 VALID_TAG ("STRIKE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1161 VALID_TAG ("/S"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1162 VALID_TAG ("/STRIKE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1163 VALID_TAG ("SUB"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1164 VALID_TAG ("/SUB"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1165 VALID_TAG ("SUP"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1166 VALID_TAG ("/SUP"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1167 VALID_TAG ("PRE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1168 VALID_TAG ("/PRE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1169 VALID_TAG ("TITLE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1170 VALID_TAG ("/TITLE"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1171 VALID_TAG ("BR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1172 VALID_TAG ("HR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1173 VALID_TAG ("/FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1174 VALID_TAG ("/A"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1175 VALID_TAG ("P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1176 VALID_TAG ("/P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1177 VALID_TAG ("H3"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1178 VALID_TAG ("/H3"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1179 VALID_TAG ("HTML"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1180 VALID_TAG ("/HTML"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1181 VALID_TAG ("BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1182 VALID_TAG ("/BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1183 VALID_TAG ("FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1184 VALID_TAG ("HEAD"); |
| 2993 | 1185 VALID_TAG ("/HEAD"); |
| 1186 VALID_TAG ("BINARY"); | |
| 1187 VALID_TAG ("/BINARY"); | |
| 5093 | 1188 |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1189 VALID_OPT_TAG ("HR"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1190 VALID_OPT_TAG ("FONT"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1191 VALID_OPT_TAG ("BODY"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1192 VALID_OPT_TAG ("A"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1193 VALID_OPT_TAG ("IMG"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1194 VALID_OPT_TAG ("P"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1195 VALID_OPT_TAG ("H3"); |
| 5093 | 1196 VALID_OPT_TAG ("HTML"); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1197 |
| 5101 | 1198 VALID_TAG ("CITE"); |
| 1199 VALID_TAG ("/CITE"); | |
| 1200 VALID_TAG ("EM"); | |
| 1201 VALID_TAG ("/EM"); | |
| 1202 VALID_TAG ("STRONG"); | |
| 1203 VALID_TAG ("/STRONG"); | |
| 1204 | |
| 5104 | 1205 VALID_OPT_TAG ("SPAN"); |
| 1206 VALID_TAG ("/SPAN"); | |
| 5174 | 1207 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
| 6982 | 1208 VALID_TAG ("IMG"); |
| 8026 | 1209 VALID_TAG("SPAN"); |
| 8061 | 1210 VALID_OPT_TAG("BR"); |
| 7988 | 1211 |
| 4793 | 1212 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
|
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
1213 gchar *e = strstr (string + strlen("!--"), "-->"); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1214 if (e) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1215 *len = e - string + strlen ("-->"); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1216 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1217 return TRUE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1218 } |
| 8118 | 1219 } |
| 1220 | |
| 8061 | 1221 *type = -1; |
| 1222 *len = close - string + 1; | |
| 1223 *tag = g_strndup(string, *len - 1); | |
| 1224 return TRUE; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1225 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1226 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1227 static gchar* |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1228 gtk_imhtml_get_html_opt (gchar *tag, |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1229 const gchar *opt) |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1230 { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1231 gchar *t = tag; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1232 gchar *e, *a; |
| 5177 | 1233 gchar *val; |
| 1234 gint len; | |
| 7280 | 1235 gchar *c; |
| 5177 | 1236 GString *ret; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1237 |
| 4793 | 1238 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1239 gboolean quote = FALSE; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1240 if (*t == '\0') break; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1241 while (*t && !((*t == ' ') && !quote)) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1242 if (*t == '\"') |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1243 quote = ! quote; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1244 t++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1245 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1246 while (*t && (*t == ' ')) t++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1247 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1248 |
| 4793 | 1249 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1250 t += strlen (opt); |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1251 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1252 return NULL; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1253 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1254 |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1255 if ((*t == '\"') || (*t == '\'')) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1256 e = a = ++t; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1257 while (*e && (*e != *(t - 1))) e++; |
| 2993 | 1258 if (*e == '\0') { |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1259 return NULL; |
| 5177 | 1260 } else |
| 1261 val = g_strndup(a, e - a); | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1262 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1263 e = a = t; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1264 while (*e && !isspace ((gint) *e)) e++; |
| 5177 | 1265 val = g_strndup(a, e - a); |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1266 } |
| 5177 | 1267 |
| 1268 ret = g_string_new(""); | |
| 1269 e = val; | |
| 1270 while(*e) { | |
| 1271 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
| 7280 | 1272 ret = g_string_append(ret, c); |
| 5177 | 1273 e += len; |
| 1274 } else { | |
| 1275 ret = g_string_append_c(ret, *e); | |
| 1276 e++; | |
| 1277 } | |
| 1278 } | |
| 1279 | |
| 1280 g_free(val); | |
| 1281 val = ret->str; | |
| 1282 g_string_free(ret, FALSE); | |
| 1283 return val; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1284 } |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1285 |
| 8118 | 1286 /* Inline CSS Support - Douglas Thrift */ |
| 1287 static gchar* | |
| 1288 gtk_imhtml_get_css_opt (gchar *style, | |
| 1289 const gchar *opt) | |
| 1290 { | |
| 1291 gchar *t = style; | |
| 1292 gchar *e, *a; | |
| 1293 gchar *val; | |
| 1294 gint len; | |
| 1295 gchar *c; | |
| 1296 GString *ret; | |
| 1297 | |
| 1298 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
| 8177 | 1299 /* gboolean quote = FALSE; */ |
| 8118 | 1300 if (*t == '\0') break; |
| 1301 while (*t && !((*t == ' ') /*&& !quote*/)) { | |
| 1302 /* if (*t == '\"') | |
| 8177 | 1303 quote = ! quote; */ |
| 8118 | 1304 t++; |
| 1305 } | |
| 1306 while (*t && (*t == ' ')) t++; | |
| 1307 } | |
| 1308 | |
| 1309 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
| 1310 t += strlen (opt); | |
| 1311 } else { | |
| 1312 return NULL; | |
| 1313 } | |
| 1314 | |
| 1315 /* if ((*t == '\"') || (*t == '\'')) { | |
| 1316 e = a = ++t; | |
| 1317 while (*e && (*e != *(t - 1))) e++; | |
| 1318 if (*e == '\0') { | |
| 1319 return NULL; | |
| 1320 } else | |
| 1321 val = g_strndup(a, e - a); | |
| 1322 } else { | |
| 1323 e = a = t; | |
| 1324 while (*e && !isspace ((gint) *e)) e++; | |
| 1325 val = g_strndup(a, e - a); | |
| 1326 }*/ | |
| 1327 | |
| 1328 e = a = t; | |
| 1329 while (*e && *e != ';') e++; | |
| 1330 val = g_strndup(a, e - a); | |
| 1331 | |
| 1332 ret = g_string_new(""); | |
| 1333 e = val; | |
| 1334 while(*e) { | |
| 1335 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
| 1336 ret = g_string_append(ret, c); | |
| 1337 e += len; | |
| 1338 } else { | |
| 1339 ret = g_string_append_c(ret, *e); | |
| 1340 e++; | |
| 1341 } | |
| 1342 } | |
| 1343 | |
| 1344 g_free(val); | |
| 1345 val = ret->str; | |
| 1346 g_string_free(ret, FALSE); | |
| 1347 return val; | |
| 1348 } | |
| 3922 | 1349 |
| 8334 | 1350 static const char *accepted_protocols[] = { |
| 1351 "http://", | |
| 1352 "https://", | |
| 1353 "ftp://" | |
| 1354 }; | |
| 1355 | |
| 1356 static const int accepted_protocols_size = 3; | |
| 1357 | |
| 1358 /* returns if the beginning of the text is a protocol. If it is the protocol, returns the length so | |
| 1359 the caller knows how long the protocol string is. */ | |
| 1360 int gtk_imhtml_is_protocol(const char *text) | |
| 1361 { | |
| 1362 gint i; | |
| 1363 | |
| 1364 for(i=0; i<accepted_protocols_size; i++){ | |
| 1365 if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ | |
| 1366 return strlen(accepted_protocols[i]); | |
| 1367 } | |
| 1368 } | |
| 1369 return 0; | |
| 1370 } | |
| 1371 | |
| 6982 | 1372 GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, |
| 1373 const gchar *text, | |
| 1374 GtkIMHtmlOptions options, | |
| 1375 GSList *images) | |
| 1428 | 1376 { |
| 8061 | 1377 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); |
| 1378 GtkTextIter insert; | |
| 1379 GdkRectangle rect; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1380 gint pos = 0; |
| 3922 | 1381 GString *str = NULL; |
| 8061 | 1382 GtkTextIter iter; |
| 1383 GtkTextMark *mark; | |
| 3922 | 1384 gchar *ws; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1385 gchar *tag; |
| 3922 | 1386 gchar *url = NULL; |
| 1387 gchar *bg = NULL; | |
| 6982 | 1388 gint len; |
| 4032 | 1389 gint tlen, smilelen, wpos=0; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1390 gint type; |
| 3922 | 1391 const gchar *c; |
| 7280 | 1392 gchar *amp; |
| 8334 | 1393 gint len_protocol; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1394 |
| 1428 | 1395 guint bold = 0, |
| 1396 italics = 0, | |
| 1397 underline = 0, | |
| 1398 strike = 0, | |
| 1399 sub = 0, | |
| 1400 sup = 0, | |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1401 title = 0, |
| 8061 | 1402 pre = 0; |
| 1428 | 1403 |
| 3922 | 1404 GSList *fonts = NULL; |
| 8061 | 1405 GtkIMHtmlScalable *scalable = NULL; |
| 4612 | 1406 int y, height; |
| 1407 | |
| 8420 | 1408 printf("Appending: %s\n", text); |
| 4895 | 1409 |
| 1428 | 1410 g_return_val_if_fail (imhtml != NULL, NULL); |
| 1411 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | |
| 1412 g_return_val_if_fail (text != NULL, NULL); | |
| 3922 | 1413 c = text; |
| 6982 | 1414 len = strlen(text); |
| 3922 | 1415 ws = g_malloc(len + 1); |
| 1416 ws[0] = 0; | |
| 1428 | 1417 |
| 1418 if (options & GTK_IMHTML_RETURN_LOG) | |
| 3922 | 1419 str = g_string_new(""); |
| 1428 | 1420 |
| 8061 | 1421 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &insert, ins); |
| 1422 | |
| 3922 | 1423 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); |
| 1424 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
| 4612 | 1425 |
| 8061 | 1426 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
| 4612 | 1427 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); |
| 1428 | |
| 8061 | 1429 #if GTK_CHECK_VERSION(2,2,0) |
| 1430 gtk_imhtml_primary_clipboard_clear(NULL, imhtml); | |
| 1431 #endif | |
| 1432 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
| 1433 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert"), | |
| 1434 &iter); | |
| 1435 | |
| 1436 if(((y + height) - (rect.y + rect.height)) > height | |
| 4612 | 1437 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ |
| 1438 options |= GTK_IMHTML_NO_SCROLL; | |
| 1439 } | |
| 1440 | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1441 while (pos < len) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1442 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1443 c++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1444 pos++; |
| 8061 | 1445 ws[wpos] = '\0'; |
| 1446 switch (type) | |
| 3922 | 1447 { |
| 1448 case 1: /* B */ | |
| 1449 case 2: /* BOLD */ | |
| 5101 | 1450 case 54: /* STRONG */ |
| 8061 | 1451 if (url) |
| 1452 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1453 else | |
| 1454 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1455 if (bold == 0) | |
| 1456 gtk_imhtml_toggle_bold(imhtml); | |
| 3922 | 1457 bold++; |
| 8061 | 1458 ws[0] = '\0'; wpos = 0; |
| 3922 | 1459 break; |
| 1460 case 3: /* /B */ | |
| 1461 case 4: /* /BOLD */ | |
| 5101 | 1462 case 55: /* /STRONG */ |
| 8061 | 1463 if (url) |
| 1464 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1465 else | |
| 1466 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1467 ws[0] = '\0'; wpos = 0; | |
| 1468 | |
| 3922 | 1469 if (bold) |
| 1470 bold--; | |
| 8061 | 1471 if (bold == 0) |
| 1472 gtk_imhtml_toggle_bold(imhtml); | |
| 3922 | 1473 break; |
| 1474 case 5: /* I */ | |
| 1475 case 6: /* ITALIC */ | |
| 5101 | 1476 case 52: /* EM */ |
| 8061 | 1477 if (url) |
| 1478 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1479 else | |
| 1480 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1481 ws[0] = '\0'; wpos = 0; | |
| 1482 if (italics == 0) | |
| 1483 gtk_imhtml_toggle_italic(imhtml); | |
| 3922 | 1484 italics++; |
| 1485 break; | |
| 1486 case 7: /* /I */ | |
| 1487 case 8: /* /ITALIC */ | |
| 5101 | 1488 case 53: /* /EM */ |
| 8061 | 1489 if (url) |
| 1490 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1491 else | |
| 1492 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1493 ws[0] = '\0'; wpos = 0; | |
| 3922 | 1494 if (italics) |
| 1495 italics--; | |
| 8061 | 1496 if (italics == 0) |
| 1497 gtk_imhtml_toggle_italic(imhtml); | |
| 3922 | 1498 break; |
| 1499 case 9: /* U */ | |
| 1500 case 10: /* UNDERLINE */ | |
| 8061 | 1501 if (url) |
| 1502 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1503 else | |
| 1504 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1505 ws[0] = '\0'; wpos = 0; | |
| 1506 if (underline == 0) | |
| 1507 gtk_imhtml_toggle_underline(imhtml); | |
| 3922 | 1508 underline++; |
| 1509 break; | |
| 1510 case 11: /* /U */ | |
| 1511 case 12: /* /UNDERLINE */ | |
| 8061 | 1512 if (url) |
| 1513 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1514 else | |
| 1515 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1516 ws[0] = '\0'; wpos = 0; | |
| 3922 | 1517 if (underline) |
| 1518 underline--; | |
| 8061 | 1519 if (underline == 0) |
| 1520 gtk_imhtml_toggle_underline(imhtml); | |
| 3922 | 1521 break; |
| 1522 case 13: /* S */ | |
| 1523 case 14: /* STRIKE */ | |
| 8177 | 1524 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1525 strike++; |
| 1526 break; | |
| 1527 case 15: /* /S */ | |
| 1528 case 16: /* /STRIKE */ | |
| 8177 | 1529 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1530 if (strike) |
| 1531 strike--; | |
| 1532 break; | |
| 1533 case 17: /* SUB */ | |
| 8177 | 1534 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1535 sub++; |
| 1536 break; | |
| 1537 case 18: /* /SUB */ | |
| 8177 | 1538 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1539 if (sub) |
| 1540 sub--; | |
| 1541 break; | |
| 1542 case 19: /* SUP */ | |
| 8177 | 1543 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1544 sup++; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1545 break; |
| 3922 | 1546 case 20: /* /SUP */ |
| 8177 | 1547 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1548 if (sup) |
| 1549 sup--; | |
| 1550 break; | |
| 1551 case 21: /* PRE */ | |
| 8177 | 1552 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1553 pre++; |
| 1554 break; | |
| 1555 case 22: /* /PRE */ | |
| 8177 | 1556 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1557 if (pre) |
| 1558 pre--; | |
| 1559 break; | |
| 1560 case 23: /* TITLE */ | |
| 8177 | 1561 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 3922 | 1562 title++; |
| 1563 break; | |
| 1564 case 24: /* /TITLE */ | |
| 1565 if (title) { | |
| 1566 if (options & GTK_IMHTML_NO_TITLE) { | |
| 1567 wpos = 0; | |
| 1568 ws [wpos] = '\0'; | |
| 1569 } | |
| 1570 title--; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1571 } |
| 3922 | 1572 break; |
| 1573 case 25: /* BR */ | |
| 5174 | 1574 case 58: /* BR/ */ |
| 8061 | 1575 case 61: /* BR (opt) */ |
| 3922 | 1576 ws[wpos] = '\n'; |
| 1577 wpos++; | |
| 8177 | 1578 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 6982 | 1579 break; |
| 3922 | 1580 case 26: /* HR */ |
| 1581 case 42: /* HR (opt) */ | |
| 1582 ws[wpos++] = '\n'; | |
| 8061 | 1583 if (url) |
| 1584 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1585 else | |
| 1586 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 5967 | 1587 scalable = gtk_imhtml_hr_new(); |
| 8061 | 1588 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
| 1589 scalable->add_to(scalable, imhtml, &iter); | |
| 1590 scalable->scale(scalable, rect.width, rect.height); | |
| 1591 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
| 1592 ws[0] = '\0'; wpos = 0; | |
| 7942 | 1593 ws[wpos++] = '\n'; |
| 8061 | 1594 |
| 3922 | 1595 break; |
| 1596 case 27: /* /FONT */ | |
| 1597 if (fonts) { | |
| 5967 | 1598 GtkIMHtmlFontDetail *font = fonts->data; |
| 8061 | 1599 if (url) |
| 1600 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1601 else | |
| 1602 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1603 ws[0] = '\0'; wpos = 0; | |
| 8177 | 1604 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 8309 | 1605 |
| 8061 | 1606 if (font->face) { |
| 1607 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
| 3922 | 1608 g_free (font->face); |
| 8061 | 1609 } |
| 1610 if (font->fore) { | |
| 1611 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
| 3922 | 1612 g_free (font->fore); |
| 8061 | 1613 } |
| 1614 if (font->back) { | |
| 1615 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
| 3922 | 1616 g_free (font->back); |
| 8061 | 1617 } |
| 4032 | 1618 if (font->sml) |
| 1619 g_free (font->sml); | |
| 3922 | 1620 g_free (font); |
| 8309 | 1621 |
| 1622 if (font->size != 3) | |
| 1623 gtk_imhtml_font_set_size(imhtml, 3); | |
| 1624 | |
| 1625 fonts = fonts->next; | |
| 1626 if (fonts) { | |
| 1627 GtkIMHtmlFontDetail *font = fonts->data; | |
| 1628 | |
| 1629 if (font->face) | |
| 1630 gtk_imhtml_toggle_fontface(imhtml, font->face); | |
| 1631 if (font->fore) | |
| 1632 gtk_imhtml_toggle_forecolor(imhtml, font->fore); | |
| 1633 if (font->back) | |
| 1634 gtk_imhtml_toggle_backcolor(imhtml, font->back); | |
| 1635 if (font->size != 3) | |
| 1636 gtk_imhtml_font_set_size(imhtml, font->size); | |
| 1637 } | |
| 3922 | 1638 } |
| 8309 | 1639 break; |
| 3922 | 1640 case 28: /* /A */ |
| 1641 if (url) { | |
| 8061 | 1642 gtk_imhtml_insert_link(imhtml, url, ws); |
| 3922 | 1643 g_free(url); |
| 8061 | 1644 ws[0] = '\0'; wpos = 0; |
| 3922 | 1645 url = NULL; |
| 8061 | 1646 ins = gtk_text_buffer_get_insert(imhtml->text_buffer); |
| 1647 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2993 | 1648 } |
| 8061 | 1649 break; |
| 8118 | 1650 |
| 3922 | 1651 case 29: /* P */ |
| 1652 case 30: /* /P */ | |
| 1653 case 31: /* H3 */ | |
| 1654 case 32: /* /H3 */ | |
| 1655 case 33: /* HTML */ | |
| 1656 case 34: /* /HTML */ | |
| 1657 case 35: /* BODY */ | |
| 1658 case 36: /* /BODY */ | |
| 1659 case 37: /* FONT */ | |
| 1660 case 38: /* HEAD */ | |
| 1661 case 39: /* /HEAD */ | |
| 6982 | 1662 case 40: /* BINARY */ |
| 1663 case 41: /* /BINARY */ | |
| 3922 | 1664 break; |
| 1665 case 43: /* FONT (opt) */ | |
| 1666 { | |
| 4032 | 1667 gchar *color, *back, *face, *size, *sml; |
| 5967 | 1668 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
| 3922 | 1669 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
| 1670 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
| 1671 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
| 1672 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
| 4032 | 1673 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
| 1674 if (!(color || back || face || size || sml)) | |
| 3922 | 1675 break; |
| 8061 | 1676 |
| 1677 if (url) | |
| 1678 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1679 else | |
| 1680 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1681 ws[0] = '\0'; wpos = 0; | |
| 1682 | |
| 5967 | 1683 font = g_new0 (GtkIMHtmlFontDetail, 1); |
| 3922 | 1684 if (fonts) |
| 1685 oldfont = fonts->data; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1686 |
| 8309 | 1687 if (color && !(options & GTK_IMHTML_NO_COLOURS)) { |
| 3922 | 1688 font->fore = color; |
| 8061 | 1689 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
| 8309 | 1690 } |
| 1691 //else if (oldfont && oldfont->fore) | |
| 1692 // font->fore = g_strdup(oldfont->fore); | |
| 1693 | |
| 1694 if (back && !(options & GTK_IMHTML_NO_COLOURS)) { | |
| 3922 | 1695 font->back = back; |
| 8061 | 1696 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
| 8309 | 1697 } |
| 1698 //else if (oldfont && oldfont->back) | |
| 1699 // font->back = g_strdup(oldfont->back); | |
| 1700 | |
| 1701 if (face && !(options & GTK_IMHTML_NO_FONTS)) { | |
| 3922 | 1702 font->face = face; |
| 8061 | 1703 gtk_imhtml_toggle_fontface(imhtml, font->face); |
| 8309 | 1704 } |
| 1705 //else if (oldfont && oldfont->face) | |
| 1706 // font->face = g_strdup(oldfont->face); | |
| 4032 | 1707 |
| 1708 if (sml) | |
| 1709 font->sml = sml; | |
| 1710 else if (oldfont && oldfont->sml) | |
| 1711 font->sml = g_strdup(oldfont->sml); | |
| 1712 | |
| 3922 | 1713 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
| 1714 if (*size == '+') { | |
| 1715 sscanf (size + 1, "%hd", &font->size); | |
| 1716 font->size += 3; | |
| 1717 } else if (*size == '-') { | |
| 1718 sscanf (size + 1, "%hd", &font->size); | |
| 1719 font->size = MAX (0, 3 - font->size); | |
| 1720 } else if (isdigit (*size)) { | |
| 1721 sscanf (size, "%hd", &font->size); | |
| 8061 | 1722 } |
| 6042 | 1723 if (font->size > 100) |
| 1724 font->size = 100; | |
| 3922 | 1725 } else if (oldfont) |
| 1726 font->size = oldfont->size; | |
| 8309 | 1727 else |
| 1728 font->size = 3; | |
| 1729 gtk_imhtml_font_set_size(imhtml, font->size); | |
| 3922 | 1730 g_free(size); |
| 1731 fonts = g_slist_prepend (fonts, font); | |
| 1732 } | |
| 1733 break; | |
| 1734 case 44: /* BODY (opt) */ | |
| 1735 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
| 1736 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
| 1737 if (bgcolor) { | |
| 8061 | 1738 if (url) |
| 1739 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1740 else | |
| 1741 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1742 ws[0] = '\0'; wpos = 0; | |
| 8177 | 1743 /* NEW_BIT(NEW_TEXT_BIT); */ |
| 3922 | 1744 if (bg) |
| 1745 g_free(bg); | |
| 1746 bg = bgcolor; | |
| 8061 | 1747 gtk_imhtml_toggle_backcolor(imhtml, bg); |
|
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
1748 } |
| 1428 | 1749 } |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1750 break; |
| 3922 | 1751 case 45: /* A (opt) */ |
| 1752 { | |
| 1753 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
| 1754 if (href) { | |
| 8061 | 1755 if (url) { |
| 1756 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1757 g_free(url); | |
| 1758 } else | |
| 1759 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1760 ws[0] = '\0'; wpos = 0; | |
| 3922 | 1761 url = href; |
| 1762 } | |
| 2993 | 1763 } |
| 3922 | 1764 break; |
| 4895 | 1765 case 46: /* IMG (opt) */ |
| 6982 | 1766 case 59: /* IMG */ |
| 4895 | 1767 { |
| 6982 | 1768 GdkPixbuf *img = NULL; |
| 1769 const gchar *filename = NULL; | |
| 4895 | 1770 |
| 6982 | 1771 if (images && images->data) { |
| 1772 img = images->data; | |
| 1773 images = images->next; | |
| 1774 filename = g_object_get_data(G_OBJECT(img), "filename"); | |
| 1775 g_object_ref(G_OBJECT(img)); | |
| 1776 } else { | |
| 1777 img = gtk_widget_render_icon(GTK_WIDGET(imhtml), | |
| 1778 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, | |
| 1779 "gtkimhtml-missing-image"); | |
| 1780 } | |
| 4895 | 1781 |
| 6982 | 1782 scalable = gtk_imhtml_image_new(img, filename); |
| 8177 | 1783 /* NEW_BIT(NEW_SCALABLE_BIT); */ |
| 6982 | 1784 g_object_unref(G_OBJECT(img)); |
| 4895 | 1785 } |
| 3922 | 1786 case 47: /* P (opt) */ |
| 1787 case 48: /* H3 (opt) */ | |
| 5093 | 1788 case 49: /* HTML (opt) */ |
| 5101 | 1789 case 50: /* CITE */ |
| 1790 case 51: /* /CITE */ | |
| 8026 | 1791 case 56: /* SPAN (opt) */ |
| 8118 | 1792 /* Inline CSS Support - Douglas Thrift |
| 1793 * | |
| 1794 * color | |
| 1795 * font-family | |
| 1796 * font-size | |
| 1797 */ | |
| 1798 { | |
| 1799 gchar *style, *color, *family, *size; | |
| 1800 GtkIMHtmlFontDetail *font, *oldfont = NULL; | |
| 1801 style = gtk_imhtml_get_html_opt (tag, "style="); | |
| 1802 | |
| 1803 if (!style) break; | |
| 1804 | |
| 1805 color = gtk_imhtml_get_css_opt (style, "color: "); | |
| 1806 family = gtk_imhtml_get_css_opt (style, | |
| 1807 "font-family: "); | |
| 1808 size = gtk_imhtml_get_css_opt (style, "font-size: "); | |
| 1809 | |
| 8120 | 1810 if (!(color || family || size)) { |
| 1811 g_free(style); | |
| 1812 break; | |
| 1813 } | |
| 8118 | 1814 |
| 1815 if (url) | |
| 1816 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1817 else | |
| 1818 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1819 ws[0] = '\0'; wpos = 0; | |
| 8177 | 1820 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 8118 | 1821 |
| 1822 font = g_new0 (GtkIMHtmlFontDetail, 1); | |
| 1823 if (fonts) | |
| 1824 oldfont = fonts->data; | |
| 1825 | |
| 1826 if (color && !(options & GTK_IMHTML_NO_COLOURS)) | |
| 1827 font->fore = color; | |
| 1828 else if (oldfont && oldfont->fore) | |
| 1829 font->fore = g_strdup(oldfont->fore); | |
| 1830 | |
| 1831 if (oldfont && oldfont->back) | |
| 1832 font->back = g_strdup(oldfont->back); | |
| 1833 | |
| 1834 if (family && !(options & GTK_IMHTML_NO_FONTS)) | |
| 1835 font->face = family; | |
| 1836 else if (oldfont && oldfont->face) | |
| 1837 font->face = g_strdup(oldfont->face); | |
| 1838 if (font->face && (atoi(font->face) > 100)) { | |
| 1839 g_free(font->face); | |
| 1840 font->face = g_strdup("100"); | |
| 1841 } | |
| 1842 | |
| 1843 if (oldfont && oldfont->sml) | |
| 1844 font->sml = g_strdup(oldfont->sml); | |
| 1845 | |
| 1846 if (size && !(options & GTK_IMHTML_NO_SIZES)) { | |
| 1847 if (g_ascii_strcasecmp(size, "smaller") == 0) | |
| 1848 { | |
| 1849 font->size = 2; | |
| 1850 } | |
| 1851 else if (g_ascii_strcasecmp(size, "larger") == 0) | |
| 1852 { | |
| 1853 font->size = 4; | |
| 1854 } | |
| 1855 else | |
| 1856 { | |
| 1857 font->size = 3; | |
| 1858 } | |
| 1859 } else if (oldfont) | |
| 1860 font->size = oldfont->size; | |
| 1861 | |
| 1862 g_free(style); | |
| 1863 g_free(size); | |
| 1864 fonts = g_slist_prepend (fonts, font); | |
| 1865 } | |
| 1866 break; | |
| 5104 | 1867 case 57: /* /SPAN */ |
| 8118 | 1868 /* Inline CSS Support - Douglas Thrift */ |
| 1869 if (fonts) { | |
| 1870 GtkIMHtmlFontDetail *font = fonts->data; | |
| 1871 if (url) | |
| 1872 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1873 else | |
| 1874 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1875 ws[0] = '\0'; wpos = 0; | |
| 8177 | 1876 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 8118 | 1877 fonts = g_slist_remove (fonts, font); |
| 1878 if (font->face) | |
| 1879 g_free (font->face); | |
| 1880 if (font->fore) | |
| 1881 g_free (font->fore); | |
| 1882 if (font->back) | |
| 1883 g_free (font->back); | |
| 1884 if (font->sml) | |
| 1885 g_free (font->sml); | |
| 1886 g_free (font); | |
| 1887 } | |
| 1888 break; | |
| 8026 | 1889 case 60: /* SPAN */ |
| 2993 | 1890 break; |
| 8061 | 1891 case 62: /* comment */ |
| 8177 | 1892 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 8317 | 1893 ws[wpos] = '\0'; |
| 1894 if (url) | |
| 1895 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1896 else | |
| 1897 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 6124 | 1898 if (imhtml->show_comments) |
| 1899 wpos = g_snprintf (ws, len, "%s", tag); | |
| 8177 | 1900 /* NEW_BIT (NEW_COMMENT_BIT); */ |
| 3922 | 1901 break; |
| 1902 default: | |
| 6882 | 1903 break; |
| 2993 | 1904 } |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1905 c += tlen; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1906 pos += tlen; |
| 4138 | 1907 if(tag) |
| 1908 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1909 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
| 7280 | 1910 while(*amp) { |
| 1911 ws [wpos++] = *amp++; | |
| 1912 } | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1913 c += tlen; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1914 pos += tlen; |
| 1428 | 1915 } else if (*c == '\n') { |
| 1916 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
| 3922 | 1917 ws[wpos] = '\n'; |
| 1918 wpos++; | |
| 8061 | 1919 if (url) |
| 1920 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1921 else | |
| 1922 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1923 ws[0] = '\0'; | |
| 1924 wpos = 0; | |
| 8177 | 1925 /* NEW_BIT (NEW_TEXT_BIT); */ |
| 1428 | 1926 } |
| 1927 c++; | |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1928 pos++; |
| 8334 | 1929 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
| 1930 while(len_protocol--){ | |
| 1931 /* Skip the next len_protocol characters, but make sure they're | |
| 1932 copied into the ws array. | |
| 1933 */ | |
| 1934 ws [wpos++] = *c++; | |
| 1935 pos++; | |
| 1936 } | |
| 4253 | 1937 } else if (imhtml->show_smileys && (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen))) { |
| 5967 | 1938 GtkIMHtmlFontDetail *fd; |
| 8061 | 1939 |
| 4032 | 1940 gchar *sml = NULL; |
| 1941 if (fonts) { | |
| 1942 fd = fonts->data; | |
| 1943 sml = fd->sml; | |
| 1944 } | |
| 8061 | 1945 if (url) |
| 1946 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1947 else { | |
| 1948 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1949 } | |
| 7988 | 1950 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
| 8061 | 1951 gtk_imhtml_insert_smiley(imhtml, sml, ws); |
| 7809 | 1952 |
| 8061 | 1953 ins = gtk_text_buffer_get_insert(imhtml->text_buffer); |
| 1954 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 1955 | |
| 4032 | 1956 c += smilelen; |
| 7809 | 1957 pos += smilelen; |
| 4032 | 1958 wpos = 0; |
| 1959 ws[0] = 0; | |
| 8061 | 1960 } else if (*c) { |
| 1428 | 1961 ws [wpos++] = *c++; |
|
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1962 pos++; |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1963 } else { |
|
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1964 break; |
| 1428 | 1965 } |
| 1966 } | |
| 8061 | 1967 if (url) |
| 1968 gtk_imhtml_insert_link(imhtml, url, ws); | |
| 1969 else | |
| 1970 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
| 1971 ws[0] = '\0'; wpos = 0; | |
| 1972 | |
| 8177 | 1973 /* NEW_BIT(NEW_TEXT_BIT); */ |
| 1428 | 1974 if (url) { |
| 1975 g_free (url); | |
| 3922 | 1976 if (str) |
| 1977 str = g_string_append (str, "</A>"); | |
| 1428 | 1978 } |
| 8061 | 1979 |
| 4032 | 1980 while (fonts) { |
| 5967 | 1981 GtkIMHtmlFontDetail *font = fonts->data; |
| 4032 | 1982 fonts = g_slist_remove (fonts, font); |
| 1983 if (font->face) | |
| 1984 g_free (font->face); | |
| 1985 if (font->fore) | |
| 1986 g_free (font->fore); | |
| 1987 if (font->back) | |
| 1988 g_free (font->back); | |
| 1989 if (font->sml) | |
| 1990 g_free (font->sml); | |
| 1991 g_free (font); | |
| 1992 if (str) | |
| 1993 str = g_string_append (str, "</FONT>"); | |
| 1994 } | |
| 1995 | |
| 3922 | 1996 if (str) { |
| 1428 | 1997 while (bold) { |
| 3922 | 1998 str = g_string_append (str, "</B>"); |
| 1428 | 1999 bold--; |
| 2000 } | |
| 2001 while (italics) { | |
| 3922 | 2002 str = g_string_append (str, "</I>"); |
| 1428 | 2003 italics--; |
| 2004 } | |
| 2005 while (underline) { | |
| 3922 | 2006 str = g_string_append (str, "</U>"); |
| 1428 | 2007 underline--; |
| 2008 } | |
| 2009 while (strike) { | |
| 3922 | 2010 str = g_string_append (str, "</S>"); |
| 1428 | 2011 strike--; |
| 2012 } | |
| 2013 while (sub) { | |
| 3922 | 2014 str = g_string_append (str, "</SUB>"); |
| 1428 | 2015 sub--; |
| 2016 } | |
| 2017 while (sup) { | |
| 3922 | 2018 str = g_string_append (str, "</SUP>"); |
| 1428 | 2019 sup--; |
| 2020 } | |
| 2021 while (title) { | |
| 3922 | 2022 str = g_string_append (str, "</TITLE>"); |
| 1428 | 2023 title--; |
| 2024 } | |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2025 while (pre) { |
| 3922 | 2026 str = g_string_append (str, "</PRE>"); |
|
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2027 pre--; |
|
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2028 } |
| 1428 | 2029 } |
| 4032 | 2030 g_free (ws); |
| 4630 | 2031 if(bg) |
| 2032 g_free(bg); | |
| 8061 | 2033 gtk_imhtml_close_tags(imhtml); |
| 4032 | 2034 if (!(options & GTK_IMHTML_NO_SCROLL)) |
| 2035 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
| 2036 0, TRUE, 0.0, 1.0); | |
| 3922 | 2037 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
| 8061 | 2038 gtk_text_buffer_move_mark (imhtml->text_buffer, |
| 2039 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert"), | |
| 2040 &iter); | |
| 3922 | 2041 return str; |
| 2042 } | |
| 2043 | |
| 4892 | 2044 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
| 2045 { | |
| 4288 | 2046 g_hash_table_destroy(imhtml->smiley_data); |
| 2047 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
| 4892 | 2048 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 4902 | 2049 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
| 4288 | 2050 imhtml->default_smilies = gtk_smiley_tree_new(); |
| 2051 } | |
| 3922 | 2052 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
| 4253 | 2053 gboolean show) |
| 2054 { | |
| 2055 imhtml->show_smileys = show; | |
| 2056 } | |
| 3922 | 2057 |
| 2058 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
| 4253 | 2059 gboolean show) |
| 2060 { | |
| 6124 | 2061 imhtml->show_comments = show; |
| 4253 | 2062 } |
|
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2063 |
| 8456 | 2064 void gtk_imhtml_html_shortcuts (GtkIMHtml *imhtml, |
| 2065 gboolean allow) | |
| 2066 { | |
| 2067 imhtml->html_shortcuts = allow; | |
| 2068 } | |
| 2069 | |
| 2070 void gtk_imhtml_smiley_shortcuts (GtkIMHtml *imhtml, | |
| 2071 gboolean allow) | |
| 2072 { | |
| 2073 imhtml->smiley_shortcuts = allow; | |
| 2074 } | |
| 2075 | |
| 2076 void | |
| 2077 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, gchar *protocol_name) { | |
| 2078 imhtml->protocol_name = protocol_name; | |
| 2079 } | |
| 2080 | |
|
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2081 void |
|
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2082 gtk_imhtml_clear (GtkIMHtml *imhtml) |
|
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2083 { |
| 7991 | 2084 GList *del; |
| 3922 | 2085 GtkTextIter start, end; |
| 8427 | 2086 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
| 7991 | 2087 |
| 3922 | 2088 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
| 2089 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
| 2090 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
| 7991 | 2091 |
| 8061 | 2092 for(del = imhtml->format_spans; del; del = del->next) { |
| 2093 GtkIMHtmlFormatSpan *span = del->data; | |
| 2094 if (span->start_tag) | |
| 2095 g_free(span->start_tag); | |
| 2096 if (span->end_tag) | |
| 2097 g_free(span->end_tag); | |
| 2098 g_free(span); | |
| 2099 } | |
| 2100 g_list_free(imhtml->format_spans); | |
| 2101 imhtml->format_spans = NULL; | |
| 2102 | |
| 7991 | 2103 for(del = imhtml->scalables; del; del = del->next) { |
| 2104 GtkIMHtmlScalable *scale = del->data; | |
| 2105 scale->free(scale); | |
| 2106 } | |
| 2107 g_list_free(imhtml->scalables); | |
| 2108 imhtml->scalables = NULL; | |
| 8061 | 2109 |
| 2110 imhtml->edit.bold = NULL; | |
| 2111 imhtml->edit.italic = NULL; | |
| 2112 imhtml->edit.underline = NULL; | |
| 2113 imhtml->edit.fontface = NULL; | |
| 2114 imhtml->edit.forecolor = NULL; | |
| 2115 imhtml->edit.backcolor = NULL; | |
| 2116 imhtml->edit.sizespan = NULL; | |
| 2117 imhtml->edit.fontsize = 3; | |
| 8427 | 2118 printf("Emiting signal\n"); |
| 2119 g_signal_emit(object, signals[CLEAR_FORMAT], 0); | |
| 2120 g_object_unref(object); | |
|
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2121 } |
|
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
2122 |
| 4046 | 2123 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
| 2124 { | |
| 5282 | 2125 GdkRectangle rect; |
| 2126 GtkTextIter iter; | |
| 4046 | 2127 |
| 5282 | 2128 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
| 2129 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
| 2130 rect.y - rect.height); | |
| 2131 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
| 8061 | 2132 |
| 4046 | 2133 } |
| 5282 | 2134 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
| 2135 { | |
| 2136 GdkRectangle rect; | |
| 2137 GtkTextIter iter; | |
| 2138 | |
| 2139 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
| 2140 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
| 2141 rect.y + rect.height); | |
| 2142 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
| 2143 } | |
| 4735 | 2144 |
| 5967 | 2145 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
| 6982 | 2146 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) |
| 4735 | 2147 { |
| 5967 | 2148 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
| 5012 | 2149 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
| 4895 | 2150 |
| 5967 | 2151 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
| 2152 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
| 2153 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
| 5046 | 2154 |
| 2155 im_image->pixbuf = img; | |
| 5012 | 2156 im_image->image = image; |
| 4895 | 2157 im_image->width = gdk_pixbuf_get_width(img); |
| 2158 im_image->height = gdk_pixbuf_get_height(img); | |
| 2159 im_image->mark = NULL; | |
| 6982 | 2160 im_image->filename = filename ? g_strdup(filename) : NULL; |
| 4895 | 2161 |
| 5046 | 2162 g_object_ref(img); |
| 4895 | 2163 return GTK_IMHTML_SCALABLE(im_image); |
| 2164 } | |
| 2165 | |
| 5967 | 2166 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
| 4895 | 2167 { |
| 5967 | 2168 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
| 4895 | 2169 |
| 2170 if(image->width > width || image->height > height){ | |
| 2171 GdkPixbuf *new_image = NULL; | |
| 2172 float factor; | |
| 2173 int new_width = image->width, new_height = image->height; | |
| 2174 | |
| 2175 if(image->width > width){ | |
| 2176 factor = (float)(width)/image->width; | |
| 2177 new_width = width; | |
| 2178 new_height = image->height * factor; | |
| 2179 } | |
| 2180 if(new_height > height){ | |
| 2181 factor = (float)(height)/new_height; | |
| 2182 new_height = height; | |
| 2183 new_width = new_width * factor; | |
| 2184 } | |
| 2185 | |
| 5046 | 2186 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
| 5012 | 2187 gtk_image_set_from_pixbuf(image->image, new_image); |
| 4895 | 2188 g_object_unref(G_OBJECT(new_image)); |
| 2189 } | |
| 2190 } | |
| 2191 | |
| 5012 | 2192 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
| 2193 { | |
| 2194 const gchar *filename = gtk_file_selection_get_filename(sel); | |
| 5967 | 2195 gchar *dirname; |
| 2196 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
| 5012 | 2197 gchar *type = NULL; |
| 5019 | 2198 GError *error = NULL; |
| 5015 | 2199 #if GTK_CHECK_VERSION(2,2,0) |
| 5012 | 2200 GSList *formats = gdk_pixbuf_get_formats(); |
| 6162 | 2201 #else |
| 2202 char *basename = g_path_get_basename(filename); | |
| 2203 char *ext = strrchr(basename, '.'); | |
| 5959 | 2204 #endif |
| 5012 | 2205 |
| 5967 | 2206 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
| 2207 /* append a / if needed */ | |
| 2208 if (filename[strlen(filename) - 1] != '/') { | |
| 2209 dirname = g_strconcat(filename, "/", NULL); | |
| 2210 } else { | |
| 2211 dirname = g_strdup(filename); | |
| 2212 } | |
| 2213 gtk_file_selection_set_filename(sel, dirname); | |
| 2214 g_free(dirname); | |
| 5959 | 2215 return; |
| 5967 | 2216 } |
| 5959 | 2217 |
| 2218 #if GTK_CHECK_VERSION(2,2,0) | |
| 5012 | 2219 while(formats){ |
| 2220 GdkPixbufFormat *format = formats->data; | |
| 2221 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
| 2222 gpointer p = extensions; | |
| 2223 | |
| 2224 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
| 2225 gchar *fmt_ext = extensions[0]; | |
| 2226 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
| 2227 | |
| 2228 if(!strcmp(fmt_ext, file_ext)){ | |
| 2229 type = gdk_pixbuf_format_get_name(format); | |
| 2230 break; | |
| 2231 } | |
| 2232 | |
| 2233 extensions++; | |
| 2234 } | |
| 2235 | |
| 2236 g_strfreev(p); | |
| 2237 | |
| 2238 if(type) | |
| 2239 break; | |
| 2240 | |
| 2241 formats = formats->next; | |
| 2242 } | |
| 2243 | |
| 5020 | 2244 g_slist_free(formats); |
| 2245 #else | |
| 2246 /* this is really ugly code, but I think it will work */ | |
| 2247 if(ext) { | |
| 2248 ext++; | |
| 2249 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
| 2250 type = g_strdup("jpeg"); | |
| 2251 else if(!g_ascii_strcasecmp(ext, "png")) | |
| 2252 type = g_strdup("png"); | |
| 2253 } | |
| 2254 | |
| 2255 g_free(basename); | |
| 2256 #endif | |
| 2257 | |
| 5012 | 2258 /* If I can't find a valid type, I will just tell the user about it and then assume |
| 2259 it's a png */ | |
| 2260 if(!type){ | |
| 2261 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
| 5967 | 2262 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
| 5012 | 2263 type = g_strdup("png"); |
| 2264 } | |
| 2265 | |
| 5046 | 2266 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
| 5012 | 2267 |
| 2268 if(error){ | |
| 2269 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
| 2270 _("Error saving image: %s"), error->message); | |
| 2271 g_error_free(error); | |
| 2272 } | |
| 2273 | |
| 2274 g_free(type); | |
| 2275 } | |
| 2276 | |
| 5967 | 2277 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
| 5012 | 2278 { |
| 5967 | 2279 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
| 5012 | 2280 |
| 6982 | 2281 if (image->filename) |
| 2282 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
| 5967 | 2283 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
| 5012 | 2284 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
| 2285 G_CALLBACK(write_img_to_file), sel); | |
| 2286 | |
| 2287 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
| 2288 G_CALLBACK(gtk_widget_destroy), sel); | |
| 2289 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
| 8061 | 2290 G_CALLBACK(gtk_widget_destroy), sel); |
| 5012 | 2291 |
| 2292 gtk_widget_show(sel); | |
| 2293 } | |
| 2294 | |
| 5967 | 2295 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
| 5012 | 2296 { |
| 2297 GdkEventButton *event_button = (GdkEventButton *) event; | |
| 2298 | |
| 2299 if (event->type == GDK_BUTTON_RELEASE) { | |
| 2300 if(event_button->button == 3) { | |
| 2301 GtkWidget *img, *item, *menu; | |
| 2302 gchar *text = g_strdup_printf(_("_Save Image...")); | |
| 2303 menu = gtk_menu_new(); | |
| 2304 | |
| 2305 /* buttons and such */ | |
| 2306 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
| 2307 item = gtk_image_menu_item_new_with_mnemonic(text); | |
| 2308 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
| 5967 | 2309 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
| 5012 | 2310 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 2311 | |
| 2312 gtk_widget_show_all(menu); | |
| 2313 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
| 2314 event_button->button, event_button->time); | |
| 2315 | |
| 2316 g_free(text); | |
| 2317 return TRUE; | |
| 2318 } | |
| 2319 } | |
| 2320 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
| 2321 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
| 2322 be caught by the regular GtkTextView menu */ | |
| 2323 else | |
| 2324 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
| 2325 | |
| 2326 } | |
| 5967 | 2327 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
| 2328 { | |
| 2329 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
| 2330 | |
| 2331 g_object_unref(image->pixbuf); | |
| 6982 | 2332 if (image->filename) |
| 2333 g_free(image->filename); | |
| 5967 | 2334 g_free(scale); |
| 2335 } | |
| 2336 | |
| 2337 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
| 2338 { | |
| 2339 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
| 2340 GtkWidget *box = gtk_event_box_new(); | |
| 2341 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
| 2342 | |
| 2343 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
| 2344 | |
| 2345 gtk_widget_show(GTK_WIDGET(image->image)); | |
| 2346 gtk_widget_show(box); | |
| 2347 | |
| 2348 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
| 2349 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
| 2350 } | |
| 2351 | |
| 2352 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
| 2353 { | |
| 2354 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
| 2355 | |
| 2356 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
| 2357 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
| 2358 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
| 2359 | |
| 2360 hr->sep = gtk_hseparator_new(); | |
| 2361 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
| 2362 gtk_widget_show(hr->sep); | |
| 2363 | |
| 2364 return GTK_IMHTML_SCALABLE(hr); | |
| 2365 } | |
| 2366 | |
| 2367 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
| 2368 { | |
| 2369 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width, 2); | |
| 2370 } | |
| 2371 | |
| 2372 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
| 2373 { | |
| 2374 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
| 2375 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
| 8061 | 2376 g_object_set_data(G_OBJECT(anchor), "text_tag", "<hr>"); |
| 5967 | 2377 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
| 2378 } | |
| 2379 | |
| 2380 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
| 2381 { | |
| 2382 g_free(scale); | |
| 2383 } | |
| 7295 | 2384 |
| 2385 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | |
| 2386 { | |
| 2387 GtkTextIter iter, start, end; | |
| 2388 gboolean new_search = TRUE; | |
| 2389 | |
| 2390 g_return_val_if_fail(imhtml != NULL, FALSE); | |
| 2391 g_return_val_if_fail(text != NULL, FALSE); | |
| 8061 | 2392 |
| 7295 | 2393 if (imhtml->search_string && !strcmp(text, imhtml->search_string)) |
| 2394 new_search = FALSE; | |
| 8061 | 2395 |
| 7295 | 2396 if (new_search) { |
| 2397 gtk_imhtml_search_clear(imhtml); | |
| 2398 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
| 2399 } else { | |
| 2400 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, | |
| 8061 | 2401 gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); |
| 7295 | 2402 } |
| 2403 imhtml->search_string = g_strdup(text); | |
| 2404 | |
| 7358 | 2405 if (gtk_source_iter_forward_search(&iter, imhtml->search_string, |
| 2406 GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, | |
| 7295 | 2407 &start, &end, NULL)) { |
| 2408 | |
| 2409 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0); | |
| 2410 gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); | |
| 2411 if (new_search) { | |
| 2412 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); | |
| 8061 | 2413 do |
| 7295 | 2414 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); |
| 8061 | 2415 while (gtk_source_iter_forward_search(&end, imhtml->search_string, |
| 2416 GTK_SOURCE_SEARCH_VISIBLE_ONLY | | |
| 7358 | 2417 GTK_SOURCE_SEARCH_CASE_INSENSITIVE, |
| 7295 | 2418 &start, &end, NULL)); |
| 2419 } | |
| 2420 return TRUE; | |
| 2421 } | |
| 8061 | 2422 |
| 2423 gtk_imhtml_search_clear(imhtml); | |
| 2424 | |
| 7295 | 2425 return FALSE; |
| 2426 } | |
| 2427 | |
| 2428 void gtk_imhtml_search_clear(GtkIMHtml *imhtml) | |
| 2429 { | |
| 2430 GtkTextIter start, end; | |
| 8061 | 2431 |
| 7295 | 2432 g_return_if_fail(imhtml != NULL); |
| 8061 | 2433 |
| 7295 | 2434 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
| 2435 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
| 2436 | |
| 2437 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end); | |
| 2438 if (imhtml->search_string) | |
| 2439 g_free(imhtml->search_string); | |
| 2440 imhtml->search_string = NULL; | |
| 2441 } | |
| 8061 | 2442 |
| 2443 /* Editable stuff */ | |
| 2444 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | |
| 2445 { | |
| 2446 GtkIMHtmlFormatSpan *span = NULL; | |
| 2447 GtkTextIter end; | |
| 2448 | |
| 2449 gtk_text_iter_forward_chars(iter, len); | |
| 2450 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
| 2451 gtk_text_iter_forward_char(&end); | |
| 2452 | |
| 2453 if (!gtk_text_iter_equal(&end, iter)) | |
| 2454 return; | |
| 2455 | |
| 2456 | |
| 2457 if ((span = imhtml->edit.bold)) { | |
| 2458 GtkTextIter bold; | |
| 2459 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &bold, span->start); | |
| 2460 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &bold, iter); | |
| 2461 } | |
| 2462 | |
| 2463 if ((span = imhtml->edit.italic)) { | |
| 2464 GtkTextIter italic; | |
| 2465 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &italic, span->start); | |
| 2466 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &italic, | |
| 2467 iter); | |
| 2468 } | |
| 2469 | |
| 2470 if ((span = imhtml->edit.underline)) { | |
| 2471 GtkTextIter underline; | |
| 2472 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &underline, span->start); | |
| 2473 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &underline, | |
| 2474 iter); | |
| 2475 } | |
| 2476 | |
| 2477 if ((span = imhtml->edit.forecolor)) { | |
| 2478 GtkTextIter fore; | |
| 2479 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &fore, span->start); | |
| 2480 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &fore, iter); | |
| 2481 } | |
| 2482 | |
| 2483 if ((span = imhtml->edit.backcolor)) { | |
| 2484 GtkTextIter back; | |
| 2485 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &back, span->start); | |
| 2486 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &back, iter); | |
| 2487 } | |
| 2488 | |
| 2489 if ((span = imhtml->edit.fontface)) { | |
| 2490 GtkTextIter face; | |
| 2491 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &face, span->start); | |
| 2492 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &face, iter); | |
| 2493 } | |
| 2494 | |
| 2495 if ((span = imhtml->edit.sizespan)) { | |
| 2496 GtkTextIter size; | |
| 2497 /* We create the tags here so that one can grow font or shrink font several times | |
| 2498 * in a row without creating unnecessary tags */ | |
| 2499 if (span->tag == NULL) { | |
| 2500 span->tag = gtk_text_buffer_create_tag | |
| 8309 | 2501 (imhtml->text_buffer, NULL, "scale", (double)_point_sizes [imhtml->edit.fontsize-1], NULL); |
| 8061 | 2502 span->start_tag = g_strdup_printf("<font size=\"%d\">", imhtml->edit.fontsize); |
| 2503 span->end_tag = g_strdup("</font>"); | |
| 2504 } | |
| 2505 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &size, span->start); | |
| 2506 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &size, iter); | |
| 2507 } | |
| 2508 } | |
| 2509 | |
| 2510 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | |
| 2511 { | |
| 2512 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | |
| 8177 | 2513 /* |
| 2514 * We need a visible caret for accessibility, so mouseless | |
| 2515 * people can highlight stuff. | |
| 2516 */ | |
| 2517 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | |
| 8061 | 2518 imhtml->editable = editable; |
| 8420 | 2519 imhtml->format_functions = !editable ? 0 : -1; |
| 2520 } | |
| 2521 | |
| 2522 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | |
| 2523 { | |
| 2524 GObject *object = g_object_ref(G_OBJECT(imhtml)); | |
| 2525 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); | |
| 2526 imhtml->format_functions = buttons; | |
| 2527 g_object_unref(object); | |
| 8061 | 2528 } |
| 2529 | |
| 2530 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) | |
| 2531 { | |
| 2532 return imhtml->editable; | |
| 2533 } | |
| 2534 | |
| 2535 gboolean gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) | |
| 2536 { | |
| 2537 GtkIMHtmlFormatSpan *span; | |
| 2538 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2539 GtkTextIter iter; | |
| 2540 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2541 if (!imhtml->edit.bold) { | |
| 2542 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
| 2543 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2544 span->start_tag = g_strdup("<b>"); | |
| 2545 span->end = NULL; | |
| 2546 span->end_tag = g_strdup("</b>"); | |
| 2547 span->buffer = imhtml->text_buffer; | |
| 2548 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "BOLD"); | |
| 2549 imhtml->edit.bold = span; | |
| 2550 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2551 } else { | |
| 8428 | 2552 GtkTextIter start; |
| 8061 | 2553 span = imhtml->edit.bold; |
| 2554 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 8428 | 2555 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); |
| 2556 if (gtk_text_iter_equal(&start, &iter)) { /* Format turned off before any text was entered, so remove the tag */ | |
| 2557 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
| 2558 if (span->start_tag) | |
| 2559 g_free(span->start_tag); | |
| 2560 if (span->end_tag) | |
| 2561 g_free(span->end_tag); | |
| 2562 g_free(span); | |
| 2563 } | |
| 8061 | 2564 imhtml->edit.bold = NULL; |
| 2565 } | |
| 2566 return imhtml->edit.bold != NULL; | |
| 2567 } | |
| 2568 | |
| 2569 gboolean gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) | |
| 2570 { | |
| 2571 GtkIMHtmlFormatSpan *span; | |
| 2572 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2573 GtkTextIter iter; | |
| 2574 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2575 if (!imhtml->edit.italic) { | |
| 2576 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
| 2577 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2578 span->start_tag = g_strdup("<i>"); | |
| 2579 span->end = NULL; | |
| 2580 span->end_tag = g_strdup("</i>"); | |
| 2581 span->buffer = imhtml->text_buffer; | |
| 2582 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "ITALIC"); | |
| 2583 imhtml->edit.italic = span; | |
| 2584 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2585 } else { | |
| 8428 | 2586 GtkTextIter start; |
| 8061 | 2587 span = imhtml->edit.italic; |
| 2588 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 8428 | 2589 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); |
| 2590 if (gtk_text_iter_equal(&start, &iter)) { /* Format turned off before any text was entered, so remove the tag */ | |
| 2591 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
| 2592 if (span->start_tag) | |
| 2593 g_free(span->start_tag); | |
| 2594 if (span->end_tag) | |
| 2595 g_free(span->end_tag); | |
| 2596 g_free(span); | |
| 2597 } | |
| 8061 | 2598 imhtml->edit.italic = NULL; |
| 2599 } | |
| 2600 return imhtml->edit.italic != NULL; | |
| 2601 } | |
| 2602 | |
| 2603 gboolean gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) | |
| 2604 { | |
| 2605 GtkIMHtmlFormatSpan *span; | |
| 2606 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2607 GtkTextIter iter; | |
| 2608 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2609 if (!imhtml->edit.underline) { | |
| 2610 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
| 2611 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2612 span->start_tag = g_strdup("<u>"); | |
| 2613 span->end = NULL; | |
| 2614 span->end_tag = g_strdup("</u>"); | |
| 2615 span->buffer = imhtml->text_buffer; | |
| 2616 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "UNDERLINE"); | |
| 2617 imhtml->edit.underline = span; | |
| 2618 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2619 } else { | |
| 8428 | 2620 GtkTextIter start; |
| 8061 | 2621 span = imhtml->edit.underline; |
| 2622 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 8428 | 2623 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); |
| 2624 if (gtk_text_iter_equal(&start, &iter)) { /* Format turned off before any text was entered, so remove the tag */ | |
| 2625 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
| 2626 if (span->start_tag) | |
| 2627 g_free(span->start_tag); | |
| 2628 if (span->end_tag) | |
| 2629 g_free(span->end_tag); | |
| 2630 g_free(span); | |
| 2631 } | |
| 8061 | 2632 imhtml->edit.underline = NULL; |
| 2633 } | |
| 2634 return imhtml->edit.underline != NULL; | |
| 2635 } | |
| 2636 | |
| 2637 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) | |
| 2638 { | |
| 2639 GtkIMHtmlFormatSpan *span; | |
| 2640 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2641 GtkTextIter iter; | |
| 2642 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2643 | |
| 2644 imhtml->edit.fontsize = size; | |
| 2645 | |
| 2646 if (imhtml->edit.sizespan) { | |
| 2647 GtkTextIter iter2; | |
| 2648 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | |
| 2649 if (gtk_text_iter_equal(&iter2, &iter)) | |
| 2650 return; | |
| 2651 span = imhtml->edit.sizespan; | |
| 2652 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2653 } | |
| 2654 if (size != -1) { | |
| 8250 | 2655 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); |
| 8061 | 2656 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); |
| 2657 span->end = NULL; | |
| 2658 span->buffer = imhtml->text_buffer; | |
| 2659 span->tag = NULL; | |
| 2660 imhtml->edit.sizespan = span; | |
| 2661 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2662 } | |
| 2663 } | |
| 2664 | |
| 2665 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) | |
| 2666 { | |
| 2667 GtkIMHtmlFormatSpan *span; | |
| 2668 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2669 GtkTextIter iter; | |
| 2670 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2671 if (imhtml->edit.fontsize == 1) | |
| 2672 return; | |
| 2673 | |
| 2674 imhtml->edit.fontsize--; | |
| 2675 | |
| 2676 if (imhtml->edit.sizespan) { | |
| 2677 GtkTextIter iter2; | |
| 2678 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | |
| 2679 if (gtk_text_iter_equal(&iter2, &iter)) | |
| 2680 return; | |
| 2681 span = imhtml->edit.sizespan; | |
| 2682 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2683 } | |
| 2684 | |
| 8250 | 2685 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); |
| 8061 | 2686 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); |
| 2687 span->end = NULL; | |
| 2688 span->buffer = imhtml->text_buffer; | |
| 2689 span->tag = NULL; | |
| 2690 imhtml->edit.sizespan = span; | |
| 2691 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2692 } | |
| 2693 | |
| 2694 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) | |
| 2695 { | |
| 2696 GtkIMHtmlFormatSpan *span; | |
| 2697 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2698 GtkTextIter iter; | |
| 2699 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2700 if (imhtml->edit.fontsize == MAX_FONT_SIZE) | |
| 2701 return; | |
| 2702 | |
| 2703 imhtml->edit.fontsize++; | |
| 2704 if (imhtml->edit.sizespan) { | |
| 2705 GtkTextIter iter2; | |
| 2706 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | |
| 2707 if (gtk_text_iter_equal(&iter2, &iter)) | |
| 2708 return; | |
| 2709 span = imhtml->edit.sizespan; | |
| 2710 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2711 } | |
| 2712 | |
| 8250 | 2713 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); |
| 8061 | 2714 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); |
| 2715 span->end = NULL; | |
| 2716 span->tag = NULL; | |
| 2717 span->buffer = imhtml->text_buffer; | |
| 2718 imhtml->edit.sizespan = span; | |
| 2719 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2720 } | |
| 2721 | |
| 2722 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) | |
| 2723 { | |
| 2724 GtkIMHtmlFormatSpan *span; | |
| 2725 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2726 GtkTextIter iter; | |
| 2727 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 8429 | 2728 if (color) { |
| 8061 | 2729 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); |
| 2730 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2731 span->start_tag = g_strdup_printf("<font color=\"%s\">", color); | |
| 2732 span->end = NULL; | |
| 2733 span->end_tag = g_strdup("</font>"); | |
| 2734 span->buffer = imhtml->text_buffer; | |
| 2735 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", color, NULL); | |
| 2736 imhtml->edit.forecolor = span; | |
| 2737 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2738 } else { | |
| 2739 span = imhtml->edit.forecolor; | |
| 2740 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2741 imhtml->edit.forecolor = NULL; | |
| 2742 } | |
| 2743 | |
| 2744 | |
| 2745 return imhtml->edit.forecolor != NULL; | |
| 2746 } | |
| 2747 | |
| 2748 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
| 2749 { | |
| 2750 GtkIMHtmlFormatSpan *span; | |
| 2751 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2752 GtkTextIter iter; | |
| 2753 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 8429 | 2754 if (color) { |
| 8061 | 2755 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); |
| 2756 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2757 span->start_tag = g_strdup_printf("<font back=\"%s\">", color); | |
| 2758 span->end = NULL; | |
| 2759 span->end_tag = g_strdup("</font>"); | |
| 2760 span->buffer = imhtml->text_buffer; | |
| 2761 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", color, NULL); | |
| 2762 imhtml->edit.backcolor = span; | |
| 2763 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2764 } else { | |
| 2765 span = imhtml->edit.backcolor; | |
| 2766 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2767 imhtml->edit.backcolor = NULL; | |
| 2768 } | |
| 2769 return imhtml->edit.backcolor != NULL; | |
| 2770 } | |
| 2771 | |
| 2772 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
| 2773 { | |
| 2774 GtkIMHtmlFormatSpan *span; | |
| 2775 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2776 GtkTextIter iter; | |
| 2777 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 8429 | 2778 if (face) { |
| 8061 | 2779 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); |
| 2780 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2781 span->start_tag = g_strdup_printf("<font face=\"%s\">", face); | |
| 2782 span->end = NULL; | |
| 2783 span->end_tag = g_strdup("</font>"); | |
| 2784 span->buffer = imhtml->text_buffer; | |
| 2785 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "family", face, NULL); | |
| 2786 imhtml->edit.fontface = span; | |
| 2787 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2788 } else { | |
| 2789 span = imhtml->edit.fontface; | |
| 2790 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2791 imhtml->edit.fontface = NULL; | |
| 2792 } | |
| 2793 return imhtml->edit.fontface != NULL; | |
| 2794 } | |
| 2795 | |
| 2796 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, const char *url, const char *text) | |
| 2797 { | |
| 2798 GtkIMHtmlFormatSpan *span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
| 2799 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2800 GtkTextIter iter; | |
| 2801 GtkTextTag *tag, *linktag; | |
| 2802 | |
| 2803 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); | |
| 2804 g_object_set_data(G_OBJECT(tag), "link_url", g_strdup(url)); | |
| 2805 | |
| 2806 linktag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "LINK"); | |
| 2807 | |
| 2808 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
| 2809 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2810 span->buffer = imhtml->text_buffer; | |
| 2811 span->start_tag = g_strdup_printf("<a href=\"%s\">", url); | |
| 2812 span->end_tag = g_strdup("</a>"); | |
| 2813 g_signal_connect(G_OBJECT(tag), "event", G_CALLBACK(tag_event), g_strdup(url)); | |
| 2814 | |
| 2815 gtk_text_buffer_insert_with_tags(imhtml->text_buffer, &iter, text, strlen(text), linktag, tag, NULL); | |
| 2816 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
| 2817 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
| 2818 } | |
| 2819 | |
| 2820 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
| 2821 { | |
| 2822 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
| 2823 GtkTextIter iter; | |
| 2824 GdkPixbuf *pixbuf = NULL; | |
| 2825 GdkPixbufAnimation *annipixbuf = NULL; | |
| 2826 GtkWidget *icon = NULL; | |
| 2827 GtkTextChildAnchor *anchor; | |
| 2828 | |
| 2829 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
| 2830 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); | |
| 2831 g_object_set_data(G_OBJECT(anchor), "text_tag", g_strdup(smiley)); | |
| 2832 | |
| 2833 annipixbuf = gtk_smiley_tree_image(imhtml, sml, smiley); | |
| 2834 if(annipixbuf) { | |
| 2835 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
| 2836 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); | |
| 2837 if(pixbuf) | |
| 2838 icon = gtk_image_new_from_pixbuf(pixbuf); | |
| 2839 } else { | |
| 2840 icon = gtk_image_new_from_animation(annipixbuf); | |
| 2841 } | |
| 2842 } | |
| 2843 | |
| 2844 if (icon) { | |
| 2845 gtk_widget_show(icon); | |
| 2846 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | |
| 2847 } | |
| 2848 } | |
| 2849 | |
| 2850 int span_compare_begin(const GtkIMHtmlFormatSpan *a, const GtkIMHtmlFormatSpan *b, GtkTextBuffer *buffer) | |
| 2851 { | |
| 2852 GtkTextIter ia, ib; | |
| 2853 gtk_text_buffer_get_iter_at_mark(buffer, &ia, a->start); | |
| 2854 gtk_text_buffer_get_iter_at_mark(buffer, &ib, b->start); | |
| 2855 return gtk_text_iter_compare(&ia, &ib); | |
| 2856 } | |
| 2857 | |
| 2858 int span_compare_end(GtkIMHtmlFormatSpan *a, GtkIMHtmlFormatSpan *b) | |
| 2859 { | |
| 2860 GtkTextIter ia, ib; | |
| 2861 gtk_text_buffer_get_iter_at_mark(a->buffer, &ia, a->start); | |
| 2862 gtk_text_buffer_get_iter_at_mark(b->buffer, &ib, b->start); | |
| 2863 /* The -1 here makes it so that if I have two spans that close at the same point, the | |
| 2864 * span added second will be closed first, as in <b><i>Hello</i></b>. Without this, | |
| 2865 * it would be <b><i>Hello</b></i> */ | |
| 2866 return gtk_text_iter_compare(&ia, &ib) - 1; | |
| 2867 } | |
| 2868 | |
| 2869 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | |
| 2870 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | |
| 2871 * check the list of formatted strings, sorted by the position of the starting tags and apply them as | |
| 2872 * needed. After applying the start tags, add the end tags to the "closers" list, which is sorted by | |
| 2873 * location of ending tags. These get applied in a similar fashion. Finally, replace <, >, &, and " | |
| 2874 * with their HTML equivilent. */ | |
| 2875 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) | |
| 2876 { | |
| 2877 gunichar c; | |
| 2878 GtkIMHtmlFormatSpan *sspan = NULL, *espan = NULL; | |
| 2879 GtkTextIter iter, siter, eiter; | |
| 2880 GList *starters = imhtml->format_spans; | |
| 2881 GList *closers = NULL; | |
| 2882 GString *str = g_string_new(""); | |
| 2883 g_list_sort_with_data(starters, (GCompareDataFunc)span_compare_begin, imhtml->text_buffer); | |
| 2884 | |
| 2885 gtk_text_iter_order(start, end); | |
| 2886 iter = *start; | |
| 2887 | |
| 2888 | |
| 2889 /* Initialize these to the end iter */ | |
| 2890 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
| 2891 eiter = siter; | |
| 2892 | |
| 8429 | 2893 if (starters) { |
| 8061 | 2894 while (starters) { |
| 2895 GtkTextIter tagend; | |
| 2896 sspan = (GtkIMHtmlFormatSpan*)starters->data; | |
| 2897 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | |
| 2898 if (gtk_text_iter_compare(&siter, start) > 0) | |
| 2899 break; | |
| 2900 if (sspan->end) | |
| 2901 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &tagend, sspan->end); | |
| 2902 if (sspan->end == NULL || gtk_text_iter_compare(&tagend, start) > 0) { | |
| 2903 str = g_string_append(str, sspan->start_tag); | |
| 2904 closers = g_list_insert_sorted(closers, sspan, (GCompareFunc)span_compare_end); | |
| 2905 espan = (GtkIMHtmlFormatSpan*)closers->data; | |
| 8365 | 2906 /* |
| 2907 * When sending an IM, the following line causes the following warning: | |
| 2908 * Gtk: file gtktextbuffer.c: line 1794 | |
| 2909 * (gtk_text_buffer_get_iter_at_mark): assertion `GTK_IS_TEXT_MARK (mark)' failed | |
| 2910 * | |
| 2911 * The callback path thingy to get here is: | |
| 2912 * gtkconv.c, send(), "buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry));" | |
| 2913 * gtkimhtml.c, gtk_imthml_get_markup(), "return gtk_imhtml_get_markup_range(imhtml, &start, &end);" | |
| 2914 * | |
| 2915 * I don't really know anything about gtkimhtml, but it almost seems like | |
| 2916 * the line above this comments expects to find a closing html tag, but | |
| 2917 * can't, for some reason. The warning depends on how much HTML I send | |
| 2918 * in my message, kind of. | |
| 2919 */ | |
| 8061 | 2920 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &eiter, espan->end); |
| 2921 } | |
| 2922 sspan = (GtkIMHtmlFormatSpan*)starters->data; | |
| 2923 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | |
| 2924 starters = starters->next; | |
| 2925 } | |
| 2926 if (!starters) { | |
| 2927 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
| 2928 sspan = NULL; | |
| 2929 } | |
| 2930 } | |
| 2931 | |
| 2932 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
| 2933 if (c == 0xFFFC) { | |
| 2934 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | |
| 2935 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); | |
| 2936 str = g_string_append(str, text); | |
| 2937 } else { | |
| 2938 while (gtk_text_iter_equal(&eiter, &iter)) { | |
| 2939 /* This is where we shall insert the ending tag of | |
| 2940 * this format span */ | |
| 2941 str = g_string_append(str, espan->end_tag); | |
| 2942 closers = g_list_remove(closers, espan); | |
| 2943 if (!closers) { | |
| 2944 espan = NULL; | |
| 2945 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &eiter); | |
| 2946 } else { | |
| 2947 espan = (GtkIMHtmlFormatSpan*)closers->data; | |
| 8429 | 2948 if (espan->end) |
| 2949 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &eiter, espan->end); | |
| 2950 else | |
| 2951 gtk_text_iter_forward_to_end(&eiter); | |
| 8061 | 2952 } |
| 2953 } | |
| 2954 while (gtk_text_iter_equal(&siter, &iter)) { | |
| 2955 /* This is where we shall insert the starting tag of | |
| 2956 * this format span */ | |
| 2957 str = g_string_append(str, sspan->start_tag); | |
| 2958 if (sspan->end) { | |
| 2959 closers = g_list_insert_sorted(closers, sspan, (GCompareFunc)span_compare_end); | |
| 2960 espan = (GtkIMHtmlFormatSpan*)closers->data; | |
| 2961 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &eiter, espan->end); | |
| 2962 | |
| 2963 } | |
| 2964 starters = starters->next; | |
| 2965 if (starters) { | |
| 2966 sspan = (GtkIMHtmlFormatSpan*)starters->data; | |
| 2967 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | |
| 2968 } else { | |
| 2969 sspan = NULL; | |
| 2970 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
| 2971 } | |
| 2972 | |
| 2973 } | |
| 2974 | |
| 2975 if (c == '<') | |
| 2976 str = g_string_append(str, "<"); | |
| 2977 else if (c == '>') | |
| 2978 str = g_string_append(str, ">"); | |
| 2979 else if (c == '&') | |
| 2980 str = g_string_append(str, "&"); | |
| 2981 else if (c == '"') | |
| 2982 str = g_string_append(str, """); | |
| 2983 else if (c == '\n') | |
| 2984 str = g_string_append(str, "<br>"); | |
| 2985 else | |
| 2986 str = g_string_append_unichar(str, c); | |
| 2987 } | |
| 2988 gtk_text_iter_forward_char(&iter); | |
| 2989 } | |
| 2990 while (closers) { | |
| 2991 GtkIMHtmlFormatSpan *span = (GtkIMHtmlFormatSpan*)closers->data; | |
| 2992 str = g_string_append(str, span->end_tag); | |
| 2993 closers = g_list_remove(closers, span); | |
| 2994 | |
| 2995 } | |
| 8428 | 2996 printf("gotten: %s\n", str->str); |
| 8061 | 2997 return g_string_free(str, FALSE); |
| 2998 } | |
| 2999 | |
| 3000 void gtk_imhtml_close_tags(GtkIMHtml *imhtml) | |
| 3001 { | |
| 3002 | |
| 3003 if (imhtml->edit.bold) | |
| 3004 gtk_imhtml_toggle_bold(imhtml); | |
| 3005 | |
| 3006 if (imhtml->edit.italic) | |
| 3007 gtk_imhtml_toggle_italic(imhtml); | |
| 3008 | |
| 3009 if (imhtml->edit.underline) | |
| 3010 gtk_imhtml_toggle_underline(imhtml); | |
| 3011 | |
| 3012 if (imhtml->edit.forecolor) | |
| 3013 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
| 3014 | |
| 3015 if (imhtml->edit.backcolor) | |
| 3016 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
| 3017 | |
| 3018 if (imhtml->edit.fontface) | |
| 3019 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
| 3020 | |
| 3021 if (imhtml->edit.sizespan) | |
| 3022 gtk_imhtml_font_set_size(imhtml, -1); | |
| 3023 | |
| 3024 } | |
| 3025 | |
| 3026 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
| 3027 { | |
| 3028 GtkTextIter start, end; | |
| 3029 | |
| 3030 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
| 3031 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
| 3032 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
| 3033 } | |
| 3034 | |
| 3035 char *gtk_imhtml_get_text(GtkIMHtml *imhtml) | |
| 3036 { | |
| 3037 GtkTextIter start_iter, end_iter; | |
| 3038 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start_iter); | |
| 3039 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end_iter); | |
| 3040 return gtk_text_buffer_get_text(imhtml->text_buffer, &start_iter, &end_iter, FALSE); | |
| 3041 | |
| 3042 } |
