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