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