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