Mercurial > pidgin
annotate src/gtkimhtml.c @ 6056:395116fdd270
[gaim-migrate @ 6506]
I'm reverting the patch to make f2 retroactively toggle timestamps because
it causes highlighting in the gtkimhtml window to act strangely when
timestamps are disabled. Cheung, if you think you can fix this please do,
but it seems like it's due to the incomplete nature of invisibility in
GtkTextViews.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 08 Jul 2003 01:28:42 +0000 |
parents | 19cb60247a6c |
children | c99959f1bb73 |
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 | |
97 index = (int) pos - (int) t->values->str; | |
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 | |
304 | |
4263 | 305 |
4032 | 306 static GtkTextViewClass *parent_class = NULL; |
307 | |
3922 | 308 /* GtkIMHtml has one signal--URL_CLICKED */ |
1428 | 309 enum { |
310 URL_CLICKED, | |
311 LAST_SIGNAL | |
312 }; | |
313 static guint signals [LAST_SIGNAL] = { 0 }; | |
314 | |
4032 | 315 static void |
316 gtk_imhtml_finalize (GObject *object) | |
317 { | |
318 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
4895 | 319 GList *scalables; |
320 | |
4138 | 321 g_hash_table_destroy(imhtml->smiley_data); |
4032 | 322 gtk_smiley_tree_destroy(imhtml->default_smilies); |
4138 | 323 gdk_cursor_unref(imhtml->hand_cursor); |
324 gdk_cursor_unref(imhtml->arrow_cursor); | |
4735 | 325 if(imhtml->tip_window){ |
326 gtk_widget_destroy(imhtml->tip_window); | |
327 } | |
328 if(imhtml->tip_timer) | |
329 gtk_timeout_remove(imhtml->tip_timer); | |
330 | |
4895 | 331 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
332 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
333 scale->free(scale); | |
334 } | |
335 | |
336 g_list_free(imhtml->scalables); | |
4032 | 337 G_OBJECT_CLASS(parent_class)->finalize (object); |
338 } | |
1428 | 339 |
3922 | 340 /* Boring GTK stuff */ |
341 static void gtk_imhtml_class_init (GtkIMHtmlClass *class) | |
1428 | 342 { |
3922 | 343 GtkObjectClass *object_class; |
4032 | 344 GObjectClass *gobject_class; |
3922 | 345 object_class = (GtkObjectClass*) class; |
4032 | 346 gobject_class = (GObjectClass*) class; |
347 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); | |
4417 | 348 signals[URL_CLICKED] = g_signal_new("url_clicked", |
349 G_TYPE_FROM_CLASS(gobject_class), | |
350 G_SIGNAL_RUN_FIRST, | |
351 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
352 NULL, | |
353 0, | |
354 g_cclosure_marshal_VOID__POINTER, | |
355 G_TYPE_NONE, 1, | |
356 G_TYPE_POINTER); | |
4032 | 357 gobject_class->finalize = gtk_imhtml_finalize; |
1428 | 358 } |
359 | |
3922 | 360 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 361 { |
3922 | 362 GtkTextIter iter; |
363 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
364 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
365 imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); | |
366 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
5105 | 367 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 368 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), FALSE); |
369 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); | |
370 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), FALSE); | |
371 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ | |
3465 | 372 |
3922 | 373 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
374 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ | |
375 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); | |
376 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
377 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
378 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
379 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
380 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
381 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
3465 | 382 |
3922 | 383 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
384 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
385 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
2993 | 386 |
4253 | 387 imhtml->show_smileys = TRUE; |
6056 | 388 imhtml->show_comments = TRUE; |
4253 | 389 |
4892 | 390 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 391 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 392 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 393 |
4944 | 394 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 395 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 396 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
397 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); | |
4735 | 398 |
399 imhtml->tip = NULL; | |
400 imhtml->tip_timer = 0; | |
401 imhtml->tip_window = NULL; | |
4895 | 402 |
403 imhtml->scalables = NULL; | |
2993 | 404 } |
405 | |
3922 | 406 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 407 { |
4635 | 408 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 409 } |
410 | |
4635 | 411 GType gtk_imhtml_get_type() |
1428 | 412 { |
4635 | 413 static GType imhtml_type = 0; |
1428 | 414 |
415 if (!imhtml_type) { | |
4635 | 416 static const GTypeInfo imhtml_info = { |
417 sizeof(GtkIMHtmlClass), | |
418 NULL, | |
419 NULL, | |
420 (GClassInitFunc) gtk_imhtml_class_init, | |
421 NULL, | |
422 NULL, | |
1428 | 423 sizeof (GtkIMHtml), |
4635 | 424 0, |
425 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 426 }; |
4635 | 427 |
428 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
429 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 430 } |
431 | |
432 return imhtml_type; | |
433 } | |
434 | |
4417 | 435 struct url_data { |
436 GObject *object; | |
437 gchar *url; | |
438 }; | |
439 | |
440 static void url_open(GtkWidget *w, struct url_data *data) { | |
441 if(!data) return; | |
442 | |
443 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); | |
444 | |
445 g_object_unref(data->object); | |
446 g_free(data->url); | |
447 g_free(data); | |
448 } | |
5582 | 449 |
4417 | 450 static void url_copy(GtkWidget *w, gchar *url) { |
451 GtkClipboard *clipboard; | |
452 | |
5293
ead927e2543f
[gaim-migrate @ 5665]
Christian Hammond <chipx86@chipx86.com>
parents:
5282
diff
changeset
|
453 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
4417 | 454 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 455 |
456 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | |
457 gtk_clipboard_set_text(clipboard, url, -1); | |
4417 | 458 } |
459 | |
460 /* The callback for an event on a link tag. */ | |
5091 | 461 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, char *url) { |
4417 | 462 GdkEventButton *event_button = (GdkEventButton *) event; |
463 | |
3922 | 464 if (event->type == GDK_BUTTON_RELEASE) { |
4417 | 465 if (event_button->button == 1) { |
466 GtkTextIter start, end; | |
467 /* we shouldn't open a URL if the user has selected something: */ | |
468 gtk_text_buffer_get_selection_bounds( | |
469 gtk_text_iter_get_buffer(arg2), &start, &end); | |
470 if(gtk_text_iter_get_offset(&start) != | |
471 gtk_text_iter_get_offset(&end)) | |
472 return FALSE; | |
473 | |
474 /* A link was clicked--we emit the "url_clicked" signal | |
475 * with the URL as the argument */ | |
5091 | 476 g_signal_emit(imhtml, signals[URL_CLICKED], 0, url); |
4417 | 477 return FALSE; |
478 } else if(event_button->button == 3) { | |
4745 | 479 GtkWidget *img, *item, *menu; |
4417 | 480 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 481 tempdata->object = g_object_ref(imhtml); |
4417 | 482 tempdata->url = g_strdup(url); |
4745 | 483 |
5091 | 484 /* Don't want the tooltip around if user right-clicked on link */ |
485 if (GTK_IMHTML(imhtml)->tip_window) { | |
486 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
487 GTK_IMHTML(imhtml)->tip_window = NULL; | |
488 } | |
489 if (GTK_IMHTML(imhtml)->tip_timer) { | |
490 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
491 GTK_IMHTML(imhtml)->tip_timer = 0; | |
492 } | |
493 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 494 menu = gtk_menu_new(); |
4745 | 495 |
4417 | 496 /* buttons and such */ |
497 img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); | |
4420 | 498 item = gtk_image_menu_item_new_with_mnemonic(_("_Copy Link Location")); |
4417 | 499 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
500 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_copy), | |
501 url); | |
502 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
503 | |
504 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); | |
4420 | 505 item = gtk_image_menu_item_new_with_mnemonic(_("_Open Link in Browser")); |
4417 | 506 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
507 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_open), | |
508 tempdata); | |
509 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
4756 | 510 |
4417 | 511 gtk_widget_show_all(menu); |
4756 | 512 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
513 event_button->button, event_button->time); | |
4745 | 514 |
4417 | 515 return TRUE; |
516 } | |
1428 | 517 } |
4417 | 518 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
519 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
520 be caught by the regular GtkTextView menu */ | |
521 else | |
522 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 523 } |
524 | |
4298 | 525 /* this isn't used yet |
4032 | 526 static void |
4263 | 527 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
528 GtkIMHtmlSmiley *smiley) | |
4032 | 529 { |
530 GtkSmileyTree *t = tree; | |
4263 | 531 const gchar *x = smiley->smile; |
4032 | 532 gint len = 0; |
533 | |
534 while (*x) { | |
535 gchar *pos; | |
536 | |
537 if (!t->values) | |
538 return; | |
539 | |
540 pos = strchr (t->values->str, *x); | |
541 if (pos) | |
542 t = t->children [(int) pos - (int) t->values->str]; | |
543 else | |
544 return; | |
545 | |
546 x++; len++; | |
547 } | |
548 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
549 if (t->image) { |
4032 | 550 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
551 } |
4032 | 552 } |
4298 | 553 */ |
554 | |
4032 | 555 |
556 static gint | |
557 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
558 const gchar *text) | |
559 { | |
560 GtkSmileyTree *t = tree; | |
561 const gchar *x = text; | |
562 gint len = 0; | |
563 | |
564 while (*x) { | |
565 gchar *pos; | |
566 | |
567 if (!t->values) | |
568 break; | |
569 | |
570 pos = strchr (t->values->str, *x); | |
571 if (pos) | |
572 t = t->children [(int) pos - (int) t->values->str]; | |
573 else | |
574 break; | |
575 | |
576 x++; len++; | |
577 } | |
578 | |
579 if (t->image) | |
580 return len; | |
581 | |
582 return 0; | |
583 } | |
584 | |
585 void | |
4263 | 586 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
587 gchar *sml, | |
588 GtkIMHtmlSmiley *smiley) | |
4032 | 589 { |
590 GtkSmileyTree *tree; | |
591 g_return_if_fail (imhtml != NULL); | |
592 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
4263 | 593 |
4032 | 594 if (sml == NULL) |
595 tree = imhtml->default_smilies; | |
596 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
597 } else { | |
598 tree = gtk_smiley_tree_new(); | |
4892 | 599 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 600 } |
601 | |
4263 | 602 gtk_smiley_tree_insert (tree, smiley); |
4032 | 603 } |
604 | |
605 static gboolean | |
606 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
607 GSList *fonts, | |
608 const gchar *text, | |
609 gint *len) | |
610 { | |
611 GtkSmileyTree *tree; | |
5967 | 612 GtkIMHtmlFontDetail *font; |
4032 | 613 char *sml = NULL; |
614 | |
615 if (fonts) { | |
616 font = fonts->data; | |
617 sml = font->sml; | |
618 } | |
619 | |
620 if (sml == NULL) | |
621 tree = imhtml->default_smilies; | |
622 else { | |
623 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
624 } | |
625 if (tree == NULL) | |
626 return FALSE; | |
627 | |
628 *len = gtk_smiley_tree_lookup (tree, text); | |
629 return (*len > 0); | |
630 } | |
631 | |
4263 | 632 GdkPixbuf* |
4032 | 633 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
634 const gchar *sml, | |
635 const gchar *text) | |
636 { | |
637 GtkSmileyTree *t; | |
638 const gchar *x = text; | |
639 if (sml == NULL) | |
640 t = imhtml->default_smilies; | |
641 else | |
642 t = g_hash_table_lookup(imhtml->smiley_data, sml); | |
643 | |
644 | |
645 if (t == NULL) | |
646 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
647 | |
648 while (*x) { | |
649 gchar *pos; | |
650 | |
651 if (!t->values) { | |
652 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
653 } | |
654 | |
655 pos = strchr (t->values->str, *x); | |
656 if (pos) { | |
657 t = t->children [(int) pos - (int) t->values->str]; | |
658 } else { | |
659 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
660 } | |
661 x++; | |
662 } | |
663 | |
4263 | 664 if (!t->image->icon) |
665 t->image->icon = gdk_pixbuf_new_from_file(t->image->file, NULL); | |
666 | |
667 return t->image->icon; | |
4032 | 668 } |
4793 | 669 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 670 *tag = g_strndup (string, strlen (x)); \ |
671 *len = strlen (x) + 1; \ | |
672 return TRUE; \ | |
673 } \ | |
674 (*type)++ | |
1428 | 675 |
4793 | 676 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 677 const gchar *c = string + strlen (x " "); \ |
678 gchar e = '"'; \ | |
679 gboolean quote = FALSE; \ | |
680 while (*c) { \ | |
681 if (*c == '"' || *c == '\'') { \ | |
682 if (quote && (*c == e)) \ | |
683 quote = !quote; \ | |
684 else if (!quote) { \ | |
685 quote = !quote; \ | |
686 e = *c; \ | |
687 } \ | |
688 } else if (!quote && (*c == '>')) \ | |
689 break; \ | |
690 c++; \ | |
691 } \ | |
692 if (*c) { \ | |
693 *tag = g_strndup (string, c - string); \ | |
694 *len = c - string + 1; \ | |
695 return TRUE; \ | |
696 } \ | |
697 } \ | |
698 (*type)++ | |
1428 | 699 |
700 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
701 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
702 gtk_imhtml_is_amp_escape (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
703 gchar *replace, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
704 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
705 { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
706 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
707 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
708 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
709 |
4793 | 710 if (!g_ascii_strncasecmp (string, "&", 5)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
711 *replace = '&'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
712 *length = 5; |
4793 | 713 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
714 *replace = '<'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
715 *length = 4; |
4793 | 716 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
717 *replace = '>'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
718 *length = 4; |
4793 | 719 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
720 *replace = ' '; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
721 *length = 6; |
4793 | 722 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
723 *replace = '©'; /* was: '©' */ |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
724 *length = 6; |
4793 | 725 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
726 *replace = '\"'; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
727 *length = 6; |
4793 | 728 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3705
diff
changeset
|
729 *replace = '®'; /* was: '®' */ |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
730 *length = 5; |
5093 | 731 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
732 *replace = '\''; | |
733 *length = 6; | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
734 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
735 guint pound = 0; |
3004 | 736 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
737 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
738 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
739 *replace = (gchar)pound; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
740 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
741 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
742 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
743 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
744 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
745 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
746 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
747 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
748 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
749 |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
750 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
751 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
752 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
753 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
754 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
755 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
756 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
757 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
758 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
759 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
760 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
761 if (!strchr (string, '>')) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
762 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
763 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
764 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
765 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
766 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
767 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
768 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
769 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
770 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
771 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
772 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
773 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
774 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
775 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
776 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
777 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
778 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
779 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
780 VALID_TAG ("SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
781 VALID_TAG ("/SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
782 VALID_TAG ("SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
783 VALID_TAG ("/SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
784 VALID_TAG ("PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
785 VALID_TAG ("/PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
786 VALID_TAG ("TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
787 VALID_TAG ("/TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
788 VALID_TAG ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
789 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
790 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
791 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
792 VALID_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
793 VALID_TAG ("/P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
794 VALID_TAG ("H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
795 VALID_TAG ("/H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
796 VALID_TAG ("HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
797 VALID_TAG ("/HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
798 VALID_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
799 VALID_TAG ("/BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
800 VALID_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
801 VALID_TAG ("HEAD"); |
2993 | 802 VALID_TAG ("/HEAD"); |
803 VALID_TAG ("BINARY"); | |
804 VALID_TAG ("/BINARY"); | |
5093 | 805 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
806 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
807 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
808 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
809 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
810 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
811 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
812 VALID_OPT_TAG ("H3"); |
5093 | 813 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
814 |
5101 | 815 VALID_TAG ("CITE"); |
816 VALID_TAG ("/CITE"); | |
817 VALID_TAG ("EM"); | |
818 VALID_TAG ("/EM"); | |
819 VALID_TAG ("STRONG"); | |
820 VALID_TAG ("/STRONG"); | |
821 | |
5104 | 822 VALID_OPT_TAG ("SPAN"); |
823 VALID_TAG ("/SPAN"); | |
5174 | 824 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
5104 | 825 |
4793 | 826 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
827 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
828 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
829 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
830 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
831 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
832 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
833 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
834 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
835 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
836 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
837 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
838 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
839 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
840 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
841 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
842 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
843 gchar *e, *a; |
5177 | 844 gchar *val; |
845 gint len; | |
846 gchar c; | |
847 GString *ret; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
848 |
4793 | 849 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
850 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
851 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
852 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
853 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
854 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
855 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
856 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
857 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
858 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
859 |
4793 | 860 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
861 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
862 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
863 return NULL; |
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 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
867 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
868 while (*e && (*e != *(t - 1))) e++; |
2993 | 869 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
870 return NULL; |
5177 | 871 } else |
872 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
873 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
874 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
875 while (*e && !isspace ((gint) *e)) e++; |
5177 | 876 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
877 } |
5177 | 878 |
879 ret = g_string_new(""); | |
880 e = val; | |
881 while(*e) { | |
882 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
883 ret = g_string_append_c(ret, c); | |
884 e += len; | |
885 } else { | |
886 ret = g_string_append_c(ret, *e); | |
887 e++; | |
888 } | |
889 } | |
890 | |
891 g_free(val); | |
892 val = ret->str; | |
893 g_string_free(ret, FALSE); | |
894 return val; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
895 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
896 |
3922 | 897 |
898 | |
899 #define NEW_TEXT_BIT 0 | |
4343 | 900 #define NEW_COMMENT_BIT 2 |
4895 | 901 #define NEW_SCALABLE_BIT 1 |
3922 | 902 #define NEW_BIT(x) ws [wpos] = '\0'; \ |
903 mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \ | |
904 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \ | |
4895 | 905 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ |
3922 | 906 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \ |
907 gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \ | |
908 if (bold) \ | |
909 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \ | |
4895 | 910 if (italics) \ |
3922 | 911 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \ |
912 if (underline) \ | |
913 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \ | |
914 if (strike) \ | |
915 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \ | |
916 if (sub) \ | |
917 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \ | |
918 if (sup) \ | |
919 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \ | |
920 if (pre) \ | |
921 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &iter); \ | |
922 if (bg) { \ | |
923 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); \ | |
924 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
925 } \ | |
926 if (fonts) { \ | |
5967 | 927 GtkIMHtmlFontDetail *fd = fonts->data; \ |
3922 | 928 if (fd->fore) { \ |
929 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \ | |
930 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
931 } \ | |
932 if (fd->back) { \ | |
933 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); \ | |
934 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
935 } \ | |
936 if (fd->face) { \ | |
937 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "font", fd->face, NULL); \ | |
938 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
939 } \ | |
940 if (fd->size) { \ | |
5118 | 941 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \ |
3922 | 942 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
943 } \ | |
944 } \ | |
945 if (url) { \ | |
946 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \ | |
5012 | 947 g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), g_strdup(url)); \ |
3922 | 948 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
4735 | 949 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); \ |
950 g_object_set_data(G_OBJECT(texttag), "link_url", g_strdup(url)); \ | |
951 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
3922 | 952 } \ |
953 wpos = 0; \ | |
954 ws[0] = 0; \ | |
955 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4895 | 956 if (x == NEW_SCALABLE_BIT) { \ |
957 GdkRectangle rect; \ | |
958 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); \ | |
959 scalable->add_to(scalable, imhtml, &iter); \ | |
960 scalable->scale(scalable, rect.width, rect.height); \ | |
961 imhtml->scalables = g_list_append(imhtml->scalables, scalable); \ | |
962 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4343 | 963 } \ |
3922 | 964 |
4895 | 965 |
966 | |
3922 | 967 GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, |
968 const gchar *text, | |
969 gint len, | |
970 GtkIMHtmlOptions options) | |
1428 | 971 { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
972 gint pos = 0; |
3922 | 973 GString *str = NULL; |
974 GtkTextIter iter, siter; | |
975 GtkTextMark *mark, *mark2; | |
976 GtkTextTag *texttag; | |
977 gchar *ws; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
978 gchar *tag; |
3922 | 979 gchar *url = NULL; |
980 gchar *bg = NULL; | |
4032 | 981 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
982 gint type; |
3922 | 983 const gchar *c; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
984 gchar amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
985 |
1428 | 986 guint bold = 0, |
987 italics = 0, | |
988 underline = 0, | |
989 strike = 0, | |
990 sub = 0, | |
991 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
992 title = 0, |
3922 | 993 pre = 0; |
1428 | 994 |
3922 | 995 GSList *fonts = NULL; |
1428 | 996 |
4612 | 997 GdkRectangle rect; |
998 int y, height; | |
999 | |
4895 | 1000 GtkIMHtmlScalable *scalable = NULL; |
1001 | |
1428 | 1002 g_return_val_if_fail (imhtml != NULL, NULL); |
1003 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | |
1004 g_return_val_if_fail (text != NULL, NULL); | |
3922 | 1005 g_return_val_if_fail (len != 0, NULL); |
1006 | |
1007 c = text; | |
1008 if (len == -1) | |
1009 len = strlen(text); | |
1010 ws = g_malloc(len + 1); | |
1011 ws[0] = 0; | |
1428 | 1012 |
1013 if (options & GTK_IMHTML_RETURN_LOG) | |
3922 | 1014 str = g_string_new(""); |
1428 | 1015 |
3922 | 1016 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); |
1017 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
4612 | 1018 |
1019 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1020 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1021 | |
1022 if(((y + height) - (rect.y + rect.height)) > height | |
1023 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1024 options |= GTK_IMHTML_NO_SCROLL; | |
1025 } | |
1026 | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1027 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1028 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1029 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1030 pos++; |
3922 | 1031 switch (type) |
1032 { | |
1033 case 1: /* B */ | |
1034 case 2: /* BOLD */ | |
5101 | 1035 case 54: /* STRONG */ |
3922 | 1036 NEW_BIT (NEW_TEXT_BIT); |
1037 bold++; | |
1038 break; | |
1039 case 3: /* /B */ | |
1040 case 4: /* /BOLD */ | |
5101 | 1041 case 55: /* /STRONG */ |
3922 | 1042 NEW_BIT (NEW_TEXT_BIT); |
1043 if (bold) | |
1044 bold--; | |
1045 break; | |
1046 case 5: /* I */ | |
1047 case 6: /* ITALIC */ | |
5101 | 1048 case 52: /* EM */ |
3922 | 1049 NEW_BIT (NEW_TEXT_BIT); |
1050 italics++; | |
1051 break; | |
1052 case 7: /* /I */ | |
1053 case 8: /* /ITALIC */ | |
5101 | 1054 case 53: /* /EM */ |
3922 | 1055 NEW_BIT (NEW_TEXT_BIT); |
1056 if (italics) | |
1057 italics--; | |
1058 break; | |
1059 case 9: /* U */ | |
1060 case 10: /* UNDERLINE */ | |
1061 NEW_BIT (NEW_TEXT_BIT); | |
1062 underline++; | |
1063 break; | |
1064 case 11: /* /U */ | |
1065 case 12: /* /UNDERLINE */ | |
1066 NEW_BIT (NEW_TEXT_BIT); | |
1067 if (underline) | |
1068 underline--; | |
1069 break; | |
1070 case 13: /* S */ | |
1071 case 14: /* STRIKE */ | |
1072 NEW_BIT (NEW_TEXT_BIT); | |
1073 strike++; | |
1074 break; | |
1075 case 15: /* /S */ | |
1076 case 16: /* /STRIKE */ | |
1077 NEW_BIT (NEW_TEXT_BIT); | |
1078 if (strike) | |
1079 strike--; | |
1080 break; | |
1081 case 17: /* SUB */ | |
1082 NEW_BIT (NEW_TEXT_BIT); | |
1083 sub++; | |
1084 break; | |
1085 case 18: /* /SUB */ | |
1086 NEW_BIT (NEW_TEXT_BIT); | |
1087 if (sub) | |
1088 sub--; | |
1089 break; | |
1090 case 19: /* SUP */ | |
1091 NEW_BIT (NEW_TEXT_BIT); | |
1092 sup++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1093 break; |
3922 | 1094 case 20: /* /SUP */ |
1095 NEW_BIT (NEW_TEXT_BIT); | |
1096 if (sup) | |
1097 sup--; | |
1098 break; | |
1099 case 21: /* PRE */ | |
1100 NEW_BIT (NEW_TEXT_BIT); | |
1101 pre++; | |
1102 break; | |
1103 case 22: /* /PRE */ | |
1104 NEW_BIT (NEW_TEXT_BIT); | |
1105 if (pre) | |
1106 pre--; | |
1107 break; | |
1108 case 23: /* TITLE */ | |
1109 NEW_BIT (NEW_TEXT_BIT); | |
1110 title++; | |
1111 break; | |
1112 case 24: /* /TITLE */ | |
1113 if (title) { | |
1114 if (options & GTK_IMHTML_NO_TITLE) { | |
1115 wpos = 0; | |
1116 ws [wpos] = '\0'; | |
1117 } | |
1118 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1119 } |
3922 | 1120 break; |
1121 case 25: /* BR */ | |
5174 | 1122 case 58: /* BR/ */ |
3922 | 1123 ws[wpos] = '\n'; |
1124 wpos++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1125 NEW_BIT (NEW_TEXT_BIT); |
3922 | 1126 break; |
1127 case 26: /* HR */ | |
1128 case 42: /* HR (opt) */ | |
1129 ws[wpos++] = '\n'; | |
5967 | 1130 scalable = gtk_imhtml_hr_new(); |
4895 | 1131 NEW_BIT(NEW_SCALABLE_BIT); |
4343 | 1132 ws[wpos++] = '\n'; |
3922 | 1133 break; |
1134 case 27: /* /FONT */ | |
1135 if (fonts) { | |
5967 | 1136 GtkIMHtmlFontDetail *font = fonts->data; |
3922 | 1137 NEW_BIT (NEW_TEXT_BIT); |
1138 fonts = g_slist_remove (fonts, font); | |
1139 if (font->face) | |
1140 g_free (font->face); | |
1141 if (font->fore) | |
1142 g_free (font->fore); | |
1143 if (font->back) | |
1144 g_free (font->back); | |
4032 | 1145 if (font->sml) |
1146 g_free (font->sml); | |
3922 | 1147 g_free (font); |
1148 } | |
1149 break; | |
1150 case 28: /* /A */ | |
1151 if (url) { | |
1152 NEW_BIT(NEW_TEXT_BIT); | |
1153 g_free(url); | |
1154 url = NULL; | |
2993 | 1155 break; |
1156 } | |
3922 | 1157 case 29: /* P */ |
1158 case 30: /* /P */ | |
1159 case 31: /* H3 */ | |
1160 case 32: /* /H3 */ | |
1161 case 33: /* HTML */ | |
1162 case 34: /* /HTML */ | |
1163 case 35: /* BODY */ | |
1164 case 36: /* /BODY */ | |
1165 case 37: /* FONT */ | |
1166 case 38: /* HEAD */ | |
1167 case 39: /* /HEAD */ | |
1168 break; | |
1169 case 40: /* BINARY */ | |
4895 | 1170 NEW_BIT (NEW_TEXT_BIT); |
4997 | 1171 while (pos < len && g_ascii_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) { |
1172 c++; | |
1173 pos++; | |
1174 } | |
1175 c = c - tlen; /* Because it will add this later */ | |
4895 | 1176 break; |
3922 | 1177 case 41: /* /BINARY */ |
1178 break; | |
1179 case 43: /* FONT (opt) */ | |
1180 { | |
4032 | 1181 gchar *color, *back, *face, *size, *sml; |
5967 | 1182 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 1183 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
1184 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
1185 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
1186 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 1187 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
1188 if (!(color || back || face || size || sml)) | |
3922 | 1189 break; |
1190 | |
1191 NEW_BIT (NEW_TEXT_BIT); | |
1192 | |
5967 | 1193 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 1194 if (fonts) |
1195 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1196 |
3922 | 1197 if (color && !(options & GTK_IMHTML_NO_COLOURS)) |
1198 font->fore = color; | |
1199 else if (oldfont && oldfont->fore) | |
1200 font->fore = g_strdup(oldfont->fore); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1201 |
3922 | 1202 if (back && !(options & GTK_IMHTML_NO_COLOURS)) |
1203 font->back = back; | |
1204 else if (oldfont && oldfont->back) | |
1205 font->back = g_strdup(oldfont->back); | |
1206 | |
1207 if (face && !(options & GTK_IMHTML_NO_FONTS)) | |
1208 font->face = face; | |
1209 else if (oldfont && oldfont->face) | |
1210 font->face = g_strdup(oldfont->face); | |
4629 | 1211 if (font->face && (atoi(font->face) > 100)) { |
1212 g_free(font->face); | |
1213 font->face = g_strdup("100"); | |
1214 } | |
4032 | 1215 |
1216 if (sml) | |
1217 font->sml = sml; | |
1218 else if (oldfont && oldfont->sml) | |
1219 font->sml = g_strdup(oldfont->sml); | |
1220 | |
3922 | 1221 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
1222 if (*size == '+') { | |
1223 sscanf (size + 1, "%hd", &font->size); | |
1224 font->size += 3; | |
1225 } else if (*size == '-') { | |
1226 sscanf (size + 1, "%hd", &font->size); | |
1227 font->size = MAX (0, 3 - font->size); | |
1228 } else if (isdigit (*size)) { | |
1229 sscanf (size, "%hd", &font->size); | |
1230 } | |
6042 | 1231 if (font->size > 100) |
1232 font->size = 100; | |
3922 | 1233 } else if (oldfont) |
1234 font->size = oldfont->size; | |
1235 g_free(size); | |
1236 fonts = g_slist_prepend (fonts, font); | |
1237 } | |
1238 break; | |
1239 case 44: /* BODY (opt) */ | |
1240 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
1241 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
1242 if (bgcolor) { | |
1243 NEW_BIT(NEW_TEXT_BIT); | |
1244 if (bg) | |
1245 g_free(bg); | |
1246 bg = bgcolor; | |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
1247 } |
1428 | 1248 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1249 break; |
3922 | 1250 case 45: /* A (opt) */ |
1251 { | |
1252 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
1253 if (href) { | |
1254 NEW_BIT (NEW_TEXT_BIT); | |
1255 if (url) | |
1256 g_free (url); | |
1257 url = href; | |
1258 } | |
2993 | 1259 } |
3922 | 1260 break; |
4895 | 1261 case 46: /* IMG (opt) */ |
1262 { | |
1263 gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); | |
1264 gchar *id = gtk_imhtml_get_html_opt (tag, "ID="); | |
1265 gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE="); | |
1266 gint im_len = datasize?atoi(datasize):0; | |
1267 | |
1268 if (src && id && im_len && im_len <= len - pos) { | |
1269 /* This is an embedded IM image, or is it? */ | |
1270 char *tmp = NULL; | |
1271 const char *alltext; | |
1272 guchar *imagedata = NULL; | |
1273 | |
1274 GdkPixbufLoader *load; | |
1275 GdkPixbuf *imagepb = NULL; | |
1276 GError *error = NULL; | |
1277 | |
1278 tmp = g_strdup_printf("<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize); | |
1279 alltext = strstr(c, tmp); | |
1280 imagedata = g_memdup(alltext + strlen(tmp), im_len); | |
1281 | |
1282 g_free(tmp); | |
1283 | |
1284 load = gdk_pixbuf_loader_new(); | |
1285 if (!gdk_pixbuf_loader_write(load, imagedata, im_len, &error)){ | |
1286 fprintf(stderr, "IM Image corrupted or unreadable.: %s\n", error->message); | |
1287 } else { | |
1288 imagepb = gdk_pixbuf_loader_get_pixbuf(load); | |
1289 if (imagepb) { | |
5967 | 1290 scalable = gtk_imhtml_image_new(imagepb, g_strdup(src)); |
4895 | 1291 NEW_BIT(NEW_SCALABLE_BIT); |
5012 | 1292 g_object_unref(imagepb); |
4895 | 1293 } |
1294 } | |
1295 | |
1296 gdk_pixbuf_loader_close(load, NULL); | |
1297 | |
1298 | |
1299 g_free(imagedata); | |
1300 g_free(id); | |
1301 g_free(datasize); | |
1302 g_free(src); | |
1303 | |
1304 break; | |
1305 } | |
1306 g_free(id); | |
1307 g_free(datasize); | |
1308 g_free(src); | |
1309 } | |
3922 | 1310 case 47: /* P (opt) */ |
1311 case 48: /* H3 (opt) */ | |
5093 | 1312 case 49: /* HTML (opt) */ |
5101 | 1313 case 50: /* CITE */ |
1314 case 51: /* /CITE */ | |
5104 | 1315 case 56: /* SPAN */ |
1316 case 57: /* /SPAN */ | |
2993 | 1317 break; |
5174 | 1318 case 59: /* comment */ |
3922 | 1319 NEW_BIT (NEW_TEXT_BIT); |
6056 | 1320 if (imhtml->show_comments) |
1321 wpos = g_snprintf (ws, len, "%s", tag); | |
3922 | 1322 NEW_BIT (NEW_COMMENT_BIT); |
1323 break; | |
1324 default: | |
1325 break; | |
2993 | 1326 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1327 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1328 pos += tlen; |
4138 | 1329 if(tag) |
1330 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1331 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1332 ws [wpos++] = amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1333 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1334 pos += tlen; |
1428 | 1335 } else if (*c == '\n') { |
1336 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 1337 ws[wpos] = '\n'; |
1338 wpos++; | |
1428 | 1339 NEW_BIT (NEW_TEXT_BIT); |
1340 } | |
1341 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1342 pos++; |
4253 | 1343 } else if (imhtml->show_smileys && (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen))) { |
5967 | 1344 GtkIMHtmlFontDetail *fd; |
4032 | 1345 gchar *sml = NULL; |
1346 if (fonts) { | |
1347 fd = fonts->data; | |
1348 sml = fd->sml; | |
1349 } | |
1350 NEW_BIT (NEW_TEXT_BIT); | |
1351 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | |
4263 | 1352 gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gtk_smiley_tree_image (imhtml, sml, ws)); |
4032 | 1353 c += smilelen; |
1354 pos += smilelen; | |
1355 wpos = 0; | |
1356 ws[0] = 0; | |
1357 } else if (*c) { | |
1428 | 1358 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1359 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1360 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1361 break; |
1428 | 1362 } |
1363 } | |
3922 | 1364 |
1365 NEW_BIT(NEW_TEXT_BIT); | |
1428 | 1366 if (url) { |
1367 g_free (url); | |
3922 | 1368 if (str) |
1369 str = g_string_append (str, "</A>"); | |
1428 | 1370 } |
3922 | 1371 |
4032 | 1372 while (fonts) { |
5967 | 1373 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 1374 fonts = g_slist_remove (fonts, font); |
1375 if (font->face) | |
1376 g_free (font->face); | |
1377 if (font->fore) | |
1378 g_free (font->fore); | |
1379 if (font->back) | |
1380 g_free (font->back); | |
1381 if (font->sml) | |
1382 g_free (font->sml); | |
1383 g_free (font); | |
1384 if (str) | |
1385 str = g_string_append (str, "</FONT>"); | |
1386 } | |
1387 | |
3922 | 1388 if (str) { |
1428 | 1389 while (bold) { |
3922 | 1390 str = g_string_append (str, "</B>"); |
1428 | 1391 bold--; |
1392 } | |
1393 while (italics) { | |
3922 | 1394 str = g_string_append (str, "</I>"); |
1428 | 1395 italics--; |
1396 } | |
1397 while (underline) { | |
3922 | 1398 str = g_string_append (str, "</U>"); |
1428 | 1399 underline--; |
1400 } | |
1401 while (strike) { | |
3922 | 1402 str = g_string_append (str, "</S>"); |
1428 | 1403 strike--; |
1404 } | |
1405 while (sub) { | |
3922 | 1406 str = g_string_append (str, "</SUB>"); |
1428 | 1407 sub--; |
1408 } | |
1409 while (sup) { | |
3922 | 1410 str = g_string_append (str, "</SUP>"); |
1428 | 1411 sup--; |
1412 } | |
1413 while (title) { | |
3922 | 1414 str = g_string_append (str, "</TITLE>"); |
1428 | 1415 title--; |
1416 } | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1417 while (pre) { |
3922 | 1418 str = g_string_append (str, "</PRE>"); |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1419 pre--; |
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1420 } |
1428 | 1421 } |
4032 | 1422 g_free (ws); |
4630 | 1423 if(bg) |
1424 g_free(bg); | |
4032 | 1425 if (!(options & GTK_IMHTML_NO_SCROLL)) |
1426 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
1427 0, TRUE, 0.0, 1.0); | |
3922 | 1428 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
1429 return str; | |
1430 } | |
1431 | |
4892 | 1432 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
1433 { | |
4288 | 1434 g_hash_table_destroy(imhtml->smiley_data); |
1435 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 1436 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1437 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 1438 imhtml->default_smilies = gtk_smiley_tree_new(); |
1439 } | |
3922 | 1440 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
4253 | 1441 gboolean show) |
1442 { | |
1443 imhtml->show_smileys = show; | |
1444 } | |
3922 | 1445 |
1446 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
4253 | 1447 gboolean show) |
1448 { | |
6056 | 1449 imhtml->show_comments = show; |
4253 | 1450 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1451 |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1452 void |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1453 gtk_imhtml_clear (GtkIMHtml *imhtml) |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1454 { |
3922 | 1455 GtkTextIter start, end; |
2993 | 1456 |
3922 | 1457 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
1458 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
1459 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1460 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
1461 |
4046 | 1462 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
1463 { | |
5282 | 1464 GdkRectangle rect; |
1465 GtkTextIter iter; | |
4046 | 1466 |
5282 | 1467 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
1468 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
1469 rect.y - rect.height); | |
1470 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
1471 | |
4046 | 1472 } |
5282 | 1473 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
1474 { | |
1475 GdkRectangle rect; | |
1476 GtkTextIter iter; | |
1477 | |
1478 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1479 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
1480 rect.y + rect.height); | |
1481 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
1482 } | |
4735 | 1483 |
5967 | 1484 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
1485 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, gchar *filename) | |
4735 | 1486 { |
5967 | 1487 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 1488 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 1489 |
5967 | 1490 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
1491 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
1492 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 1493 |
1494 im_image->pixbuf = img; | |
5012 | 1495 im_image->image = image; |
4895 | 1496 im_image->width = gdk_pixbuf_get_width(img); |
1497 im_image->height = gdk_pixbuf_get_height(img); | |
1498 im_image->mark = NULL; | |
5012 | 1499 im_image->filename = filename; |
4895 | 1500 |
5046 | 1501 g_object_ref(img); |
4895 | 1502 return GTK_IMHTML_SCALABLE(im_image); |
1503 } | |
1504 | |
5967 | 1505 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 1506 { |
5967 | 1507 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 1508 |
1509 if(image->width > width || image->height > height){ | |
1510 GdkPixbuf *new_image = NULL; | |
1511 float factor; | |
1512 int new_width = image->width, new_height = image->height; | |
1513 | |
1514 if(image->width > width){ | |
1515 factor = (float)(width)/image->width; | |
1516 new_width = width; | |
1517 new_height = image->height * factor; | |
1518 } | |
1519 if(new_height > height){ | |
1520 factor = (float)(height)/new_height; | |
1521 new_height = height; | |
1522 new_width = new_width * factor; | |
1523 } | |
1524 | |
5046 | 1525 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 1526 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 1527 g_object_unref(G_OBJECT(new_image)); |
1528 } | |
1529 } | |
1530 | |
5012 | 1531 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
1532 { | |
1533 const gchar *filename = gtk_file_selection_get_filename(sel); | |
5967 | 1534 gchar *dirname; |
1535 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
5012 | 1536 gchar *type = NULL; |
5019 | 1537 GError *error = NULL; |
5015 | 1538 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 1539 GSList *formats = gdk_pixbuf_get_formats(); |
5959 | 1540 #endif |
5012 | 1541 |
5967 | 1542 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
1543 /* append a / if needed */ | |
1544 if (filename[strlen(filename) - 1] != '/') { | |
1545 dirname = g_strconcat(filename, "/", NULL); | |
1546 } else { | |
1547 dirname = g_strdup(filename); | |
1548 } | |
1549 gtk_file_selection_set_filename(sel, dirname); | |
1550 g_free(dirname); | |
5959 | 1551 return; |
5967 | 1552 } |
5959 | 1553 |
1554 #if GTK_CHECK_VERSION(2,2,0) | |
5012 | 1555 while(formats){ |
1556 GdkPixbufFormat *format = formats->data; | |
1557 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
1558 gpointer p = extensions; | |
1559 | |
1560 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
1561 gchar *fmt_ext = extensions[0]; | |
1562 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
1563 | |
1564 if(!strcmp(fmt_ext, file_ext)){ | |
1565 type = gdk_pixbuf_format_get_name(format); | |
1566 break; | |
1567 } | |
1568 | |
1569 extensions++; | |
1570 } | |
1571 | |
1572 g_strfreev(p); | |
1573 | |
1574 if(type) | |
1575 break; | |
1576 | |
1577 formats = formats->next; | |
1578 } | |
1579 | |
5020 | 1580 g_slist_free(formats); |
1581 #else | |
1582 /* this is really ugly code, but I think it will work */ | |
1583 char *basename = g_path_get_basename(filename); | |
1584 char *ext = strrchr(basename, '.'); | |
1585 | |
1586 if(ext) { | |
1587 ext++; | |
1588 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
1589 type = g_strdup("jpeg"); | |
1590 else if(!g_ascii_strcasecmp(ext, "png")) | |
1591 type = g_strdup("png"); | |
1592 } | |
1593 | |
1594 g_free(basename); | |
1595 #endif | |
1596 | |
5012 | 1597 /* If I can't find a valid type, I will just tell the user about it and then assume |
1598 it's a png */ | |
1599 if(!type){ | |
1600 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
5967 | 1601 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
5012 | 1602 type = g_strdup("png"); |
1603 } | |
1604 | |
5046 | 1605 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 1606 |
1607 if(error){ | |
1608 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
1609 _("Error saving image: %s"), error->message); | |
1610 g_error_free(error); | |
1611 } | |
1612 | |
1613 g_free(type); | |
1614 } | |
1615 | |
5967 | 1616 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
5012 | 1617 { |
5967 | 1618 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
5012 | 1619 |
1620 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
5967 | 1621 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
5012 | 1622 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
1623 G_CALLBACK(write_img_to_file), sel); | |
1624 | |
1625 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
1626 G_CALLBACK(gtk_widget_destroy), sel); | |
1627 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
1628 G_CALLBACK(gtk_widget_destroy), sel); | |
1629 | |
1630 gtk_widget_show(sel); | |
1631 } | |
1632 | |
5967 | 1633 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 1634 { |
1635 GdkEventButton *event_button = (GdkEventButton *) event; | |
1636 | |
1637 if (event->type == GDK_BUTTON_RELEASE) { | |
1638 if(event_button->button == 3) { | |
1639 GtkWidget *img, *item, *menu; | |
1640 gchar *text = g_strdup_printf(_("_Save Image...")); | |
1641 menu = gtk_menu_new(); | |
1642 | |
1643 /* buttons and such */ | |
1644 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
1645 item = gtk_image_menu_item_new_with_mnemonic(text); | |
1646 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 1647 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 1648 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
1649 | |
1650 gtk_widget_show_all(menu); | |
1651 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
1652 event_button->button, event_button->time); | |
1653 | |
1654 g_free(text); | |
1655 return TRUE; | |
1656 } | |
1657 } | |
1658 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
1659 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1660 be caught by the regular GtkTextView menu */ | |
1661 else | |
1662 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1663 | |
1664 } | |
5967 | 1665 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
1666 { | |
1667 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
1668 | |
1669 g_object_unref(image->pixbuf); | |
1670 g_free(image->filename); | |
1671 g_free(scale); | |
1672 } | |
1673 | |
1674 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1675 { | |
1676 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
1677 GtkWidget *box = gtk_event_box_new(); | |
1678 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
1679 | |
1680 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
1681 | |
1682 gtk_widget_show(GTK_WIDGET(image->image)); | |
1683 gtk_widget_show(box); | |
1684 | |
1685 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
1686 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
1687 } | |
1688 | |
1689 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
1690 { | |
1691 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
1692 | |
1693 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
1694 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
1695 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
1696 | |
1697 hr->sep = gtk_hseparator_new(); | |
1698 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
1699 gtk_widget_show(hr->sep); | |
1700 | |
1701 return GTK_IMHTML_SCALABLE(hr); | |
1702 } | |
1703 | |
1704 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
1705 { | |
1706 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width, 2); | |
1707 } | |
1708 | |
1709 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1710 { | |
1711 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
1712 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
1713 | |
1714 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); | |
1715 } | |
1716 | |
1717 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
1718 { | |
1719 /* gtk_widget_destroy(((GtkIMHtmlHr *)scale)->sep); */ | |
1720 g_free(scale); | |
1721 } |