Mercurial > pidgin.yaz
annotate src/gtkimhtml.c @ 5105:4cfc49e31c2e
[gaim-migrate @ 5468]
David Brigada (jsi) writes:
" This patch changes GTK_WRAP_WORD to GTK_WRAP_WORD_CHAR
throughout the sources. That fixes a bug where long
single-word input into GtkTextViews and similar would
cause the textview to expand, causing the window to
expand. This fix depends on a patch to GTK+ that is in
current CVS but not yet released. To address the
backwards-compatibility issue, GTK_WRAP_WORD_CHAR is
#defined to GTK_WRAP_WORD when not defined by GTK+'s
header files.
The only problem I can forsee is binary compatibility;
if Gaim is compiled under a GTK+ CVS (or a future
release) environment, and then run under a GTK+ 2.2.1
or earlier environment, behavior is undefined; the text
area will probably not wrap at all. However, source
compatibility is maintained."
basically, gaim will start wrapping text in any version of gtk2 that supports it,
and should work exactly the same in any version that still has the bug.
many thanks to David for his hard work.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 11 Apr 2003 04:23:55 +0000 |
parents | a20a644e0da4 |
children | be43e51c523c |
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 | |
74 #define POINT_SIZE(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 | |
4419 | 300 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
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"); | |
733 | |
4793 | 734 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
735 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
736 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
737 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
738 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
739 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
740 } |
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 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
744 } |
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 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
747 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
748 const gchar *opt) |
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 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
751 gchar *e, *a; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
752 |
4793 | 753 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
754 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
755 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
756 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
757 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
758 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
759 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
760 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
761 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
762 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
763 |
4793 | 764 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
765 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
766 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
767 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
768 } |
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 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
771 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
772 while (*e && (*e != *(t - 1))) e++; |
2993 | 773 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
774 return NULL; |
2993 | 775 } else |
776 return g_strndup (a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
777 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
778 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
779 while (*e && !isspace ((gint) *e)) e++; |
2993 | 780 return g_strndup (a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
781 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
782 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
783 |
3922 | 784 |
785 | |
786 #define NEW_TEXT_BIT 0 | |
4343 | 787 #define NEW_COMMENT_BIT 2 |
4895 | 788 #define NEW_SCALABLE_BIT 1 |
3922 | 789 #define NEW_BIT(x) ws [wpos] = '\0'; \ |
790 mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \ | |
791 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \ | |
4895 | 792 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ |
3922 | 793 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \ |
794 gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \ | |
795 if (bold) \ | |
796 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \ | |
4895 | 797 if (italics) \ |
3922 | 798 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \ |
799 if (underline) \ | |
800 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \ | |
801 if (strike) \ | |
802 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \ | |
803 if (sub) \ | |
804 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \ | |
805 if (sup) \ | |
806 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \ | |
807 if (pre) \ | |
808 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &iter); \ | |
809 if (bg) { \ | |
810 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); \ | |
811 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
812 } \ | |
813 if (fonts) { \ | |
814 FontDetail *fd = fonts->data; \ | |
815 if (fd->fore) { \ | |
816 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \ | |
817 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
818 } \ | |
819 if (fd->back) { \ | |
820 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); \ | |
821 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
822 } \ | |
823 if (fd->face) { \ | |
824 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "font", fd->face, NULL); \ | |
825 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
826 } \ | |
827 if (fd->size) { \ | |
828 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \ | |
829 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
830 } \ | |
831 } \ | |
832 if (url) { \ | |
833 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \ | |
5012 | 834 g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), g_strdup(url)); \ |
3922 | 835 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ |
4735 | 836 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); \ |
837 g_object_set_data(G_OBJECT(texttag), "link_url", g_strdup(url)); \ | |
838 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \ | |
3922 | 839 } \ |
840 wpos = 0; \ | |
841 ws[0] = 0; \ | |
842 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4895 | 843 if (x == NEW_SCALABLE_BIT) { \ |
844 GdkRectangle rect; \ | |
845 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); \ | |
846 scalable->add_to(scalable, imhtml, &iter); \ | |
847 scalable->scale(scalable, rect.width, rect.height); \ | |
848 imhtml->scalables = g_list_append(imhtml->scalables, scalable); \ | |
849 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \ | |
4343 | 850 } \ |
3922 | 851 |
4895 | 852 |
853 | |
3922 | 854 GString* gtk_imhtml_append_text (GtkIMHtml *imhtml, |
855 const gchar *text, | |
856 gint len, | |
857 GtkIMHtmlOptions options) | |
1428 | 858 { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
859 gint pos = 0; |
3922 | 860 GString *str = NULL; |
861 GtkTextIter iter, siter; | |
862 GtkTextMark *mark, *mark2; | |
863 GtkTextTag *texttag; | |
864 gchar *ws; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
865 gchar *tag; |
3922 | 866 gchar *url = NULL; |
867 gchar *bg = NULL; | |
4032 | 868 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
869 gint type; |
3922 | 870 const gchar *c; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
871 gchar amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
872 |
1428 | 873 guint bold = 0, |
874 italics = 0, | |
875 underline = 0, | |
876 strike = 0, | |
877 sub = 0, | |
878 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
879 title = 0, |
3922 | 880 pre = 0; |
1428 | 881 |
3922 | 882 GSList *fonts = NULL; |
1428 | 883 |
4612 | 884 GdkRectangle rect; |
885 int y, height; | |
886 | |
4895 | 887 GtkIMHtmlScalable *scalable = NULL; |
888 | |
1428 | 889 g_return_val_if_fail (imhtml != NULL, NULL); |
890 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | |
891 g_return_val_if_fail (text != NULL, NULL); | |
3922 | 892 g_return_val_if_fail (len != 0, NULL); |
893 | |
894 c = text; | |
895 if (len == -1) | |
896 len = strlen(text); | |
897 ws = g_malloc(len + 1); | |
898 ws[0] = 0; | |
1428 | 899 |
900 if (options & GTK_IMHTML_RETURN_LOG) | |
3922 | 901 str = g_string_new(""); |
1428 | 902 |
3922 | 903 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); |
904 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
4612 | 905 |
906 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
907 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
908 | |
909 if(((y + height) - (rect.y + rect.height)) > height | |
910 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
911 options |= GTK_IMHTML_NO_SCROLL; | |
912 } | |
913 | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
914 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
915 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
916 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
917 pos++; |
3922 | 918 switch (type) |
919 { | |
920 case 1: /* B */ | |
921 case 2: /* BOLD */ | |
5101 | 922 case 54: /* STRONG */ |
3922 | 923 NEW_BIT (NEW_TEXT_BIT); |
924 bold++; | |
925 break; | |
926 case 3: /* /B */ | |
927 case 4: /* /BOLD */ | |
5101 | 928 case 55: /* /STRONG */ |
3922 | 929 NEW_BIT (NEW_TEXT_BIT); |
930 if (bold) | |
931 bold--; | |
932 break; | |
933 case 5: /* I */ | |
934 case 6: /* ITALIC */ | |
5101 | 935 case 52: /* EM */ |
3922 | 936 NEW_BIT (NEW_TEXT_BIT); |
937 italics++; | |
938 break; | |
939 case 7: /* /I */ | |
940 case 8: /* /ITALIC */ | |
5101 | 941 case 53: /* /EM */ |
3922 | 942 NEW_BIT (NEW_TEXT_BIT); |
943 if (italics) | |
944 italics--; | |
945 break; | |
946 case 9: /* U */ | |
947 case 10: /* UNDERLINE */ | |
948 NEW_BIT (NEW_TEXT_BIT); | |
949 underline++; | |
950 break; | |
951 case 11: /* /U */ | |
952 case 12: /* /UNDERLINE */ | |
953 NEW_BIT (NEW_TEXT_BIT); | |
954 if (underline) | |
955 underline--; | |
956 break; | |
957 case 13: /* S */ | |
958 case 14: /* STRIKE */ | |
959 NEW_BIT (NEW_TEXT_BIT); | |
960 strike++; | |
961 break; | |
962 case 15: /* /S */ | |
963 case 16: /* /STRIKE */ | |
964 NEW_BIT (NEW_TEXT_BIT); | |
965 if (strike) | |
966 strike--; | |
967 break; | |
968 case 17: /* SUB */ | |
969 NEW_BIT (NEW_TEXT_BIT); | |
970 sub++; | |
971 break; | |
972 case 18: /* /SUB */ | |
973 NEW_BIT (NEW_TEXT_BIT); | |
974 if (sub) | |
975 sub--; | |
976 break; | |
977 case 19: /* SUP */ | |
978 NEW_BIT (NEW_TEXT_BIT); | |
979 sup++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
980 break; |
3922 | 981 case 20: /* /SUP */ |
982 NEW_BIT (NEW_TEXT_BIT); | |
983 if (sup) | |
984 sup--; | |
985 break; | |
986 case 21: /* PRE */ | |
987 NEW_BIT (NEW_TEXT_BIT); | |
988 pre++; | |
989 break; | |
990 case 22: /* /PRE */ | |
991 NEW_BIT (NEW_TEXT_BIT); | |
992 if (pre) | |
993 pre--; | |
994 break; | |
995 case 23: /* TITLE */ | |
996 NEW_BIT (NEW_TEXT_BIT); | |
997 title++; | |
998 break; | |
999 case 24: /* /TITLE */ | |
1000 if (title) { | |
1001 if (options & GTK_IMHTML_NO_TITLE) { | |
1002 wpos = 0; | |
1003 ws [wpos] = '\0'; | |
1004 } | |
1005 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1006 } |
3922 | 1007 break; |
1008 case 25: /* BR */ | |
1009 ws[wpos] = '\n'; | |
1010 wpos++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1011 NEW_BIT (NEW_TEXT_BIT); |
3922 | 1012 break; |
1013 case 26: /* HR */ | |
1014 case 42: /* HR (opt) */ | |
1015 ws[wpos++] = '\n'; | |
4895 | 1016 scalable = gaim_hr_new(); |
1017 NEW_BIT(NEW_SCALABLE_BIT); | |
4343 | 1018 ws[wpos++] = '\n'; |
3922 | 1019 break; |
1020 case 27: /* /FONT */ | |
1021 if (fonts) { | |
1022 FontDetail *font = fonts->data; | |
1023 NEW_BIT (NEW_TEXT_BIT); | |
1024 fonts = g_slist_remove (fonts, font); | |
1025 if (font->face) | |
1026 g_free (font->face); | |
1027 if (font->fore) | |
1028 g_free (font->fore); | |
1029 if (font->back) | |
1030 g_free (font->back); | |
4032 | 1031 if (font->sml) |
1032 g_free (font->sml); | |
3922 | 1033 g_free (font); |
1034 } | |
1035 break; | |
1036 case 28: /* /A */ | |
1037 if (url) { | |
1038 NEW_BIT(NEW_TEXT_BIT); | |
1039 g_free(url); | |
1040 url = NULL; | |
2993 | 1041 break; |
1042 } | |
3922 | 1043 case 29: /* P */ |
1044 case 30: /* /P */ | |
1045 case 31: /* H3 */ | |
1046 case 32: /* /H3 */ | |
1047 case 33: /* HTML */ | |
1048 case 34: /* /HTML */ | |
1049 case 35: /* BODY */ | |
1050 case 36: /* /BODY */ | |
1051 case 37: /* FONT */ | |
1052 case 38: /* HEAD */ | |
1053 case 39: /* /HEAD */ | |
1054 break; | |
1055 case 40: /* BINARY */ | |
4895 | 1056 NEW_BIT (NEW_TEXT_BIT); |
4997 | 1057 while (pos < len && g_ascii_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) { |
1058 c++; | |
1059 pos++; | |
1060 } | |
1061 c = c - tlen; /* Because it will add this later */ | |
4895 | 1062 break; |
3922 | 1063 case 41: /* /BINARY */ |
1064 break; | |
1065 case 43: /* FONT (opt) */ | |
1066 { | |
4032 | 1067 gchar *color, *back, *face, *size, *sml; |
3922 | 1068 FontDetail *font, *oldfont = NULL; |
1069 color = gtk_imhtml_get_html_opt (tag, "COLOR="); | |
1070 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
1071 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
1072 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 1073 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
1074 if (!(color || back || face || size || sml)) | |
3922 | 1075 break; |
1076 | |
1077 NEW_BIT (NEW_TEXT_BIT); | |
1078 | |
1079 font = g_new0 (FontDetail, 1); | |
1080 if (fonts) | |
1081 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1082 |
3922 | 1083 if (color && !(options & GTK_IMHTML_NO_COLOURS)) |
1084 font->fore = color; | |
1085 else if (oldfont && oldfont->fore) | |
1086 font->fore = g_strdup(oldfont->fore); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1087 |
3922 | 1088 if (back && !(options & GTK_IMHTML_NO_COLOURS)) |
1089 font->back = back; | |
1090 else if (oldfont && oldfont->back) | |
1091 font->back = g_strdup(oldfont->back); | |
1092 | |
1093 if (face && !(options & GTK_IMHTML_NO_FONTS)) | |
1094 font->face = face; | |
1095 else if (oldfont && oldfont->face) | |
1096 font->face = g_strdup(oldfont->face); | |
4629 | 1097 if (font->face && (atoi(font->face) > 100)) { |
1098 g_free(font->face); | |
1099 font->face = g_strdup("100"); | |
1100 } | |
4032 | 1101 |
1102 if (sml) | |
1103 font->sml = sml; | |
1104 else if (oldfont && oldfont->sml) | |
1105 font->sml = g_strdup(oldfont->sml); | |
1106 | |
3922 | 1107 if (size && !(options & GTK_IMHTML_NO_SIZES)) { |
1108 if (*size == '+') { | |
1109 sscanf (size + 1, "%hd", &font->size); | |
1110 font->size += 3; | |
1111 } else if (*size == '-') { | |
1112 sscanf (size + 1, "%hd", &font->size); | |
1113 font->size = MAX (0, 3 - font->size); | |
1114 } else if (isdigit (*size)) { | |
1115 sscanf (size, "%hd", &font->size); | |
1116 } | |
1117 } else if (oldfont) | |
1118 font->size = oldfont->size; | |
1119 g_free(size); | |
1120 fonts = g_slist_prepend (fonts, font); | |
1121 } | |
1122 break; | |
1123 case 44: /* BODY (opt) */ | |
1124 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
1125 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
1126 if (bgcolor) { | |
1127 NEW_BIT(NEW_TEXT_BIT); | |
1128 if (bg) | |
1129 g_free(bg); | |
1130 bg = bgcolor; | |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
1131 } |
1428 | 1132 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1133 break; |
3922 | 1134 case 45: /* A (opt) */ |
1135 { | |
1136 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
1137 if (href) { | |
1138 NEW_BIT (NEW_TEXT_BIT); | |
1139 if (url) | |
1140 g_free (url); | |
1141 url = href; | |
1142 } | |
2993 | 1143 } |
3922 | 1144 break; |
4895 | 1145 case 46: /* IMG (opt) */ |
1146 { | |
1147 gchar *src = gtk_imhtml_get_html_opt (tag, "SRC="); | |
1148 gchar *id = gtk_imhtml_get_html_opt (tag, "ID="); | |
1149 gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE="); | |
1150 gint im_len = datasize?atoi(datasize):0; | |
1151 | |
1152 if (src && id && im_len && im_len <= len - pos) { | |
1153 /* This is an embedded IM image, or is it? */ | |
1154 char *tmp = NULL; | |
1155 const char *alltext; | |
1156 guchar *imagedata = NULL; | |
1157 | |
1158 GdkPixbufLoader *load; | |
1159 GdkPixbuf *imagepb = NULL; | |
1160 GError *error = NULL; | |
1161 | |
1162 tmp = g_strdup_printf("<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize); | |
1163 alltext = strstr(c, tmp); | |
1164 imagedata = g_memdup(alltext + strlen(tmp), im_len); | |
1165 | |
1166 g_free(tmp); | |
1167 | |
1168 load = gdk_pixbuf_loader_new(); | |
1169 if (!gdk_pixbuf_loader_write(load, imagedata, im_len, &error)){ | |
1170 fprintf(stderr, "IM Image corrupted or unreadable.: %s\n", error->message); | |
1171 } else { | |
1172 imagepb = gdk_pixbuf_loader_get_pixbuf(load); | |
1173 if (imagepb) { | |
5012 | 1174 scalable = gaim_im_image_new(imagepb, g_strdup(src)); |
4895 | 1175 NEW_BIT(NEW_SCALABLE_BIT); |
5012 | 1176 g_object_unref(imagepb); |
4895 | 1177 } |
1178 } | |
1179 | |
1180 gdk_pixbuf_loader_close(load, NULL); | |
1181 | |
1182 | |
1183 g_free(imagedata); | |
1184 g_free(id); | |
1185 g_free(datasize); | |
1186 g_free(src); | |
1187 | |
1188 break; | |
1189 } | |
1190 g_free(id); | |
1191 g_free(datasize); | |
1192 g_free(src); | |
1193 } | |
3922 | 1194 case 47: /* P (opt) */ |
1195 case 48: /* H3 (opt) */ | |
5093 | 1196 case 49: /* HTML (opt) */ |
5101 | 1197 case 50: /* CITE */ |
1198 case 51: /* /CITE */ | |
5104 | 1199 case 56: /* SPAN */ |
1200 case 57: /* /SPAN */ | |
2993 | 1201 break; |
5104 | 1202 case 58: /* comment */ |
3922 | 1203 NEW_BIT (NEW_TEXT_BIT); |
4253 | 1204 if (imhtml->show_comments) |
1205 wpos = g_snprintf (ws, len, "%s", tag); | |
3922 | 1206 NEW_BIT (NEW_COMMENT_BIT); |
1207 break; | |
1208 default: | |
1209 break; | |
2993 | 1210 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1211 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1212 pos += tlen; |
4138 | 1213 if(tag) |
1214 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1215 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1216 ws [wpos++] = amp; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1217 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1218 pos += tlen; |
1428 | 1219 } else if (*c == '\n') { |
1220 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 1221 ws[wpos] = '\n'; |
1222 wpos++; | |
1428 | 1223 NEW_BIT (NEW_TEXT_BIT); |
1224 } | |
1225 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1226 pos++; |
4253 | 1227 } else if (imhtml->show_smileys && (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen))) { |
4032 | 1228 FontDetail *fd; |
1229 gchar *sml = NULL; | |
1230 if (fonts) { | |
1231 fd = fonts->data; | |
1232 sml = fd->sml; | |
1233 } | |
1234 NEW_BIT (NEW_TEXT_BIT); | |
1235 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | |
4263 | 1236 gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gtk_smiley_tree_image (imhtml, sml, ws)); |
4032 | 1237 c += smilelen; |
1238 pos += smilelen; | |
1239 wpos = 0; | |
1240 ws[0] = 0; | |
1241 } else if (*c) { | |
1428 | 1242 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1243 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1244 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1245 break; |
1428 | 1246 } |
1247 } | |
3922 | 1248 |
1249 NEW_BIT(NEW_TEXT_BIT); | |
1428 | 1250 if (url) { |
1251 g_free (url); | |
3922 | 1252 if (str) |
1253 str = g_string_append (str, "</A>"); | |
1428 | 1254 } |
3922 | 1255 |
4032 | 1256 while (fonts) { |
1257 FontDetail *font = fonts->data; | |
1258 fonts = g_slist_remove (fonts, font); | |
1259 if (font->face) | |
1260 g_free (font->face); | |
1261 if (font->fore) | |
1262 g_free (font->fore); | |
1263 if (font->back) | |
1264 g_free (font->back); | |
1265 if (font->sml) | |
1266 g_free (font->sml); | |
1267 g_free (font); | |
1268 if (str) | |
1269 str = g_string_append (str, "</FONT>"); | |
1270 } | |
1271 | |
3922 | 1272 if (str) { |
1428 | 1273 while (bold) { |
3922 | 1274 str = g_string_append (str, "</B>"); |
1428 | 1275 bold--; |
1276 } | |
1277 while (italics) { | |
3922 | 1278 str = g_string_append (str, "</I>"); |
1428 | 1279 italics--; |
1280 } | |
1281 while (underline) { | |
3922 | 1282 str = g_string_append (str, "</U>"); |
1428 | 1283 underline--; |
1284 } | |
1285 while (strike) { | |
3922 | 1286 str = g_string_append (str, "</S>"); |
1428 | 1287 strike--; |
1288 } | |
1289 while (sub) { | |
3922 | 1290 str = g_string_append (str, "</SUB>"); |
1428 | 1291 sub--; |
1292 } | |
1293 while (sup) { | |
3922 | 1294 str = g_string_append (str, "</SUP>"); |
1428 | 1295 sup--; |
1296 } | |
1297 while (title) { | |
3922 | 1298 str = g_string_append (str, "</TITLE>"); |
1428 | 1299 title--; |
1300 } | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1301 while (pre) { |
3922 | 1302 str = g_string_append (str, "</PRE>"); |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1303 pre--; |
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1304 } |
1428 | 1305 } |
4032 | 1306 g_free (ws); |
4630 | 1307 if(bg) |
1308 g_free(bg); | |
4032 | 1309 if (!(options & GTK_IMHTML_NO_SCROLL)) |
1310 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
1311 0, TRUE, 0.0, 1.0); | |
3922 | 1312 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); |
1313 return str; | |
1314 } | |
1315 | |
4892 | 1316 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
1317 { | |
4288 | 1318 g_hash_table_destroy(imhtml->smiley_data); |
1319 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 1320 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1321 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 1322 imhtml->default_smilies = gtk_smiley_tree_new(); |
1323 } | |
3922 | 1324 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
4253 | 1325 gboolean show) |
1326 { | |
1327 imhtml->show_smileys = show; | |
1328 } | |
3922 | 1329 |
1330 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
4253 | 1331 gboolean show) |
1332 { | |
1333 imhtml->show_comments = show; | |
1334 } | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1335 |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1336 void |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1337 gtk_imhtml_clear (GtkIMHtml *imhtml) |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1338 { |
3922 | 1339 GtkTextIter start, end; |
2993 | 1340 |
3922 | 1341 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
1342 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
1343 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
1344 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
1345 |
4046 | 1346 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
1347 { | |
1348 | |
1349 } | |
3922 | 1350 void gtk_imhtml_page_down (GtkIMHtml *imhtml){} |
4735 | 1351 |
1352 static gint | |
1353 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
1354 { | |
1355 PangoLayout *layout; | |
1356 | |
1357 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
1358 | |
1359 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
1360 | |
1361 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, | |
1362 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, | |
1363 "tooltip", 0, 0, -1, -1); | |
1364 | |
1365 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
1366 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
1367 | |
4764 | 1368 g_object_unref(layout); |
4735 | 1369 return FALSE; |
1370 } | |
1371 | |
1372 static gint | |
1373 gtk_imhtml_tip (gpointer data) | |
1374 { | |
1375 GtkIMHtml *imhtml = data; | |
1376 PangoFontMetrics *font; | |
1377 PangoLayout *layout; | |
1378 | |
1379 gint gap, x, y, h, w, scr_w, baseline_skip; | |
1380 | |
1381 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
1382 | |
1383 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
1384 imhtml->tip_timer = 0; | |
1385 return FALSE; | |
1386 } | |
1387 | |
1388 if (imhtml->tip_window){ | |
1389 gtk_widget_destroy (imhtml->tip_window); | |
1390 imhtml->tip_window = NULL; | |
1391 } | |
1392 | |
1393 imhtml->tip_timer = 0; | |
1394 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
1395 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
1396 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
1397 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
1398 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
1399 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
1400 | |
1401 gtk_widget_ensure_style (imhtml->tip_window); | |
1402 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
1403 font = pango_font_get_metrics(pango_context_load_font(pango_layout_get_context(layout), | |
1404 imhtml->tip_window->style->font_desc), | |
1405 NULL); | |
1406 | |
1407 | |
1408 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
1409 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font) + | |
1410 pango_font_metrics_get_descent(font))/ 4); | |
1411 | |
1412 if (gap < 2) | |
1413 gap = 2; | |
1414 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
1415 pango_font_metrics_get_descent(font)); | |
1416 w = 8 + scr_w; | |
1417 h = 8 + baseline_skip; | |
1418 | |
1419 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
1420 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
1421 y += GTK_WIDGET(imhtml)->allocation.y; | |
1422 | |
1423 scr_w = gdk_screen_width(); | |
1424 | |
1425 x -= ((w >> 1) + 4); | |
1426 | |
1427 if ((x + w) > scr_w) | |
1428 x -= (x + w) - scr_w; | |
1429 else if (x < 0) | |
1430 x = 0; | |
1431 | |
1432 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font) + | |
1433 pango_font_metrics_get_descent(font)); | |
1434 | |
1435 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
1436 gtk_widget_show (imhtml->tip_window); | |
1437 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
1438 | |
1439 pango_font_metrics_unref(font); | |
4895 | 1440 g_object_unref(layout); |
4735 | 1441 |
1442 return FALSE; | |
1443 } | |
4895 | 1444 |
4947 | 1445 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
4895 | 1446 { |
4903 | 1447 GdkRectangle rect; |
4895 | 1448 |
4903 | 1449 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); |
4947 | 1450 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ |
4902 | 1451 GList *iter = GTK_IMHTML(widget)->scalables; |
4895 | 1452 |
1453 while(iter){ | |
1454 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data); | |
4903 | 1455 scale->scale(scale, rect.width, rect.height); |
4895 | 1456 |
1457 iter = iter->next; | |
1458 } | |
1459 } | |
1460 | |
4947 | 1461 widget->old_rect = rect; |
4895 | 1462 return FALSE; |
1463 } | |
1464 | |
1465 /* GtkIMHtmlScalable, gaim_im_image, gaim_hr */ | |
5012 | 1466 GtkIMHtmlScalable *gaim_im_image_new(GdkPixbuf *img, gchar *filename) |
4895 | 1467 { |
1468 gaim_im_image *im_image = g_malloc(sizeof(gaim_im_image)); | |
5012 | 1469 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 1470 |
1471 GTK_IMHTML_SCALABLE(im_image)->scale = gaim_im_image_scale; | |
1472 GTK_IMHTML_SCALABLE(im_image)->add_to = gaim_im_image_add_to; | |
1473 GTK_IMHTML_SCALABLE(im_image)->free = gaim_im_image_free; | |
5046 | 1474 |
1475 im_image->pixbuf = img; | |
5012 | 1476 im_image->image = image; |
4895 | 1477 im_image->width = gdk_pixbuf_get_width(img); |
1478 im_image->height = gdk_pixbuf_get_height(img); | |
1479 im_image->mark = NULL; | |
5012 | 1480 im_image->filename = filename; |
4895 | 1481 |
5046 | 1482 g_object_ref(img); |
4895 | 1483 return GTK_IMHTML_SCALABLE(im_image); |
1484 } | |
1485 | |
1486 void gaim_im_image_scale(GtkIMHtmlScalable *scale, int width, int height) | |
1487 { | |
1488 gaim_im_image *image = (gaim_im_image *)scale; | |
1489 | |
1490 if(image->width > width || image->height > height){ | |
1491 GdkPixbuf *new_image = NULL; | |
1492 float factor; | |
1493 int new_width = image->width, new_height = image->height; | |
1494 | |
1495 if(image->width > width){ | |
1496 factor = (float)(width)/image->width; | |
1497 new_width = width; | |
1498 new_height = image->height * factor; | |
1499 } | |
1500 if(new_height > height){ | |
1501 factor = (float)(height)/new_height; | |
1502 new_height = height; | |
1503 new_width = new_width * factor; | |
1504 } | |
1505 | |
5046 | 1506 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 1507 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 1508 g_object_unref(G_OBJECT(new_image)); |
1509 } | |
1510 } | |
1511 | |
1512 void gaim_im_image_free(GtkIMHtmlScalable *scale) | |
1513 { | |
1514 gaim_im_image *image = (gaim_im_image *)scale; | |
5046 | 1515 |
1516 g_object_unref(image->pixbuf); | |
5012 | 1517 g_free(image->filename); |
4895 | 1518 g_free(scale); |
1519 } | |
1520 | |
1521 void gaim_im_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1522 { | |
1523 gaim_im_image *image = (gaim_im_image *)scale; | |
5012 | 1524 GtkWidget *box = gtk_event_box_new(); |
1525 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
4895 | 1526 |
5012 | 1527 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); |
1528 | |
1529 gtk_widget_show(GTK_WIDGET(image->image)); | |
1530 gtk_widget_show(box); | |
1531 | |
1532 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
1533 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gaim_im_image_clicked), image); | |
4895 | 1534 } |
1535 | |
1536 GtkIMHtmlScalable *gaim_hr_new() | |
1537 { | |
1538 gaim_hr *hr = g_malloc(sizeof(gaim_hr)); | |
1539 | |
1540 GTK_IMHTML_SCALABLE(hr)->scale = gaim_hr_scale; | |
1541 GTK_IMHTML_SCALABLE(hr)->add_to = gaim_hr_add_to; | |
1542 GTK_IMHTML_SCALABLE(hr)->free = gaim_hr_free; | |
1543 | |
1544 hr->sep = gtk_hseparator_new(); | |
1545 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
1546 gtk_widget_show(hr->sep); | |
1547 | |
1548 return GTK_IMHTML_SCALABLE(hr); | |
1549 } | |
1550 | |
1551 void gaim_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
1552 { | |
1553 gtk_widget_set_size_request(((gaim_hr *)scale)->sep, width, 2); | |
1554 } | |
1555 | |
1556 void gaim_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
1557 { | |
1558 gaim_hr *hr = (gaim_hr *)scale; | |
1559 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
1560 | |
1561 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); | |
1562 } | |
1563 | |
1564 void gaim_hr_free(GtkIMHtmlScalable *scale) | |
1565 { | |
1566 /* gtk_widget_destroy(((gaim_hr *)scale)->sep); */ | |
1567 g_free(scale); | |
1568 } | |
5012 | 1569 |
1570 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) | |
1571 { | |
1572 const gchar *filename = gtk_file_selection_get_filename(sel); | |
1573 gaim_im_image *image = g_object_get_data(G_OBJECT(sel), "gaim_im_image"); | |
1574 gchar *type = NULL; | |
5019 | 1575 GError *error = NULL; |
5015 | 1576 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 1577 GSList *formats = gdk_pixbuf_get_formats(); |
1578 | |
1579 while(formats){ | |
1580 GdkPixbufFormat *format = formats->data; | |
1581 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
1582 gpointer p = extensions; | |
1583 | |
1584 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
1585 gchar *fmt_ext = extensions[0]; | |
1586 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
1587 | |
1588 if(!strcmp(fmt_ext, file_ext)){ | |
1589 type = gdk_pixbuf_format_get_name(format); | |
1590 break; | |
1591 } | |
1592 | |
1593 extensions++; | |
1594 } | |
1595 | |
1596 g_strfreev(p); | |
1597 | |
1598 if(type) | |
1599 break; | |
1600 | |
1601 formats = formats->next; | |
1602 } | |
1603 | |
5020 | 1604 g_slist_free(formats); |
1605 #else | |
1606 /* this is really ugly code, but I think it will work */ | |
1607 char *basename = g_path_get_basename(filename); | |
1608 char *ext = strrchr(basename, '.'); | |
1609 | |
1610 if(ext) { | |
1611 ext++; | |
1612 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
1613 type = g_strdup("jpeg"); | |
1614 else if(!g_ascii_strcasecmp(ext, "png")) | |
1615 type = g_strdup("png"); | |
1616 } | |
1617 | |
1618 g_free(basename); | |
1619 #endif | |
1620 | |
5012 | 1621 /* If I can't find a valid type, I will just tell the user about it and then assume |
1622 it's a png */ | |
1623 if(!type){ | |
1624 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
1625 _("Gaim was unable to guess the image type base on the file extension supplied. Defaulting to PNG.")); | |
1626 type = g_strdup("png"); | |
1627 } | |
1628 | |
5046 | 1629 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 1630 |
1631 if(error){ | |
1632 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
1633 _("Error saving image: %s"), error->message); | |
1634 g_error_free(error); | |
1635 } | |
1636 | |
1637 g_free(type); | |
1638 } | |
1639 | |
1640 static void gaim_im_image_save(GtkWidget *w, gaim_im_image *image) | |
1641 { | |
1642 GtkWidget *sel = gtk_file_selection_new(_("Gaim - Save Image")); | |
1643 | |
1644 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
1645 g_object_set_data(G_OBJECT(sel), "gaim_im_image", image); | |
1646 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
1647 G_CALLBACK(write_img_to_file), sel); | |
1648 | |
1649 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
1650 G_CALLBACK(gtk_widget_destroy), sel); | |
1651 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
1652 G_CALLBACK(gtk_widget_destroy), sel); | |
1653 | |
1654 gtk_widget_show(sel); | |
1655 } | |
1656 | |
1657 static gboolean gaim_im_image_clicked(GtkWidget *w, GdkEvent *event, gaim_im_image *image) | |
1658 { | |
1659 GdkEventButton *event_button = (GdkEventButton *) event; | |
1660 | |
1661 if (event->type == GDK_BUTTON_RELEASE) { | |
1662 if(event_button->button == 3) { | |
1663 GtkWidget *img, *item, *menu; | |
1664 gchar *text = g_strdup_printf(_("_Save Image...")); | |
1665 menu = gtk_menu_new(); | |
1666 | |
1667 /* buttons and such */ | |
1668 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
1669 item = gtk_image_menu_item_new_with_mnemonic(text); | |
1670 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
1671 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gaim_im_image_save), image); | |
1672 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
1673 | |
1674 gtk_widget_show_all(menu); | |
1675 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
1676 event_button->button, event_button->time); | |
1677 | |
1678 g_free(text); | |
1679 return TRUE; | |
1680 } | |
1681 } | |
1682 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
1683 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1684 be caught by the regular GtkTextView menu */ | |
1685 else | |
1686 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1687 | |
1688 } |