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