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