Mercurial > pidgin
annotate src/gtkimhtml.c @ 6982:083d1e4a9c78
[gaim-migrate @ 7538]
This is Mr. Holland's Opus. And by Mr. Holland I mean Robot101. He
rewrote the coreish IM image support so that the binary data gets
ripped out in the prpl and put in an imgstore instead of just being
passed in the same huge as char string as the actual message. This
is good because it's prpl agnostic, or something. It also means
we don't have a silly length of "-1" with pretty much every send or
receive IM function.
It should be crash free, bug free, and memleak free, but additional
testing is always a good thing.
If you like good stuff then you'll love this patch. But don't take
my word for it--ba dun dunt!
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sat, 27 Sep 2003 19:17:21 +0000 |
parents | 4f8258b2bb8d |
children | 48cc5d5d5a6c |
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" |
26 #include <gtk/gtk.h> | |
4895 | 27 #include <glib/gerror.h> |
4046 | 28 #include <gdk/gdkkeysyms.h> |
1428 | 29 #include <string.h> |
30 #include <ctype.h> | |
31 #include <stdio.h> | |
4629 | 32 #include <stdlib.h> |
1428 | 33 #include <math.h> |
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
34 #ifdef HAVE_LANGINFO_CODESET |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
35 #include <langinfo.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
36 #include <locale.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
37 #endif |
1428 | 38 |
4417 | 39 #ifdef ENABLE_NLS |
40 # include <libintl.h> | |
41 # define _(x) gettext(x) | |
42 # ifdef gettext_noop | |
43 # define N_(String) gettext_noop (String) | |
44 # else | |
45 # define N_(String) (String) | |
46 # endif | |
47 #else | |
48 # define N_(String) (String) | |
49 # define _(x) (x) | |
50 #endif | |
51 | |
4735 | 52 #include <pango/pango-font.h> |
53 | |
5105 | 54 /* GTK+ < 2.2.2 hack, see ui.h for details. */ |
55 #ifndef GTK_WRAP_WORD_CHAR | |
56 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD | |
57 #endif | |
58 | |
4735 | 59 #define TOOLTIP_TIMEOUT 500 |
60 | |
3922 | 61 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a |
62 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | |
63 #define MAX_FONT_SIZE 7 | |
5367 | 64 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
3928 | 65 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
|
66 |
4032 | 67 static GtkSmileyTree* |
68 gtk_smiley_tree_new () | |
69 { | |
70 return g_new0 (GtkSmileyTree, 1); | |
71 } | |
72 | |
73 static void | |
74 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
4263 | 75 GtkIMHtmlSmiley *smiley) |
4032 | 76 { |
77 GtkSmileyTree *t = tree; | |
4263 | 78 const gchar *x = smiley->smile; |
4032 | 79 |
80 if (!strlen (x)) | |
81 return; | |
82 | |
83 while (*x) { | |
84 gchar *pos; | |
85 gint index; | |
86 | |
87 if (!t->values) | |
88 t->values = g_string_new (""); | |
89 | |
90 pos = strchr (t->values->str, *x); | |
91 if (!pos) { | |
92 t->values = g_string_append_c (t->values, *x); | |
93 index = t->values->len - 1; | |
94 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
95 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
96 } else | |
6478
338147ea6896
[gaim-migrate @ 6991]
Christian Hammond <chipx86@chipx86.com>
parents:
6162
diff
changeset
|
97 index = (int) pos - GPOINTER_TO_INT(t->values->str); |
4032 | 98 |
99 t = t->children [index]; | |
100 | |
101 x++; | |
102 } | |
103 | |
4263 | 104 t->image = smiley; |
4032 | 105 } |
4041 | 106 |
4263 | 107 |
4264 | 108 void gtk_smiley_tree_destroy (GtkSmileyTree *tree) |
4032 | 109 { |
110 GSList *list = g_slist_append (NULL, tree); | |
111 | |
112 while (list) { | |
113 GtkSmileyTree *t = list->data; | |
114 gint i; | |
115 list = g_slist_remove(list, t); | |
116 if (t->values) { | |
117 for (i = 0; i < t->values->len; i++) | |
118 list = g_slist_append (list, t->children [i]); | |
119 g_string_free (t->values, TRUE); | |
120 g_free (t->children); | |
121 } | |
122 g_free (t); | |
123 } | |
124 } | |
125 | |
5967 | 126 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
127 { | |
128 GdkRectangle rect; | |
129 | |
130 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); | |
131 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ | |
132 GList *iter = GTK_IMHTML(widget)->scalables; | |
133 | |
134 while(iter){ | |
135 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data); | |
136 scale->scale(scale, rect.width, rect.height); | |
137 | |
138 iter = iter->next; | |
139 } | |
140 } | |
141 | |
142 widget->old_rect = rect; | |
143 return FALSE; | |
144 } | |
145 | |
146 static gint | |
147 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
148 { | |
149 PangoLayout *layout; | |
150 | |
151 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
152 | |
153 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
154 | |
155 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, | |
156 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, | |
157 "tooltip", 0, 0, -1, -1); | |
158 | |
159 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
160 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
161 | |
162 g_object_unref(layout); | |
163 return FALSE; | |
164 } | |
165 | |
166 static gint | |
167 gtk_imhtml_tip (gpointer data) | |
168 { | |
169 GtkIMHtml *imhtml = data; | |
170 PangoFontMetrics *font; | |
171 PangoLayout *layout; | |
172 | |
173 gint gap, x, y, h, w, scr_w, baseline_skip; | |
174 | |
175 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
176 | |
177 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
178 imhtml->tip_timer = 0; | |
179 return FALSE; | |
180 } | |
181 | |
182 if (imhtml->tip_window){ | |
183 gtk_widget_destroy (imhtml->tip_window); | |
184 imhtml->tip_window = NULL; | |
185 } | |
186 | |
187 imhtml->tip_timer = 0; | |
188 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
189 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
190 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
191 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
192 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
193 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
194 | |
195 gtk_widget_ensure_style (imhtml->tip_window); | |
196 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
197 font = pango_font_get_metrics(pango_context_load_font(pango_layout_get_context(layout), | |
198 imhtml->tip_window->style->font_desc), | |
199 NULL); | |
200 | |
201 | |
202 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
203 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + | |
204 pango_font_metrics_get_descent(font))/ 4); | |
205 | |
206 if (gap < 2) | |
207 gap = 2; | |
208 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
209 pango_font_metrics_get_descent(font)); | |
210 w = 8 + scr_w; | |
211 h = 8 + baseline_skip; | |
212 | |
213 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
214 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
215 y += GTK_WIDGET(imhtml)->allocation.y; | |
216 | |
217 scr_w = gdk_screen_width(); | |
218 | |
219 x -= ((w >> 1) + 4); | |
220 | |
221 if ((x + w) > scr_w) | |
222 x -= (x + w) - scr_w; | |
223 else if (x < 0) | |
224 x = 0; | |
225 | |
226 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
227 pango_font_metrics_get_descent(font)); | |
228 | |
229 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
230 gtk_widget_show (imhtml->tip_window); | |
231 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
232 | |
233 pango_font_metrics_unref(font); | |
234 g_object_unref(layout); | |
235 | |
236 return FALSE; | |
237 } | |
238 | |
239 gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) | |
240 { | |
241 GtkTextIter iter; | |
242 GdkWindow *win = event->window; | |
243 int x, y; | |
244 char *tip = NULL; | |
245 GSList *tags = NULL, *templist = NULL; | |
246 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); | |
247 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, | |
248 event->x, event->y, &x, &y); | |
249 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
250 tags = gtk_text_iter_get_tags(&iter); | |
251 | |
252 templist = tags; | |
253 while (templist) { | |
254 GtkTextTag *tag = templist->data; | |
255 tip = g_object_get_data(G_OBJECT(tag), "link_url"); | |
256 if (tip) | |
257 break; | |
258 templist = templist->next; | |
259 } | |
260 | |
261 if (GTK_IMHTML(imhtml)->tip) { | |
262 if ((tip == GTK_IMHTML(imhtml)->tip)) { | |
263 return FALSE; | |
264 } | |
265 /* We've left the cell. Remove the timeout and create a new one below */ | |
266 if (GTK_IMHTML(imhtml)->tip_window) { | |
267 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
268 GTK_IMHTML(imhtml)->tip_window = NULL; | |
269 } | |
270 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->arrow_cursor); | |
271 if (GTK_IMHTML(imhtml)->tip_timer) | |
272 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
273 GTK_IMHTML(imhtml)->tip_timer = 0; | |
274 } | |
275 | |
276 if(tip){ | |
277 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); | |
278 GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, | |
279 gtk_imhtml_tip, imhtml); | |
280 } | |
281 | |
282 GTK_IMHTML(imhtml)->tip = tip; | |
283 g_slist_free(tags); | |
284 return FALSE; | |
285 } | |
286 | |
287 gboolean gtk_leave_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) | |
288 { | |
289 /* when leaving the widget, clear any current & pending tooltips and restore the cursor */ | |
290 if (GTK_IMHTML(imhtml)->tip_window) { | |
291 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
292 GTK_IMHTML(imhtml)->tip_window = NULL; | |
293 } | |
294 if (GTK_IMHTML(imhtml)->tip_timer) { | |
295 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
296 GTK_IMHTML(imhtml)->tip_timer = 0; | |
297 } | |
298 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
299 | |
300 /* propogate the event normally */ | |
301 return FALSE; | |
302 } | |
303 | |
6066 | 304 /* |
305 * XXX - This should be removed eventually. | |
306 * | |
307 * This function exists to work around a gross bug in GtkTextView. | |
308 * Basically, we short circuit ctrl+a and ctrl+end because they make | |
309 * el program go boom. | |
310 * | |
311 * It's supposed to be fixed in gtk2.2. You can view the bug report at | |
312 * http://bugzilla.gnome.org/show_bug.cgi?id=107939 | |
313 */ | |
314 gboolean gtk_key_pressed_cb(GtkWidget *imhtml, GdkEventKey *event, gpointer data) | |
315 { | |
316 if (event->state & GDK_CONTROL_MASK) | |
317 switch (event->keyval) { | |
318 case 'a': | |
319 return TRUE; | |
320 break; | |
321 | |
322 case GDK_Home: | |
323 return TRUE; | |
324 break; | |
325 | |
326 case GDK_End: | |
327 return TRUE; | |
328 break; | |
329 } | |
330 | |
331 return FALSE; | |
332 } | |
333 | |
5967 | 334 |
4263 | 335 |
4032 | 336 static GtkTextViewClass *parent_class = NULL; |
337 | |
3922 | 338 /* GtkIMHtml has one signal--URL_CLICKED */ |
1428 | 339 enum { |
340 URL_CLICKED, | |
341 LAST_SIGNAL | |
342 }; | |
343 static guint signals [LAST_SIGNAL] = { 0 }; | |
344 | |
4032 | 345 static void |
346 gtk_imhtml_finalize (GObject *object) | |
347 { | |
348 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
4895 | 349 GList *scalables; |
350 | |
4138 | 351 g_hash_table_destroy(imhtml->smiley_data); |
4032 | 352 gtk_smiley_tree_destroy(imhtml->default_smilies); |
4138 | 353 gdk_cursor_unref(imhtml->hand_cursor); |
354 gdk_cursor_unref(imhtml->arrow_cursor); | |
4735 | 355 if(imhtml->tip_window){ |
356 gtk_widget_destroy(imhtml->tip_window); | |
357 } | |
358 if(imhtml->tip_timer) | |
359 gtk_timeout_remove(imhtml->tip_timer); | |
360 | |
4895 | 361 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
362 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
363 scale->free(scale); | |
364 } | |
365 | |
366 g_list_free(imhtml->scalables); | |
4032 | 367 G_OBJECT_CLASS(parent_class)->finalize (object); |
368 } | |
1428 | 369 |
3922 | 370 /* Boring GTK stuff */ |
371 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) | |
1428 | 372 { |
3922 | 373 GtkObjectClass *object_class; |
4032 | 374 GObjectClass *gobject_class; |
3922 | 375 object_class = (GtkObjectClass*) class; |
4032 | 376 gobject_class = (GObjectClass*) class; |
377 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); | |
4417 | 378 signals[URL_CLICKED] = g_signal_new("url_clicked", |
379 G_TYPE_FROM_CLASS(gobject_class), | |
380 G_SIGNAL_RUN_FIRST, | |
381 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
382 NULL, | |
383 0, | |
384 g_cclosure_marshal_VOID__POINTER, | |
385 G_TYPE_NONE, 1, | |
386 G_TYPE_POINTER); | |
4032 | 387 gobject_class->finalize = gtk_imhtml_finalize; |
1428 | 388 } |
389 | |
3922 | 390 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 391 { |
3922 | 392 GtkTextIter iter; |
393 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
394 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
395 imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); | |
396 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
5105 | 397 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 398 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), FALSE); |
399 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); | |
400 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), FALSE); | |
401 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ | |
3465 | 402 |
3922 | 403 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
404 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ | |
405 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); | |
406 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
407 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
408 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
409 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
410 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
411 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
3465 | 412 |
3922 | 413 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
414 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
415 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
2993 | 416 |
4253 | 417 imhtml->show_smileys = TRUE; |
6124 | 418 imhtml->show_comments = TRUE; |
4253 | 419 |
4892 | 420 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 421 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 422 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 423 |
4944 | 424 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 425 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 426 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
6066 | 427 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
4944 | 428 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
4735 | 429 |
430 imhtml->tip = NULL; | |
431 imhtml->tip_timer = 0; | |
432 imhtml->tip_window = NULL; | |
4895 | 433 |
434 imhtml->scalables = NULL; | |
2993 | 435 } |
436 | |
3922 | 437 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 438 { |
4635 | 439 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 440 } |
441 | |
4635 | 442 GType gtk_imhtml_get_type() |
1428 | 443 { |
4635 | 444 static GType imhtml_type = 0; |
1428 | 445 |
446 if (!imhtml_type) { | |
4635 | 447 static const GTypeInfo imhtml_info = { |
448 sizeof(GtkIMHtmlClass), | |
449 NULL, | |
450 NULL, | |
451 (GClassInitFunc) gtk_imhtml_class_init, | |
452 NULL, | |
453 NULL, | |
1428 | 454 sizeof (GtkIMHtml), |
4635 | 455 0, |
456 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 457 }; |
4635 | 458 |
459 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
460 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 461 } |
462 | |
463 return imhtml_type; | |
464 } | |
465 | |
4417 | 466 struct url_data { |
467 GObject *object; | |
468 gchar *url; | |
469 }; | |
470 | |
471 static void url_open(GtkWidget *w, struct url_data *data) { | |
472 if(!data) return; | |
473 | |
474 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); | |
475 | |
476 g_object_unref(data->object); | |
477 g_free(data->url); | |
478 g_free(data); | |
479 } | |
5582 | 480 |
4417 | 481 static void url_copy(GtkWidget *w, gchar *url) { |
482 GtkClipboard *clipboard; | |
483 | |
5293
ead927e2543f
[gaim-migrate @ 5665]
Christian Hammond <chipx86@chipx86.com>
parents:
5282
diff
changeset
|
484 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
4417 | 485 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 486 |
487 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | |
488 gtk_clipboard_set_text(clipboard, url, -1); | |
4417 | 489 } |
490 | |
491 /* The callback for an event on a link tag. */ | |
5091 | 492 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, char *url) { |
4417 | 493 GdkEventButton *event_button = (GdkEventButton *) event; |
494 | |
3922 | 495 if (event->type == GDK_BUTTON_RELEASE) { |
4417 | 496 if (event_button->button == 1) { |
497 GtkTextIter start, end; | |
498 /* we shouldn't open a URL if the user has selected something: */ | |
499 gtk_text_buffer_get_selection_bounds( | |
500 gtk_text_iter_get_buffer(arg2), &start, &end); | |
501 if(gtk_text_iter_get_offset(&start) != | |
502 gtk_text_iter_get_offset(&end)) | |
503 return FALSE; | |
504 | |
505 /* A link was clicked--we emit the "url_clicked" signal | |
506 * with the URL as the argument */ | |
5091 | 507 g_signal_emit(imhtml, signals[URL_CLICKED], 0, url); |
4417 | 508 return FALSE; |
509 } else if(event_button->button == 3) { | |
4745 | 510 GtkWidget *img, *item, *menu; |
4417 | 511 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 512 tempdata->object = g_object_ref(imhtml); |
4417 | 513 tempdata->url = g_strdup(url); |
4745 | 514 |
5091 | 515 /* Don't want the tooltip around if user right-clicked on link */ |
516 if (GTK_IMHTML(imhtml)->tip_window) { | |
517 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
518 GTK_IMHTML(imhtml)->tip_window = NULL; | |
519 } | |
520 if (GTK_IMHTML(imhtml)->tip_timer) { | |
521 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
522 GTK_IMHTML(imhtml)->tip_timer = 0; | |
523 } | |
524 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 525 menu = gtk_menu_new(); |
4745 | 526 |
4417 | 527 /* buttons and such */ |
528 img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); | |
4420 | 529 item = gtk_image_menu_item_new_with_mnemonic(_("_Copy Link Location")); |
4417 | 530 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
531 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_copy), | |
532 url); | |
533 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
534 | |
535 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); | |
4420 | 536 item = gtk_image_menu_item_new_with_mnemonic(_("_Open Link in Browser")); |
4417 | 537 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
538 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_open), | |
539 tempdata); | |
540 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
4756 | 541 |
4417 | 542 gtk_widget_show_all(menu); |
4756 | 543 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
544 event_button->button, event_button->time); | |
4745 | 545 |
4417 | 546 return TRUE; |
547 } | |
1428 | 548 } |
4417 | 549 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
550 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
551 be caught by the regular GtkTextView menu */ | |
552 else | |
553 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 554 } |
555 | |
4298 | 556 /* this isn't used yet |
4032 | 557 static void |
4263 | 558 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
559 GtkIMHtmlSmiley *smiley) | |
4032 | 560 { |
561 GtkSmileyTree *t = tree; | |
4263 | 562 const gchar *x = smiley->smile; |
4032 | 563 gint len = 0; |
564 | |
565 while (*x) { | |
566 gchar *pos; | |
567 | |
568 if (!t->values) | |
569 return; | |
570 | |
571 pos = strchr (t->values->str, *x); | |
572 if (pos) | |
573 t = t->children [(int) pos - (int) t->values->str]; | |
574 else | |
575 return; | |
576 | |
577 x++; len++; | |
578 } | |
579 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
580 if (t->image) { |
4032 | 581 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
582 } |
4032 | 583 } |
4298 | 584 */ |
585 | |
4032 | 586 |
587 static gint | |
588 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
589 const gchar *text) | |
590 { | |
591 GtkSmileyTree *t = tree; | |
592 const gchar *x = text; | |
593 gint len = 0; | |
594 | |
595 while (*x) { | |
596 gchar *pos; | |
597 | |
598 if (!t->values) | |
599 break; | |
600 | |
601 pos = strchr (t->values->str, *x); | |
602 if (pos) | |
6478
338147ea6896
[gaim-migrate @ 6991]
Christian Hammond <chipx86@chipx86.com>
parents:
6162
diff
changeset
|
603 t = t->children [(int) pos - GPOINTER_TO_INT(t->values->str)]; |
4032 | 604 else |
605 break; | |
606 | |
607 x++; len++; | |
608 } | |
609 | |
610 if (t->image) | |
611 return len; | |
612 | |
613 return 0; | |
614 } | |
615 | |
616 void | |
4263 | 617 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
618 gchar *sml, | |
619 GtkIMHtmlSmiley *smiley) | |
4032 | 620 { |
621 GtkSmileyTree *tree; | |
622 g_return_if_fail (imhtml != NULL); | |
623 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
4263 | 624 |
4032 | 625 if (sml == NULL) |
626 tree = imhtml->default_smilies; | |
627 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
628 } else { | |
629 tree = gtk_smiley_tree_new(); | |
4892 | 630 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 631 } |
632 | |
4263 | 633 gtk_smiley_tree_insert (tree, smiley); |
4032 | 634 } |
635 | |
636 static gboolean | |
637 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
638 GSList *fonts, | |
639 const gchar *text, | |
640 gint *len) | |
641 { | |
642 GtkSmileyTree *tree; | |
5967 | 643 GtkIMHtmlFontDetail *font; |
4032 | 644 char *sml = NULL; |
645 | |
646 if (fonts) { | |
647 font = fonts->data; | |
648 sml = font->sml; | |
649 } | |
650 | |
651 if (sml == NULL) | |
652 tree = imhtml->default_smilies; | |
653 else { | |
654 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
655 } | |
656 if (tree == NULL) | |
657 return FALSE; | |
658 | |
659 *len = gtk_smiley_tree_lookup (tree, text); | |
660 return (*len > 0); | |
661 } | |
662 | |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
663 GdkPixbufAnimation * |
4032 | 664 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
665 const gchar *sml, | |
666 const gchar *text) | |
667 { | |
668 GtkSmileyTree *t; | |
669 const gchar *x = text; | |
670 if (sml == NULL) | |
671 t = imhtml->default_smilies; | |
672 else | |
673 t = g_hash_table_lookup(imhtml->smiley_data, sml); | |
674 | |
675 | |
676 if (t == NULL) | |
677 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
678 | |
679 while (*x) { | |
680 gchar *pos; | |
681 | |
682 if (!t->values) { | |
683 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
684 } | |
685 | |
686 pos = strchr (t->values->str, *x); | |
687 if (pos) { | |
6478
338147ea6896
[gaim-migrate @ 6991]
Christian Hammond <chipx86@chipx86.com>
parents:
6162
diff
changeset
|
688 t = t->children [(int) pos - GPOINTER_TO_INT(t->values->str)]; |
4032 | 689 } else { |
690 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
691 } | |
692 x++; | |
693 } | |
694 | |
4263 | 695 if (!t->image->icon) |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
696 t->image->icon = gdk_pixbuf_animation_new_from_file(t->image->file, NULL); |
4263 | 697 |
698 return t->image->icon; | |
4032 | 699 } |
4793 | 700 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 701 *tag = g_strndup (string, strlen (x)); \ |
702 *len = strlen (x) + 1; \ | |
703 return TRUE; \ | |
704 } \ | |
705 (*type)++ | |
1428 | 706 |
4793 | 707 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 708 const gchar *c = string + strlen (x " "); \ |
709 gchar e = '"'; \ | |
710 gboolean quote = FALSE; \ | |
711 while (*c) { \ | |
712 if (*c == '"' || *c == '\'') { \ | |
713 if (quote && (*c == e)) \ | |
714 quote = !quote; \ | |
715 else if (!quote) { \ | |
716 quote = !quote; \ | |
717 e = *c; \ | |
718 } \ | |
719 } else if (!quote && (*c == '>')) \ | |
720 break; \ | |
721 c++; \ | |
722 } \ | |
723 if (*c) { \ | |
724 *tag = g_strndup (string, c - string); \ | |
725 *len = c - string + 1; \ | |
726 return TRUE; \ | |
727 } \ | |
728 } \ | |
729 (*type)++ | |
1428 | 730 |
731 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
732 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
733 gtk_imhtml_is_amp_escape (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
734 gchar *replace, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
735 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
736 { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
737 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
738 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
739 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
740 |
4793 | 741 if (!g_ascii_strncasecmp (string, "&", 5)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
742 *replace = '&'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
743 *length = 5; |
4793 | 744 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
745 *replace = '<'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
746 *length = 4; |
4793 | 747 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
748 *replace = '>'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
749 *length = 4; |
4793 | 750 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
751 *replace = ' '; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
752 *length = 6; |
4793 | 753 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
754 *replace = '©'; /* was: '©' */ |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
755 *length = 6; |
4793 | 756 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
757 *replace = '\"'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
758 *length = 6; |
4793 | 759 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
760 *replace = '®'; /* was: '®' */ |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
761 *length = 5; |
5093 | 762 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
763 *replace = '\''; | |
764 *length = 6; | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
765 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
766 guint pound = 0; |
3004 | 767 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
768 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
769 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
770 *replace = (gchar)pound; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
771 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
772 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
773 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
774 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
775 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
776 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
777 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
778 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
779 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
780 |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
781 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
782 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
783 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
784 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
785 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
786 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
787 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
788 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
789 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
790 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
791 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
792 if (!strchr (string, '>')) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
793 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
794 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
795 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
796 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
797 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
798 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
799 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
800 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
801 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
802 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
803 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
804 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
805 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
806 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
807 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
808 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
809 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
810 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
811 VALID_TAG ("SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
812 VALID_TAG ("/SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
813 VALID_TAG ("SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
814 VALID_TAG ("/SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
815 VALID_TAG ("PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
816 VALID_TAG ("/PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
817 VALID_TAG ("TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
818 VALID_TAG ("/TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
819 VALID_TAG ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
820 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
821 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
822 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
823 VALID_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
824 VALID_TAG ("/P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
825 VALID_TAG ("H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
826 VALID_TAG ("/H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
827 VALID_TAG ("HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
828 VALID_TAG ("/HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
829 VALID_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
830 VALID_TAG ("/BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
831 VALID_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
832 VALID_TAG ("HEAD"); |
2993 | 833 VALID_TAG ("/HEAD"); |
834 VALID_TAG ("BINARY"); | |
835 VALID_TAG ("/BINARY"); | |
5093 | 836 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
837 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
838 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
839 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
840 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
841 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
842 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
843 VALID_OPT_TAG ("H3"); |
5093 | 844 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
845 |
5101 | 846 VALID_TAG ("CITE"); |
847 VALID_TAG ("/CITE"); | |
848 VALID_TAG ("EM"); | |
849 VALID_TAG ("/EM"); | |
850 VALID_TAG ("STRONG"); | |
851 VALID_TAG ("/STRONG"); | |
852 | |
5104 | 853 VALID_OPT_TAG ("SPAN"); |
854 VALID_TAG ("/SPAN"); | |
5174 | 855 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
6982 | 856 VALID_TAG ("IMG"); |
5104 | 857 |
4793 | 858 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
859 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
860 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
861 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
862 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
863 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
864 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
865 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
866 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
867 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
868 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
869 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
870 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
871 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
872 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
873 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
874 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
875 gchar *e, *a; |
5177 | 876 gchar *val; |
877 gint len; | |
878 gchar c; | |
879 GString *ret; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
880 |
4793 | 881 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
882 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
883 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
884 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
885 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
886 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
887 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
888 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
889 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
890 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
891 |
4793 | 892 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
893 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
894 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
895 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
896 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
897 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
898 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
899 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
900 while (*e && (*e != *(t - 1))) e++; |
2993 | 901 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
902 return NULL; |
5177 | 903 } else |
904 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
905 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
906 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
907 while (*e && !isspace ((gint) *e)) e++; |
5177 | 908 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
909 } |
5177 | 910 |
911 ret = g_string_new(""); | |
912 e = val; | |
913 while(*e) { | |
914 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
915 ret = g_string_append_c(ret, c); | |
916 e += len; | |
917 } else { | |
918 ret = g_string_append_c(ret, *e); | |
919 e++; | |
920 } | |
921 } | |
922 | |
923 g_free(val); | |
924 val = ret->str; | |
925 g_string_free(ret, FALSE); | |
926 return val; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
927 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
928 |
3922 | 929 |
930 | |
931 #define NEW_TEXT_BIT 0 | |
4343 | 932 #define NEW_COMMENT_BIT 2 |
4895 | 933 #define NEW_SCALABLE_BIT 1 |
3922 | 934 #define NEW_BIT(x) ws [wpos] = '\0'; \ |
935 mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \ | |
936 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \ | |
4895 | 937 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ |
3922 | 938 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \ |
939 gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \ | |
940 if (bold) \ | |
941 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \ | |
4895 | 942 if (italics) \ |
3922 | 943 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \ |
944 if (underline) \ | |
945 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \ | |
946 if (strike) \ | |
947 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \ | |
948 if (sub) \ | |
949 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \ | |
950 if (sup) \ | |
951 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \ | |
952 if (pre) \ | |
953 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &iter); \ | |
954 if (bg) { \ | |
955 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); \ | |
956 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
957 } \ | |
958 if (fonts) { \ | |
5967 | 959 GtkIMHtmlFontDetail *fd = fonts->data; \ |
3922 | 960 if (fd->fore) { \ |
961 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \ | |
962 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
963 } \ | |
964 if (fd->back) { \ | |
965 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); \ | |
966 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
967 } \ | |
968 if (fd->face) { \ | |
6648 | 969 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "family", fd->face, NULL); \ |
3922 | 970 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
971 } \ | |
972 if (fd->size) { \ | |
5118 | 973 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \ |
3922 | 974 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
975 } \ | |
976 } \ | |
977 if (url) { \ | |
978 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \ | |
5012 | 979 g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), g_strdup(url)); \ |
3922 | 980 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
4735 | 981 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); \ |
982 g_object_set_data(G_OBJECT(texttag), "link_url", g_strdup(url)); \ | |
983 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
3922 | 984 } \ |
985 wpos = 0; \ | |
986 ws[0] = 0; \ | |
987 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4895 | 988 if (x == NEW_SCALABLE_BIT) { \ |
989 GdkRectangle rect; \ | |
990 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); \ | |
991 scalable->add_to(scalable, imhtml, &iter); \ | |
992 scalable->scale(scalable, rect.width, rect.height); \ | |
993 imhtml->scalables = g_list_append(imhtml->scalables, scalable); \ | |
994 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4343 | 995 } \ |
3922 | 996 |
4895 | 997 |
998 | |
6982 | 999 GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, |
1000 const gchar *text, | |
1001 GtkIMHtmlOptions options, | |
1002 GSList *images) | |
1428 | 1003 { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1004 gint pos = 0; |
3922 | 1005 GString *str = NULL; |
1006 GtkTextIter iter, siter; | |
1007 GtkTextMark *mark, *mark2; | |
1008 GtkTextTag *texttag; | |
1009 gchar *ws; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1010 gchar *tag; |
3922 | 1011 gchar *url = NULL; |
1012 gchar *bg = NULL; | |
6982 | 1013 gint len; |
4032 | 1014 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1015 gint type; |
3922 | 1016 const gchar *c; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1017 gchar amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1018 |
1428 | 1019 guint bold = 0, |
1020 italics = 0, | |
1021 underline = 0, | |
1022 strike = 0, | |
1023 sub = 0, | |
1024 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1025 title = 0, |
3922 | 1026 pre = 0; |
1428 | 1027 |
3922 | 1028 GSList *fonts = NULL; |
1428 | 1029 |
4612 | 1030 GdkRectangle rect; |
1031 int y, height; | |
1032 | |
4895 | 1033 GtkIMHtmlScalable *scalable = NULL; |
1034 | |
1428 | 1035 g_return_val_if_fail (imhtml != NULL, NULL); |
1036 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | |
1037 g_return_val_if_fail (text != NULL, NULL); | |
6982 | 1038 |
3922 | 1039 c = text; |
6982 | 1040 len = strlen(text); |
3922 | 1041 ws = g_malloc(len + 1); |
1042 ws[0] = 0; | |
1428 | 1043 |
1044 if (options & GTK_IMHTML_RETURN_LOG) | |
3922 | 1045 str = g_string_new(""); |
1428 | 1046 |
3922 | 1047 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); |
1048 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
4612 | 1049 |
1050 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1051 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1052 | |
1053 if(((y + height) - (rect.y + rect.height)) > height | |
1054 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1055 options |= GTK_IMHTML_NO_SCROLL; | |
1056 } | |
1057 | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1058 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1059 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1060 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1061 pos++; |
3922 | 1062 switch (type) |
1063 { | |
1064 case 1: /* B */ | |
1065 case 2: /* BOLD */ | |
5101 | 1066 case 54: /* STRONG */ |
3922 | 1067 NEW_BIT (NEW_TEXT_BIT); |
1068 bold++; | |
1069 break; | |
1070 case 3: /* /B */ | |
1071 case 4: /* /BOLD */ | |
5101 | 1072 case 55: /* /STRONG */ |
3922 | 1073 NEW_BIT (NEW_TEXT_BIT); |
1074 if (bold) | |
1075 bold--; | |
1076 break; | |
1077 case 5: /* I */ | |
1078 case 6: /* ITALIC */ | |
5101 | 1079 case 52: /* EM */ |
3922 | 1080 NEW_BIT (NEW_TEXT_BIT); |
1081 italics++; | |
1082 break; | |
1083 case 7: /* /I */ | |
1084 case 8: /* /ITALIC */ | |
5101 | 1085 case 53: /* /EM */ |
3922 | 1086 NEW_BIT (NEW_TEXT_BIT); |
1087 if (italics) | |
1088 italics--; | |
1089 break; | |
1090 case 9: /* U */ | |
1091 case 10: /* UNDERLINE */ | |
1092 NEW_BIT (NEW_TEXT_BIT); | |
1093 underline++; | |
1094 break; | |
1095 case 11: /* /U */ | |
1096 case 12: /* /UNDERLINE */ | |
1097 NEW_BIT (NEW_TEXT_BIT); | |
1098 if (underline) | |
1099 underline--; | |
1100 break; | |
1101 case 13: /* S */ | |
1102 case 14: /* STRIKE */ | |
1103 NEW_BIT (NEW_TEXT_BIT); | |
1104 strike++; | |
1105 break; | |
1106 case 15: /* /S */ | |
1107 case 16: /* /STRIKE */ | |
1108 NEW_BIT (NEW_TEXT_BIT); | |
1109 if (strike) | |
1110 strike--; | |
1111 break; | |
1112 case 17: /* SUB */ | |
1113 NEW_BIT (NEW_TEXT_BIT); | |
1114 sub++; | |
1115 break; | |
1116 case 18: /* /SUB */ | |
1117 NEW_BIT (NEW_TEXT_BIT); | |
1118 if (sub) | |
1119 sub--; | |
1120 break; | |
1121 case 19: /* SUP */ | |
1122 NEW_BIT (NEW_TEXT_BIT); | |
1123 sup++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1124 break; |
3922 | 1125 case 20: /* /SUP */ |
1126 NEW_BIT (NEW_TEXT_BIT); | |
1127 if (sup) | |
1128 sup--; | |
1129 break; | |
1130 case 21: /* PRE */ | |
1131 NEW_BIT (NEW_TEXT_BIT); | |
1132 pre++; | |
1133 break; | |
1134 case 22: /* /PRE */ | |
1135 NEW_BIT (NEW_TEXT_BIT); | |
1136 if (pre) | |
1137 pre--; | |
1138 break; | |
1139 case 23: /* TITLE */ | |
1140 NEW_BIT (NEW_TEXT_BIT); | |
1141 title++; | |
1142 break; | |
1143 case 24: /* /TITLE */ | |
1144 if (title) { | |
1145 if (options & GTK_IMHTML_NO_TITLE) { | |
1146 wpos = 0; | |
1147 ws [wpos] = '\0'; | |
1148 } | |
1149 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1150 } |
3922 | 1151 break; |
1152 case 25: /* BR */ | |
5174 | 1153 case 58: /* BR/ */ |
3922 | 1154 ws[wpos] = '\n'; |
1155 wpos++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1156 NEW_BIT (NEW_TEXT_BIT); |
6982 | 1157 break; |
3922 | 1158 case 26: /* HR */ |
1159 case 42: /* HR (opt) */ | |
1160 ws[wpos++] = '\n'; | |
5967 | 1161 scalable = gtk_imhtml_hr_new(); |
4895 | 1162 NEW_BIT(NEW_SCALABLE_BIT); |
4343 | 1163 ws[wpos++] = '\n'; |
3922 | 1164 break; |
1165 case 27: /* /FONT */ | |
1166 if (fonts) { | |
5967 | 1167 GtkIMHtmlFontDetail *font = fonts->data; |
3922 | 1168 NEW_BIT (NEW_TEXT_BIT); |
1169 fonts = g_slist_remove (fonts, font); | |
1170 if (font->face) | |
1171 g_free (font->face); | |
1172 if (font->fore) | |
1173 g_free (font->fore); | |
1174 if (font->back) | |
1175 g_free (font->back); | |
4032 | 1176 if (font->sml) |
1177 g_free (font->sml); | |
3922 | 1178 g_free (font); |
1179 } | |
1180 break; | |
1181 case 28: /* /A */ | |
1182 if (url) { | |
1183 NEW_BIT(NEW_TEXT_BIT); | |
1184 g_free(url); | |
1185 url = NULL; | |
2993 | 1186 break; |
1187 } | |
3922 | 1188 case 29: /* P */ |
1189 case 30: /* /P */ | |
1190 case 31: /* H3 */ | |
1191 case 32: /* /H3 */ | |
1192 case 33: /* HTML */ | |
1193 case 34: /* /HTML */ | |
1194 case 35: /* BODY */ | |
1195 case 36: /* /BODY */ | |
1196 case 37: /* FONT */ | |
1197 case 38: /* HEAD */ | |
1198 case 39: /* /HEAD */ | |
6982 | 1199 case 40: /* BINARY */ |
1200 case 41: /* /BINARY */ | |
3922 | 1201 break; |
1202 case 43: /* FONT (opt) */ | |
1203 { | |
4032 | 1204 gchar *color, *back, *face, *size, *sml; |
5967 | 1205 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 1206 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
1207 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
1208 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
1209 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 1210 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
1211 if (!(color || back || face || size || sml)) | |
3922 | 1212 break; |
1213 | |
1214 NEW_BIT (NEW_TEXT_BIT); | |
1215 | |
5967 | 1216 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 1217 if (fonts) |
1218 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1219 |
3922 | 1220 if (color && !(options & GTK_IMHTML_NO_COLOURS)) |
1221 font->fore = color; | |
1222 else if (oldfont && oldfont->fore) | |
1223 font->fore = g_strdup(oldfont->fore); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1224 |
3922 | 1225 if (back && !(options & GTK_IMHTML_NO_COLOURS)) |
1226 font->back = back; | |
1227 else if (oldfont && oldfont->back) | |
1228 font->back = g_strdup(oldfont->back); | |
1229 | |
1230 if (face && !(options & GTK_IMHTML_NO_FONTS)) | |
1231 font->face = face; | |
1232 else if (oldfont && oldfont->face) | |
1233 font->face = g_strdup(oldfont->face); | |
4629 | 1234 if (font->face && (atoi(font->face) > 100)) { |
1235 g_free(font->face); | |
1236 font->face = g_strdup("100"); | |
1237 } | |
4032 | 1238 |
1239 if (sml) | |
1240 font->sml = sml; | |
1241 else if (oldfont && oldfont->sml) | |
1242 font->sml = g_strdup(oldfont->sml); | |
1243 | |
3922 | 1244 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
1245 if (*size == '+') { | |
1246 sscanf (size + 1, "%hd", &font->size); | |
1247 font->size += 3; | |
1248 } else if (*size == '-') { | |
1249 sscanf (size + 1, "%hd", &font->size); | |
1250 font->size = MAX (0, 3 - font->size); | |
1251 } else if (isdigit (*size)) { | |
1252 sscanf (size, "%hd", &font->size); | |
1253 } | |
6042 | 1254 if (font->size > 100) |
1255 font->size = 100; | |
3922 | 1256 } else if (oldfont) |
1257 font->size = oldfont->size; | |
1258 g_free(size); | |
1259 fonts = g_slist_prepend (fonts, font); | |
1260 } | |
1261 break; | |
1262 case 44: /* BODY (opt) */ | |
1263 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
1264 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
1265 if (bgcolor) { | |
1266 NEW_BIT(NEW_TEXT_BIT); | |
1267 if (bg) | |
1268 g_free(bg); | |
1269 bg = bgcolor; | |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
1270 } |
1428 | 1271 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1272 break; |
3922 | 1273 case 45: /* A (opt) */ |
1274 { | |
1275 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
1276 if (href) { | |
1277 NEW_BIT (NEW_TEXT_BIT); | |
1278 if (url) | |
1279 g_free (url); | |
1280 url = href; | |
1281 } | |
2993 | 1282 } |
3922 | 1283 break; |
4895 | 1284 case 46: /* IMG (opt) */ |
6982 | 1285 case 59: /* IMG */ |
4895 | 1286 { |
6982 | 1287 GdkPixbuf *img = NULL; |
1288 const gchar *filename = NULL; | |
4895 | 1289 |
6982 | 1290 if (images && images->data) { |
1291 img = images->data; | |
1292 images = images->next; | |
1293 filename = g_object_get_data(G_OBJECT(img), "filename"); | |
1294 g_object_ref(G_OBJECT(img)); | |
1295 } else { | |
1296 img = gtk_widget_render_icon(GTK_WIDGET(imhtml), | |
1297 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, | |
1298 "gtkimhtml-missing-image"); | |
1299 } | |
4895 | 1300 |
6982 | 1301 scalable = gtk_imhtml_image_new(img, filename); |
1302 NEW_BIT(NEW_SCALABLE_BIT); | |
1303 g_object_unref(G_OBJECT(img)); | |
4895 | 1304 } |
3922 | 1305 case 47: /* P (opt) */ |
1306 case 48: /* H3 (opt) */ | |
5093 | 1307 case 49: /* HTML (opt) */ |
5101 | 1308 case 50: /* CITE */ |
1309 case 51: /* /CITE */ | |
5104 | 1310 case 56: /* SPAN */ |
1311 case 57: /* /SPAN */ | |
2993 | 1312 break; |
6982 | 1313 case 60: /* comment */ |
3922 | 1314 NEW_BIT (NEW_TEXT_BIT); |
6124 | 1315 if (imhtml->show_comments) |
1316 wpos = g_snprintf (ws, len, "%s", tag); | |
3922 | 1317 NEW_BIT (NEW_COMMENT_BIT); |
1318 break; | |
1319 default: | |
6882 | 1320 break; |
2993 | 1321 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1322 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1323 pos += tlen; |
4138 | 1324 if(tag) |
1325 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1326 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1327 ws [wpos++] = amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1328 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1329 pos += tlen; |
1428 | 1330 } else if (*c == '\n') { |
1331 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 1332 ws[wpos] = '\n'; |
1333 wpos++; | |
1428 | 1334 NEW_BIT (NEW_TEXT_BIT); |
1335 } | |
1336 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1337 pos++; |
4253 | 1338 } 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
|
1339 GtkTextChildAnchor *anchor; |
6882 | 1340 GtkWidget *icon = NULL; |
1341 GdkPixbufAnimation *annipixbuf = NULL; | |
1342 GdkPixbuf *pixbuf = NULL; | |
5967 | 1343 GtkIMHtmlFontDetail *fd; |
4032 | 1344 gchar *sml = NULL; |
1345 if (fonts) { | |
1346 fd = fonts->data; | |
1347 sml = fd->sml; | |
1348 } | |
1349 NEW_BIT (NEW_TEXT_BIT); | |
1350 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1351 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); |
6882 | 1352 annipixbuf = gtk_smiley_tree_image(imhtml, sml, ws); |
1353 if(annipixbuf) { | |
1354 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
1355 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); | |
1356 if(pixbuf) | |
1357 icon = gtk_image_new_from_pixbuf(pixbuf); | |
1358 } else { | |
1359 icon = gtk_image_new_from_animation(annipixbuf); | |
1360 } | |
1361 } | |
1362 | |
1363 if (icon) { | |
6839
bdc4e73f354d
[gaim-migrate @ 7384]
Christian Hammond <chipx86@chipx86.com>
parents:
6814
diff
changeset
|
1364 gtk_widget_show(icon); |
bdc4e73f354d
[gaim-migrate @ 7384]
Christian Hammond <chipx86@chipx86.com>
parents:
6814
diff
changeset
|
1365 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
|
1366 } |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1367 |
4032 | 1368 c += smilelen; |
1369 pos += smilelen; | |
1370 wpos = 0; | |
1371 ws[0] = 0; | |
1372 } else if (*c) { | |
1428 | 1373 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1374 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1375 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1376 break; |
1428 | 1377 } |
1378 } | |
3922 | 1379 |
1380 NEW_BIT(NEW_TEXT_BIT); | |
1428 | 1381 if (url) { |
1382 g_free (url); | |
3922 | 1383 if (str) |
1384 str = g_string_append (str, "</A>"); | |
1428 | 1385 } |
3922 | 1386 |
4032 | 1387 while (fonts) { |
5967 | 1388 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 1389 fonts = g_slist_remove (fonts, font); |
1390 if (font->face) | |
1391 g_free (font->face); | |
1392 if (font->fore) | |
1393 g_free (font->fore); | |
1394 if (font->back) | |
1395 g_free (font->back); | |
1396 if (font->sml) | |
1397 g_free (font->sml); | |
1398 g_free (font); | |
1399 if (str) | |
1400 str = g_string_append (str, "</FONT>"); | |
1401 } | |
1402 | |
3922 | 1403 if (str) { |
1428 | 1404 while (bold) { |
3922 | 1405 str = g_string_append (str, "</B>"); |
1428 | 1406 bold--; |
1407 } | |
1408 while (italics) { | |
3922 | 1409 str = g_string_append (str, "</I>"); |
1428 | 1410 italics--; |
1411 } | |
1412 while (underline) { | |
3922 | 1413 str = g_string_append (str, "</U>"); |
1428 | 1414 underline--; |
1415 } | |
1416 while (strike) { | |
3922 | 1417 str = g_string_append (str, "</S>"); |
1428 | 1418 strike--; |
1419 } | |
1420 while (sub) { | |
3922 | 1421 str = g_string_append (str, "</SUB>"); |
1428 | 1422 sub--; |
1423 } | |
1424 while (sup) { | |
3922 | 1425 str = g_string_append (str, "</SUP>"); |
1428 | 1426 sup--; |
1427 } | |
1428 while (title) { | |
3922 | 1429 str = g_string_append (str, "</TITLE>"); |
1428 | 1430 title--; |
1431 } | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1432 while (pre) { |
3922 | 1433 str = g_string_append (str, "</PRE>"); |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1434 pre--; |
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1435 } |
1428 | 1436 } |
4032 | 1437 g_free (ws); |
4630 | 1438 if(bg) |
1439 g_free(bg); | |
4032 | 1440 if (!(options & GTK_IMHTML_NO_SCROLL)) |
1441 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
1442 0, TRUE, 0.0, 1.0); | |
3922 | 1443 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
1444 return str; | |
1445 } | |
1446 | |
4892 | 1447 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
1448 { | |
4288 | 1449 g_hash_table_destroy(imhtml->smiley_data); |
1450 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 1451 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1452 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 1453 imhtml->default_smilies = gtk_smiley_tree_new(); |
1454 } | |
3922 | 1455 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
4253 | 1456 gboolean show) |
1457 { | |
1458 imhtml->show_smileys = show; | |
1459 } | |
3922 | 1460 |
1461 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
4253 | 1462 gboolean show) |
1463 { | |
6124 | 1464 imhtml->show_comments = show; |
4253 | 1465 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1466 |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1467 void |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1468 gtk_imhtml_clear (GtkIMHtml *imhtml) |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1469 { |
3922 | 1470 GtkTextIter start, end; |
2993 | 1471 |
3922 | 1472 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
1473 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
1474 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1475 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
1476 |
4046 | 1477 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
1478 { | |
5282 | 1479 GdkRectangle rect; |
1480 GtkTextIter iter; | |
4046 | 1481 |
5282 | 1482 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
1483 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
1484 rect.y - rect.height); | |
1485 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
1486 | |
4046 | 1487 } |
5282 | 1488 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
1489 { | |
1490 GdkRectangle rect; | |
1491 GtkTextIter iter; | |
1492 | |
1493 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1494 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
1495 rect.y + rect.height); | |
1496 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
1497 } | |
4735 | 1498 |
5967 | 1499 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
6982 | 1500 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) |
4735 | 1501 { |
5967 | 1502 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 1503 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 1504 |
5967 | 1505 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
1506 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
1507 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 1508 |
1509 im_image->pixbuf = img; | |
5012 | 1510 im_image->image = image; |
4895 | 1511 im_image->width = gdk_pixbuf_get_width(img); |
1512 im_image->height = gdk_pixbuf_get_height(img); | |
1513 im_image->mark = NULL; | |
6982 | 1514 im_image->filename = filename ? g_strdup(filename) : NULL; |
4895 | 1515 |
5046 | 1516 g_object_ref(img); |
4895 | 1517 return GTK_IMHTML_SCALABLE(im_image); |
1518 } | |
1519 | |
5967 | 1520 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 1521 { |
5967 | 1522 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 1523 |
1524 if(image->width > width || image->height > height){ | |
1525 GdkPixbuf *new_image = NULL; | |
1526 float factor; | |
1527 int new_width = image->width, new_height = image->height; | |
1528 | |
1529 if(image->width > width){ | |
1530 factor = (float)(width)/image->width; | |
1531 new_width = width; | |
1532 new_height = image->height * factor; | |
1533 } | |
1534 if(new_height > height){ | |
1535 factor = (float)(height)/new_height; | |
1536 new_height = height; | |
1537 new_width = new_width * factor; | |
1538 } | |
1539 | |
5046 | 1540 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 1541 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 1542 g_object_unref(G_OBJECT(new_image)); |
1543 } | |
1544 } | |
1545 | |
5012 | 1546 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
1547 { | |
1548 const gchar *filename = gtk_file_selection_get_filename(sel); | |
5967 | 1549 gchar *dirname; |
1550 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
5012 | 1551 gchar *type = NULL; |
5019 | 1552 GError *error = NULL; |
5015 | 1553 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 1554 GSList *formats = gdk_pixbuf_get_formats(); |
6162 | 1555 #else |
1556 char *basename = g_path_get_basename(filename); | |
1557 char *ext = strrchr(basename, '.'); | |
5959 | 1558 #endif |
5012 | 1559 |
5967 | 1560 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
1561 /* append a / if needed */ | |
1562 if (filename[strlen(filename) - 1] != '/') { | |
1563 dirname = g_strconcat(filename, "/", NULL); | |
1564 } else { | |
1565 dirname = g_strdup(filename); | |
1566 } | |
1567 gtk_file_selection_set_filename(sel, dirname); | |
1568 g_free(dirname); | |
5959 | 1569 return; |
5967 | 1570 } |
5959 | 1571 |
1572 #if GTK_CHECK_VERSION(2,2,0) | |
5012 | 1573 while(formats){ |
1574 GdkPixbufFormat *format = formats->data; | |
1575 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
1576 gpointer p = extensions; | |
1577 | |
1578 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
1579 gchar *fmt_ext = extensions[0]; | |
1580 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
1581 | |
1582 if(!strcmp(fmt_ext, file_ext)){ | |
1583 type = gdk_pixbuf_format_get_name(format); | |
1584 break; | |
1585 } | |
1586 | |
1587 extensions++; | |
1588 } | |
1589 | |
1590 g_strfreev(p); | |
1591 | |
1592 if(type) | |
1593 break; | |
1594 | |
1595 formats = formats->next; | |
1596 } | |
1597 | |
5020 | 1598 g_slist_free(formats); |
1599 #else | |
1600 /* this is really ugly code, but I think it will work */ | |
1601 if(ext) { | |
1602 ext++; | |
1603 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
1604 type = g_strdup("jpeg"); | |
1605 else if(!g_ascii_strcasecmp(ext, "png")) | |
1606 type = g_strdup("png"); | |
1607 } | |
1608 | |
1609 g_free(basename); | |
1610 #endif | |
1611 | |
5012 | 1612 /* If I can't find a valid type, I will just tell the user about it and then assume |
1613 it's a png */ | |
1614 if(!type){ | |
1615 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
5967 | 1616 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
5012 | 1617 type = g_strdup("png"); |
1618 } | |
1619 | |
5046 | 1620 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 1621 |
1622 if(error){ | |
1623 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
1624 _("Error saving image: %s"), error->message); | |
1625 g_error_free(error); | |
1626 } | |
1627 | |
1628 g_free(type); | |
1629 } | |
1630 | |
5967 | 1631 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
5012 | 1632 { |
5967 | 1633 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
5012 | 1634 |
6982 | 1635 if (image->filename) |
1636 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
5967 | 1637 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
5012 | 1638 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
1639 G_CALLBACK(write_img_to_file), sel); | |
1640 | |
1641 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
1642 G_CALLBACK(gtk_widget_destroy), sel); | |
1643 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
1644 G_CALLBACK(gtk_widget_destroy), sel); | |
1645 | |
1646 gtk_widget_show(sel); | |
1647 } | |
1648 | |
5967 | 1649 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 1650 { |
1651 GdkEventButton *event_button = (GdkEventButton *) event; | |
1652 | |
1653 if (event->type == GDK_BUTTON_RELEASE) { | |
1654 if(event_button->button == 3) { | |
1655 GtkWidget *img, *item, *menu; | |
1656 gchar *text = g_strdup_printf(_("_Save Image...")); | |
1657 menu = gtk_menu_new(); | |
1658 | |
1659 /* buttons and such */ | |
1660 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
1661 item = gtk_image_menu_item_new_with_mnemonic(text); | |
1662 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 1663 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 1664 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
1665 | |
1666 gtk_widget_show_all(menu); | |
1667 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
1668 event_button->button, event_button->time); | |
1669 | |
1670 g_free(text); | |
1671 return TRUE; | |
1672 } | |
1673 } | |
1674 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
1675 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1676 be caught by the regular GtkTextView menu */ | |
1677 else | |
1678 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1679 | |
1680 } | |
5967 | 1681 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
1682 { | |
1683 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
1684 | |
1685 g_object_unref(image->pixbuf); | |
6982 | 1686 if (image->filename) |
1687 g_free(image->filename); | |
5967 | 1688 g_free(scale); |
1689 } | |
1690 | |
1691 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1692 { | |
1693 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
1694 GtkWidget *box = gtk_event_box_new(); | |
1695 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
1696 | |
1697 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
1698 | |
1699 gtk_widget_show(GTK_WIDGET(image->image)); | |
1700 gtk_widget_show(box); | |
1701 | |
1702 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
1703 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
1704 } | |
1705 | |
1706 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
1707 { | |
1708 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
1709 | |
1710 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
1711 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
1712 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
1713 | |
1714 hr->sep = gtk_hseparator_new(); | |
1715 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
1716 gtk_widget_show(hr->sep); | |
1717 | |
1718 return GTK_IMHTML_SCALABLE(hr); | |
1719 } | |
1720 | |
1721 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
1722 { | |
1723 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width, 2); | |
1724 } | |
1725 | |
1726 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1727 { | |
1728 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
1729 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
1730 | |
1731 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); | |
1732 } | |
1733 | |
1734 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
1735 { | |
1736 g_free(scale); | |
1737 } |