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