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