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