Mercurial > pidgin
annotate src/gtkimhtml.c @ 8758:2db51720fd09
[gaim-migrate @ 9513]
Some minor gtkconv fixes
-Disable the "warn" conversation menu item for protocols that don't
support it. Same with Get Info, Invite, and Insert Link
-Fix the following weird icon animation bug: (sf bug 939768)
In the conversation window talking to someone on AIM if
you right click on an animated AIM buddy icon and
unanimate it then you tab over to chat to someone else
using another protocol (not AIM) (like MSN or ICQ) that
don't have buddy icons then come back to the original
AIM person you disabled the animated buddy icon, well,
it's animated again.
It works fine if you stay in AIM and tab from someone
having a disabled animated icon to someone with no
buddy icon and/or someone having a non animated buddy
icon. So I think the bug is in when you tab to another
chat protocol.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 22 Apr 2004 16:24:05 +0000 |
parents | 61a090413b93 |
children | 5a2b5e4abf3a |
rev | line source |
---|---|
1428 | 1 /* |
2 * GtkIMHtml | |
3 * | |
8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
1428 | 7 * |
8 * This program is free software; you can redistribute it and/or modify | |
9 * under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 | |
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
24 #ifdef HAVE_CONFIG_H |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
25 #include <config.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
26 #endif |
8526 | 27 #include "debug.h" |
8091 | 28 #include "util.h" |
1428 | 29 #include "gtkimhtml.h" |
7358 | 30 #include "gtksourceiter.h" |
1428 | 31 #include <gtk/gtk.h> |
4895 | 32 #include <glib/gerror.h> |
4046 | 33 #include <gdk/gdkkeysyms.h> |
1428 | 34 #include <string.h> |
35 #include <ctype.h> | |
36 #include <stdio.h> | |
4629 | 37 #include <stdlib.h> |
1428 | 38 #include <math.h> |
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
39 #ifdef HAVE_LANGINFO_CODESET |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
40 #include <langinfo.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
41 #include <locale.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
42 #endif |
8692 | 43 #ifdef _WIN32 |
44 #include <windows.h> | |
45 #endif | |
1428 | 46 |
4417 | 47 #ifdef ENABLE_NLS |
48 # include <libintl.h> | |
49 # define _(x) gettext(x) | |
50 # ifdef gettext_noop | |
51 # define N_(String) gettext_noop (String) | |
52 # else | |
53 # define N_(String) (String) | |
54 # endif | |
55 #else | |
56 # define N_(String) (String) | |
57 # define _(x) (x) | |
58 #endif | |
59 | |
4735 | 60 #include <pango/pango-font.h> |
61 | |
5105 | 62 /* GTK+ < 2.2.2 hack, see ui.h for details. */ |
63 #ifndef GTK_WRAP_WORD_CHAR | |
64 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD | |
65 #endif | |
66 | |
4735 | 67 #define TOOLTIP_TIMEOUT 500 |
68 | |
8677 | 69 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
8061 | 70 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
8505 | 71 static gboolean gtk_imhtml_is_amp_escape (const gchar *string, gchar **replace, gint *length); |
8698 | 72 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter); |
8091 | 73 static void gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml); |
8677 | 74 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml); |
8061 | 75 |
3922 | 76 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a |
77 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | |
78 #define MAX_FONT_SIZE 7 | |
5367 | 79 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
8380 | 80 static gdouble _point_sizes [] = { .69444444, .8333333, 1, 1.2, 1.44, 1.728, 2.0736}; |
2349
60c716c32c40
[gaim-migrate @ 2362]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2348
diff
changeset
|
81 |
8498 | 82 enum { |
8677 | 83 TARGET_HTML, |
8061 | 84 TARGET_UTF8_STRING, |
85 TARGET_COMPOUND_TEXT, | |
86 TARGET_STRING, | |
87 TARGET_TEXT | |
88 }; | |
89 | |
8091 | 90 enum { |
91 DRAG_URL | |
92 }; | |
93 | |
8420 | 94 enum { |
95 URL_CLICKED, | |
96 BUTTONS_UPDATE, | |
97 TOGGLE_FORMAT, | |
8427 | 98 CLEAR_FORMAT, |
8506 | 99 UPDATE_FORMAT, |
8420 | 100 LAST_SIGNAL |
101 }; | |
102 static guint signals [LAST_SIGNAL] = { 0 }; | |
103 | |
8061 | 104 GtkTargetEntry selection_targets[] = { |
8566 | 105 { "text/html", 0, TARGET_HTML }, |
8061 | 106 { "UTF8_STRING", 0, TARGET_UTF8_STRING }, |
107 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, | |
108 { "STRING", 0, TARGET_STRING }, | |
109 { "TEXT", 0, TARGET_TEXT}}; | |
110 | |
8091 | 111 GtkTargetEntry link_drag_drop_targets[] = { |
112 {"x-url/ftp", 0, DRAG_URL}, | |
113 {"x-url/http", 0, DRAG_URL}, | |
114 {"text/uri-list", 0, DRAG_URL}, | |
115 {"_NETSCAPE_URL", 0, DRAG_URL}}; | |
116 | |
8692 | 117 #ifdef _WIN32 |
118 /* Win32 clipboard format value, and functions to convert back and | |
119 * forth between HTML and the clipboard format. | |
120 */ | |
121 static UINT win_html_fmt; | |
122 | |
123 static gchar * | |
124 clipboard_win32_to_html(char *clipboard) { | |
8693 | 125 const char *begin, *end; |
8692 | 126 gchar *html; |
127 | |
8693 | 128 begin = strstr(clipboard, "<!--StartFragment"); |
129 while(*begin++ != '>'); | |
8692 | 130 end = strstr(clipboard, "<!--EndFragment"); |
131 html = g_strstrip(g_strndup(begin, (end ? (end - begin) : strlen(begin)))); | |
8707 | 132 return html; |
8692 | 133 } |
134 | |
135 static gchar * | |
136 clipboard_html_to_win32(char *html) { | |
8693 | 137 int length; |
8692 | 138 gchar *ret; |
139 GString *clipboard; | |
140 | |
8693 | 141 if (html == NULL) |
142 return NULL; | |
8692 | 143 |
144 length = strlen(html); | |
145 clipboard = g_string_new ("Version:0.9\r\n"); | |
146 g_string_append(clipboard, "StartHTML:0000000105\r\n"); | |
147 g_string_append(clipboard, g_strdup_printf("EndHTML:%010d\r\n", 143 + length)); | |
148 g_string_append(clipboard, "StartFragment:0000000105\r\n"); | |
149 g_string_append(clipboard, g_strdup_printf("EndFragment:%010d\r\n", 143 + length)); | |
150 g_string_append(clipboard, "<!--StartFragment-->"); | |
151 g_string_append(clipboard, html); | |
152 g_string_append(clipboard, "<!--EndFragment-->"); | |
153 ret = clipboard->str; | |
154 g_string_free(clipboard, FALSE); | |
155 return ret; | |
156 } | |
157 #endif | |
158 | |
4032 | 159 static GtkSmileyTree* |
160 gtk_smiley_tree_new () | |
161 { | |
162 return g_new0 (GtkSmileyTree, 1); | |
163 } | |
164 | |
165 static void | |
166 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
4263 | 167 GtkIMHtmlSmiley *smiley) |
4032 | 168 { |
169 GtkSmileyTree *t = tree; | |
4263 | 170 const gchar *x = smiley->smile; |
4032 | 171 |
172 if (!strlen (x)) | |
173 return; | |
174 | |
175 while (*x) { | |
176 gchar *pos; | |
177 gint index; | |
178 | |
179 if (!t->values) | |
180 t->values = g_string_new (""); | |
181 | |
182 pos = strchr (t->values->str, *x); | |
183 if (!pos) { | |
184 t->values = g_string_append_c (t->values, *x); | |
185 index = t->values->len - 1; | |
186 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
187 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
188 } else | |
7386 | 189 index = GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str); |
8061 | 190 |
4032 | 191 t = t->children [index]; |
8061 | 192 |
4032 | 193 x++; |
194 } | |
8061 | 195 |
4263 | 196 t->image = smiley; |
4032 | 197 } |
4041 | 198 |
4263 | 199 |
4264 | 200 void gtk_smiley_tree_destroy (GtkSmileyTree *tree) |
4032 | 201 { |
202 GSList *list = g_slist_append (NULL, tree); | |
203 | |
204 while (list) { | |
205 GtkSmileyTree *t = list->data; | |
206 gint i; | |
207 list = g_slist_remove(list, t); | |
7384 | 208 if (t && t->values) { |
4032 | 209 for (i = 0; i < t->values->len; i++) |
210 list = g_slist_append (list, t->children [i]); | |
211 g_string_free (t->values, TRUE); | |
212 g_free (t->children); | |
213 } | |
214 g_free (t); | |
215 } | |
216 } | |
217 | |
5967 | 218 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
219 { | |
220 GdkRectangle rect; | |
8726 | 221 int xminus; |
5967 | 222 |
223 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); | |
224 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ | |
225 GList *iter = GTK_IMHTML(widget)->scalables; | |
226 | |
8726 | 227 xminus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(widget)) + |
228 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(widget)); | |
229 | |
5967 | 230 while(iter){ |
231 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data); | |
8726 | 232 scale->scale(scale, rect.width - xminus, rect.height); |
5967 | 233 |
234 iter = iter->next; | |
235 } | |
236 } | |
237 | |
238 widget->old_rect = rect; | |
239 return FALSE; | |
240 } | |
241 | |
242 static gint | |
243 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
244 { | |
245 PangoLayout *layout; | |
246 | |
247 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
248 | |
249 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
250 | |
8061 | 251 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, |
5967 | 252 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, |
253 "tooltip", 0, 0, -1, -1); | |
254 | |
255 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
256 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
257 | |
258 g_object_unref(layout); | |
259 return FALSE; | |
260 } | |
261 | |
262 static gint | |
263 gtk_imhtml_tip (gpointer data) | |
264 { | |
265 GtkIMHtml *imhtml = data; | |
8526 | 266 PangoFontMetrics *font_metrics; |
5967 | 267 PangoLayout *layout; |
8526 | 268 PangoFont *font; |
5967 | 269 |
270 gint gap, x, y, h, w, scr_w, baseline_skip; | |
271 | |
272 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
273 | |
274 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
275 imhtml->tip_timer = 0; | |
276 return FALSE; | |
277 } | |
8061 | 278 |
5967 | 279 if (imhtml->tip_window){ |
280 gtk_widget_destroy (imhtml->tip_window); | |
281 imhtml->tip_window = NULL; | |
282 } | |
283 | |
284 imhtml->tip_timer = 0; | |
285 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
286 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
287 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
288 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
289 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
290 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
291 | |
292 gtk_widget_ensure_style (imhtml->tip_window); | |
293 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
8526 | 294 font = pango_context_load_font(pango_layout_get_context(layout), |
295 imhtml->tip_window->style->font_desc); | |
296 | |
297 if (font == NULL) { | |
298 char *tmp = pango_font_description_to_string( | |
299 imhtml->tip_window->style->font_desc); | |
300 | |
301 gaim_debug(GAIM_DEBUG_ERROR, "gtk_imhtml_tip", | |
302 "pango_context_load_font() couldn't load font: '%s'\n", | |
303 tmp); | |
304 g_free(tmp); | |
305 | |
306 return FALSE; | |
307 | |
308 } | |
309 | |
310 font_metrics = pango_font_get_metrics(font, NULL); | |
8309 | 311 |
5967 | 312 |
313 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
8526 | 314 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font_metrics) + |
315 pango_font_metrics_get_descent(font_metrics))/ 4); | |
5967 | 316 |
317 if (gap < 2) | |
318 gap = 2; | |
8526 | 319 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics) + |
320 pango_font_metrics_get_descent(font_metrics)); | |
5967 | 321 w = 8 + scr_w; |
322 h = 8 + baseline_skip; | |
323 | |
324 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
325 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
326 y += GTK_WIDGET(imhtml)->allocation.y; | |
327 | |
328 scr_w = gdk_screen_width(); | |
329 | |
330 x -= ((w >> 1) + 4); | |
331 | |
332 if ((x + w) > scr_w) | |
333 x -= (x + w) - scr_w; | |
334 else if (x < 0) | |
335 x = 0; | |
336 | |
8526 | 337 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics) + |
338 pango_font_metrics_get_descent(font_metrics)); | |
5967 | 339 |
340 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
341 gtk_widget_show (imhtml->tip_window); | |
342 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
343 | |
8526 | 344 pango_font_metrics_unref(font_metrics); |
5967 | 345 g_object_unref(layout); |
346 | |
347 return FALSE; | |
348 } | |
349 | |
350 gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) | |
8061 | 351 { |
5967 | 352 GtkTextIter iter; |
353 GdkWindow *win = event->window; | |
354 int x, y; | |
355 char *tip = NULL; | |
356 GSList *tags = NULL, *templist = NULL; | |
357 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); | |
358 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, | |
359 event->x, event->y, &x, &y); | |
360 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
361 tags = gtk_text_iter_get_tags(&iter); | |
362 | |
363 templist = tags; | |
364 while (templist) { | |
365 GtkTextTag *tag = templist->data; | |
366 tip = g_object_get_data(G_OBJECT(tag), "link_url"); | |
367 if (tip) | |
368 break; | |
369 templist = templist->next; | |
370 } | |
8061 | 371 |
5967 | 372 if (GTK_IMHTML(imhtml)->tip) { |
373 if ((tip == GTK_IMHTML(imhtml)->tip)) { | |
374 return FALSE; | |
375 } | |
376 /* We've left the cell. Remove the timeout and create a new one below */ | |
377 if (GTK_IMHTML(imhtml)->tip_window) { | |
378 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
379 GTK_IMHTML(imhtml)->tip_window = NULL; | |
380 } | |
8061 | 381 if (GTK_IMHTML(imhtml)->editable) |
382 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->text_cursor); | |
383 else | |
384 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->arrow_cursor); | |
5967 | 385 if (GTK_IMHTML(imhtml)->tip_timer) |
386 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
387 GTK_IMHTML(imhtml)->tip_timer = 0; | |
388 } | |
8061 | 389 |
5967 | 390 if(tip){ |
8061 | 391 if (!GTK_IMHTML(imhtml)->editable) |
392 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); | |
393 GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, | |
5967 | 394 gtk_imhtml_tip, imhtml); |
395 } | |
8061 | 396 |
5967 | 397 GTK_IMHTML(imhtml)->tip = tip; |
398 g_slist_free(tags); | |
399 return FALSE; | |
400 } | |
401 | |
402 gboolean gtk_leave_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) | |
403 { | |
404 /* when leaving the widget, clear any current & pending tooltips and restore the cursor */ | |
405 if (GTK_IMHTML(imhtml)->tip_window) { | |
406 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
407 GTK_IMHTML(imhtml)->tip_window = NULL; | |
408 } | |
409 if (GTK_IMHTML(imhtml)->tip_timer) { | |
410 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
411 GTK_IMHTML(imhtml)->tip_timer = 0; | |
412 } | |
8061 | 413 if (GTK_IMHTML(imhtml)->editable) |
414 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->text_cursor); | |
415 else | |
416 gdk_window_set_cursor(event->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
5967 | 417 |
8568 | 418 /* propagate the event normally */ |
5967 | 419 return FALSE; |
420 } | |
421 | |
6066 | 422 /* |
423 * XXX - This should be removed eventually. | |
424 * | |
8061 | 425 * This function exists to work around a gross bug in GtkTextView. |
426 * Basically, we short circuit ctrl+a and ctrl+end because they make | |
6066 | 427 * el program go boom. |
428 * | |
8061 | 429 * It's supposed to be fixed in gtk2.2. You can view the bug report at |
6066 | 430 * http://bugzilla.gnome.org/show_bug.cgi?id=107939 |
431 */ | |
8317 | 432 |
433 /* | |
434 * I'm adding some keyboard shortcuts too. | |
435 */ | |
436 | |
437 gboolean gtk_key_pressed_cb(GtkIMHtml *imhtml, GdkEventKey *event, gpointer data) | |
8677 | 438 { |
8317 | 439 char buf[7]; |
440 buf[0] = '\0'; | |
441 | |
6066 | 442 if (event->state & GDK_CONTROL_MASK) |
443 switch (event->keyval) { | |
8539 | 444 #if (!GTK_CHECK_VERSION(2,2,0)) |
8317 | 445 case 'a': |
446 return TRUE; | |
447 break; | |
8677 | 448 |
8317 | 449 case GDK_Home: |
450 return TRUE; | |
451 break; | |
452 | |
453 case GDK_End: | |
454 return TRUE; | |
455 break; | |
8758 | 456 #endif /* !(Gtk+ >= 2.2.0) */ |
8317 | 457 |
458 case 'b': /* ctrl-b is GDK_Left, which moves backwards. */ | |
459 case 'B': | |
8420 | 460 if (imhtml->format_functions & GTK_IMHTML_BOLD) { |
8456 | 461 if(imhtml->html_shortcuts) { |
462 gtk_imhtml_toggle_bold(imhtml); | |
8466 | 463 return TRUE; |
8456 | 464 } |
8420 | 465 } |
8466 | 466 return FALSE; |
8317 | 467 break; |
8654 | 468 |
469 #ifdef LAY_OFF_MY_FRIGGIN_KEYBINDINGS | |
8317 | 470 case 'f': |
471 case 'F': | |
472 /*set_toggle(gtkconv->toolbar.font, | |
473 !gtk_toggle_button_get_active( | |
474 GTK_TOGGLE_BUTTON(gtkconv->toolbar.font)));*/ | |
475 | |
476 return TRUE; | |
477 break; | |
8654 | 478 #endif /* this doesn't even DO anything */ |
8317 | 479 |
480 case 'i': | |
481 case 'I': | |
8481 | 482 if (imhtml->format_functions & GTK_IMHTML_ITALIC) { |
8466 | 483 if(imhtml->html_shortcuts) { |
8456 | 484 gtk_imhtml_toggle_italic(imhtml); |
8466 | 485 return TRUE; |
486 } | |
8481 | 487 } |
8466 | 488 return FALSE; |
8317 | 489 break; |
490 | |
491 case 'u': /* ctrl-u is GDK_Clear, which clears the line. */ | |
492 case 'U': | |
8481 | 493 if (imhtml->format_functions & GTK_IMHTML_UNDERLINE) { |
8466 | 494 if(imhtml->html_shortcuts) { |
8456 | 495 gtk_imhtml_toggle_underline(imhtml); |
8466 | 496 return TRUE; |
497 } | |
8481 | 498 } |
8466 | 499 return FALSE; |
8317 | 500 break; |
501 | |
502 case '-': | |
8420 | 503 if (imhtml->format_functions & GTK_IMHTML_SHRINK) |
504 gtk_imhtml_font_shrink(imhtml); | |
8317 | 505 return TRUE; |
506 break; | |
507 | |
508 case '=': | |
509 case '+': | |
8420 | 510 if (imhtml->format_functions & GTK_IMHTML_GROW) |
511 gtk_imhtml_font_grow(imhtml); | |
8317 | 512 return TRUE; |
513 break; | |
8677 | 514 |
8317 | 515 case '1': strcpy(buf, ":-)"); break; |
516 case '2': strcpy(buf, ":-("); break; | |
517 case '3': strcpy(buf, ";-)"); break; | |
518 case '4': strcpy(buf, ":-P"); break; | |
519 case '5': strcpy(buf, "=-O"); break; | |
520 case '6': strcpy(buf, ":-*"); break; | |
521 case '7': strcpy(buf, ">:o"); break; | |
522 case '8': strcpy(buf, "8-)"); break; | |
523 case '!': strcpy(buf, ":-$"); break; | |
524 case '@': strcpy(buf, ":-!"); break; | |
525 case '#': strcpy(buf, ":-["); break; | |
526 case '$': strcpy(buf, "O:-)"); break; | |
527 case '%': strcpy(buf, ":-/"); break; | |
528 case '^': strcpy(buf, ":'("); break; | |
529 case '&': strcpy(buf, ":-X"); break; | |
530 case '*': strcpy(buf, ":-D"); break; | |
6066 | 531 } |
8456 | 532 if (*buf && imhtml->smiley_shortcuts) { |
533 gtk_imhtml_insert_smiley(imhtml, imhtml->protocol_name, buf); | |
8317 | 534 return TRUE; |
8677 | 535 } |
6066 | 536 return FALSE; |
537 } | |
538 | |
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
539 #if GTK_CHECK_VERSION(2,2,0) |
8061 | 540 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { |
8681 | 541 char *text; |
8061 | 542 GtkTextIter start, end; |
543 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
544 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
8681 | 545 |
8061 | 546 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); |
547 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
8681 | 548 gboolean primary = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY) == clipboard; |
8061 | 549 |
550 if (info == TARGET_HTML) { | |
8149 | 551 int len; |
8148 | 552 char *selection; |
8061 | 553 GString *str = g_string_new(NULL); |
8681 | 554 if (primary) { |
555 text = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
556 } else | |
557 text = imhtml->clipboard_html_string; | |
8061 | 558 |
559 /* Mozilla asks that we start our text/html with the Unicode byte order mark */ | |
560 str = g_string_append_unichar(str, 0xfeff); | |
561 str = g_string_append(str, text); | |
562 str = g_string_append_unichar(str, 0x0000); | |
8148 | 563 selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
8719 | 564 gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 16, selection, len); |
8061 | 565 g_string_free(str, TRUE); |
566 g_free(selection); | |
567 } else { | |
8681 | 568 if (primary) { |
569 text = gtk_imhtml_get_text(imhtml, &start, &end); | |
570 } else | |
571 text = imhtml->clipboard_text_string; | |
8061 | 572 gtk_selection_data_set_text(selection_data, text, strlen(text)); |
573 } | |
8681 | 574 if (primary) /* This was allocated here */ |
575 g_free(text); | |
576 } | |
8061 | 577 |
578 static void gtk_imhtml_primary_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml) | |
7749 | 579 { |
8061 | 580 GtkTextIter insert; |
581 GtkTextIter selection_bound; | |
582 | |
583 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &insert, | |
584 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert")); | |
585 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &selection_bound, | |
586 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound")); | |
587 | |
588 if (!gtk_text_iter_equal (&insert, &selection_bound)) | |
589 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
590 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound"), | |
591 &insert); | |
7749 | 592 } |
7742 | 593 |
8677 | 594 static void copy_clipboard_cb(GtkIMHtml *imhtml, gpointer unused) |
7749 | 595 { |
8681 | 596 GtkTextIter start, end; |
597 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
598 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
599 | |
600 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | |
601 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
602 | |
8061 | 603 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), |
604 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
605 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
606 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | |
7346 | 607 |
8681 | 608 if (imhtml->clipboard_html_string) { |
609 g_free(imhtml->clipboard_html_string); | |
610 g_free(imhtml->clipboard_text_string); | |
611 } | |
612 | |
613 imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
614 imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); | |
615 | |
8692 | 616 #ifdef _WIN32 |
617 /* We're going to still copy plain text, but let's toss the "HTML Format" | |
618 we need into the windows clipboard now as well. */ | |
619 HGLOBAL hdata; | |
620 gchar *clipboard = clipboard_html_to_win32(imhtml->clipboard_html_string); | |
621 gchar *buffer; | |
622 gint length = strlen(clipboard); | |
623 if(clipboard != NULL) { | |
8693 | 624 OpenClipboard(NULL); |
8692 | 625 hdata = GlobalAlloc(GMEM_MOVEABLE, length); |
626 buffer = GlobalLock(hdata); | |
627 memcpy(buffer, clipboard, length); | |
628 GlobalUnlock(hdata); | |
629 SetClipboardData(win_html_fmt, hdata); | |
630 CloseClipboard(); | |
8693 | 631 g_free(clipboard); |
8692 | 632 } |
633 #endif | |
634 | |
8061 | 635 g_signal_stop_emission_by_name(imhtml, "copy-clipboard"); |
636 } | |
637 | |
8698 | 638 static void cut_clipboard_cb(GtkIMHtml *imhtml, gpointer unused) |
639 { | |
640 GtkTextIter start, end; | |
641 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
642 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
643 | |
644 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | |
645 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
646 | |
647 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), | |
648 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
649 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
650 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | |
651 | |
652 if (imhtml->clipboard_html_string) { | |
653 g_free(imhtml->clipboard_html_string); | |
654 g_free(imhtml->clipboard_text_string); | |
655 } | |
656 | |
657 imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
658 imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); | |
659 | |
660 #ifdef _WIN32 | |
661 /* We're going to still copy plain text, but let's toss the "HTML Format" | |
662 we need into the windows clipboard now as well. */ | |
663 HGLOBAL hdata; | |
664 gchar *clipboard = clipboard_html_to_win32(imhtml->clipboard_html_string); | |
665 gchar *buffer; | |
666 gint length = strlen(clipboard); | |
667 if(clipboard != NULL) { | |
668 OpenClipboard(NULL); | |
669 hdata = GlobalAlloc(GMEM_MOVEABLE, length); | |
670 buffer = GlobalLock(hdata); | |
671 memcpy(buffer, clipboard, length); | |
672 GlobalUnlock(hdata); | |
673 SetClipboardData(win_html_fmt, hdata); | |
674 CloseClipboard(); | |
675 g_free(clipboard); | |
676 } | |
677 #endif | |
678 | |
679 if (imhtml->editable) | |
680 gtk_text_buffer_delete_selection(imhtml->text_buffer, FALSE, FALSE); | |
681 g_signal_stop_emission_by_name(imhtml, "cut-clipboard"); | |
682 } | |
683 | |
8061 | 684 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) |
685 { | |
686 char *text; | |
687 guint16 c; | |
688 GtkIMHtml *imhtml = data; | |
8677 | 689 GtkTextIter iter; |
8698 | 690 GtkIMHtmlOptions flags = GTK_IMHTML_NO_NEWLINE; |
691 gboolean plaintext = FALSE; | |
7809 | 692 |
8123 | 693 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) |
8105 | 694 return; |
695 | |
8692 | 696 #ifdef _WIN32 |
697 /* If we're on windows, let's see if we can get data from the HTML Format | |
698 clipboard before we try to paste from the GTK buffer */ | |
699 HGLOBAL hdata; | |
700 DWORD err; | |
701 char *buffer; | |
702 if (IsClipboardFormatAvailable(win_html_fmt)) { | |
8693 | 703 OpenClipboard(NULL); |
8692 | 704 hdata = GetClipboardData(win_html_fmt); |
705 if (hdata == NULL) { | |
706 err = GetLastError(); | |
707 gaim_debug_info("html clipboard", "error number %u! See http://msdn.microsoft.com/library/en-us/debug/base/system_error_codes.asp\n", err); | |
708 CloseClipboard(); | |
709 return; | |
710 } | |
711 buffer = GlobalLock(hdata); | |
712 if (buffer == NULL) { | |
8693 | 713 err = GetLastError(); |
8692 | 714 gaim_debug_info("html clipboard", "error number %u! See http://msdn.microsoft.com/library/en-us/debug/base/system_error_codes.asp\n", err); |
715 CloseClipboard(); | |
716 return; | |
717 } | |
718 text = clipboard_win32_to_html(buffer); | |
719 GlobalUnlock(hdata); | |
720 CloseClipboard(); | |
721 } else | |
722 #endif | |
8061 | 723 if (selection_data->length < 0) { |
8698 | 724 char *tmp; |
8061 | 725 text = gtk_clipboard_wait_for_text(clipboard); |
8698 | 726 flags = 0; |
727 plaintext = TRUE; | |
8128
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
728 |
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
729 if (text == NULL) |
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
730 return; |
9aafd344230d
[gaim-migrate @ 8833]
Christian Hammond <chipx86@chipx86.com>
parents:
8123
diff
changeset
|
731 |
8698 | 732 tmp = gaim_escape_html(text); |
733 g_free(text); | |
734 text = tmp; | |
8061 | 735 } else { |
8719 | 736 #if 0 |
737 /* Here's some debug code, for figuring out what sent to us over the clipboard. */ | |
738 { | |
739 int i; | |
740 | |
741 gaim_debug_misc("gtkimhtml", "In paste_received_cb():\n\tformat = %d, length = %d\n\t", | |
742 selection_data->format, selection_data->length); | |
743 | |
744 for (i = 0; i < (/*(selection_data->format / 8) **/ selection_data->length); i++) { | |
745 if ((i % 70) == 0) | |
746 printf("\n\t"); | |
747 if (selection_data->data[i] == '\0') | |
748 printf("."); | |
749 else | |
750 printf("%c", selection_data->data[i]); | |
751 } | |
752 printf("\n"); | |
753 } | |
754 #endif | |
755 text = g_malloc(selection_data->length); | |
756 memcpy(text, selection_data->data, selection_data->length); | |
7766 | 757 } |
8061 | 758 |
759 memcpy (&c, text, 2); | |
760 if (c == 0xfeff) { | |
761 /* This is UCS2 */ | |
8719 | 762 char *utf8 = g_convert(text+2, selection_data->length - 2, "UTF-8", "UCS-2", NULL, NULL, NULL); |
8061 | 763 g_free(text); |
764 text = utf8; | |
8698 | 765 if (!text) { |
766 gaim_debug_warning("gtkimhtml", "g_convert failed in paste_received_cb\n"); | |
767 return; | |
768 } | |
8061 | 769 } |
8698 | 770 |
771 if (!(*text) || !g_utf8_validate(text, -1, NULL)) { | |
772 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in paste_received_cb\n"); | |
773 g_free(text); | |
774 return; | |
775 } | |
776 | |
8677 | 777 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, gtk_text_buffer_get_insert(imhtml->text_buffer)); |
8698 | 778 if (!imhtml->wbfo && !plaintext) |
779 gtk_imhtml_close_tags(imhtml, &iter); | |
780 gtk_imhtml_insert_html_at_iter(imhtml, text, flags, &iter); | |
8677 | 781 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter); |
8698 | 782 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), gtk_text_buffer_get_insert(imhtml->text_buffer), |
783 0, FALSE, 0.0, 0.0); | |
8681 | 784 g_free(text); |
8061 | 785 } |
786 | |
787 static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) | |
788 { | |
789 | |
790 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); | |
791 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
792 paste_received_cb, imhtml); | |
793 g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); | |
7766 | 794 } |
795 | |
8677 | 796 static void imhtml_realized_remove_primary(GtkIMHtml *imhtml, gpointer unused) |
797 { | |
798 gtk_text_buffer_remove_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, | |
799 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); | |
800 | |
801 } | |
802 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
803 static void imhtml_destroy_add_primary(GtkIMHtml *imhtml, gpointer unused) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
804 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
805 gtk_text_buffer_add_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
806 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
807 } |
8677 | 808 #endif |
809 | |
810 static void mark_set_so_update_selection_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml) | |
811 { | |
812 if (gtk_text_buffer_get_selection_bounds(buffer, NULL, NULL)) { | |
813 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY), | |
814 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
815 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
816 (GtkClipboardClearFunc)gtk_imhtml_primary_clipboard_clear, G_OBJECT(imhtml)); | |
817 } | |
818 } | |
819 | |
820 /* does this go in the #ifdef too? I need to keep track of which functions are 2.2 only */ | |
821 /* adapted from gtktextview.c */ | |
822 static gboolean gtk_imhtml_button_press_event(GtkIMHtml *imhtml, GdkEventButton *event, gpointer unused) | |
7346 | 823 { |
8677 | 824 if (event->button == 2) { |
825 int x, y; | |
826 GtkTextIter iter; | |
827 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY); | |
828 | |
829 if (!imhtml->editable) | |
830 return FALSE; | |
831 | |
832 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), | |
833 GTK_TEXT_WINDOW_TEXT, | |
834 event->x, | |
835 event->y, | |
836 &x, | |
837 &y); | |
838 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
839 gtk_text_buffer_place_cursor(imhtml->text_buffer, &iter); | |
840 | |
841 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
842 paste_received_cb, imhtml); | |
843 | |
844 return TRUE; | |
845 } | |
846 | |
7346 | 847 return FALSE; |
848 } | |
4263 | 849 |
4032 | 850 static GtkTextViewClass *parent_class = NULL; |
851 | |
852 static void | |
853 gtk_imhtml_finalize (GObject *object) | |
854 { | |
855 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
4895 | 856 GList *scalables; |
8061 | 857 |
4138 | 858 g_hash_table_destroy(imhtml->smiley_data); |
4032 | 859 gtk_smiley_tree_destroy(imhtml->default_smilies); |
4138 | 860 gdk_cursor_unref(imhtml->hand_cursor); |
861 gdk_cursor_unref(imhtml->arrow_cursor); | |
8061 | 862 gdk_cursor_unref(imhtml->text_cursor); |
8677 | 863 |
4735 | 864 if(imhtml->tip_window){ |
865 gtk_widget_destroy(imhtml->tip_window); | |
866 } | |
867 if(imhtml->tip_timer) | |
868 gtk_timeout_remove(imhtml->tip_timer); | |
869 | |
4895 | 870 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
871 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
872 scale->free(scale); | |
873 } | |
7991 | 874 |
8681 | 875 if (imhtml->clipboard_text_string) { |
876 g_free(imhtml->clipboard_text_string); | |
877 g_free(imhtml->clipboard_html_string); | |
878 } | |
879 | |
4895 | 880 g_list_free(imhtml->scalables); |
4032 | 881 G_OBJECT_CLASS(parent_class)->finalize (object); |
882 } | |
1428 | 883 |
3922 | 884 /* Boring GTK stuff */ |
8519 | 885 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) |
1428 | 886 { |
3922 | 887 GtkObjectClass *object_class; |
4032 | 888 GObjectClass *gobject_class; |
8519 | 889 object_class = (GtkObjectClass*) klass; |
890 gobject_class = (GObjectClass*) klass; | |
4032 | 891 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); |
4417 | 892 signals[URL_CLICKED] = g_signal_new("url_clicked", |
893 G_TYPE_FROM_CLASS(gobject_class), | |
894 G_SIGNAL_RUN_FIRST, | |
895 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
896 NULL, | |
897 0, | |
898 g_cclosure_marshal_VOID__POINTER, | |
899 G_TYPE_NONE, 1, | |
900 G_TYPE_POINTER); | |
8506 | 901 signals[BUTTONS_UPDATE] = g_signal_new("format_buttons_update", |
8420 | 902 G_TYPE_FROM_CLASS(gobject_class), |
903 G_SIGNAL_RUN_FIRST, | |
904 G_STRUCT_OFFSET(GtkIMHtmlClass, buttons_update), | |
905 NULL, | |
906 0, | |
907 g_cclosure_marshal_VOID__POINTER, | |
908 G_TYPE_NONE, 1, | |
909 G_TYPE_INT); | |
910 signals[TOGGLE_FORMAT] = g_signal_new("format_function_toggle", | |
911 G_TYPE_FROM_CLASS(gobject_class), | |
912 G_SIGNAL_RUN_FIRST, | |
913 G_STRUCT_OFFSET(GtkIMHtmlClass, toggle_format), | |
914 NULL, | |
915 0, | |
916 g_cclosure_marshal_VOID__POINTER, | |
8427 | 917 G_TYPE_NONE, 1, |
8420 | 918 G_TYPE_INT); |
8427 | 919 signals[CLEAR_FORMAT] = g_signal_new("format_function_clear", |
920 G_TYPE_FROM_CLASS(gobject_class), | |
921 G_SIGNAL_RUN_FIRST, | |
922 G_STRUCT_OFFSET(GtkIMHtmlClass, clear_format), | |
923 NULL, | |
924 0, | |
8481 | 925 g_cclosure_marshal_VOID__VOID, |
926 G_TYPE_NONE, 0); | |
8506 | 927 signals[UPDATE_FORMAT] = g_signal_new("format_function_update", |
928 G_TYPE_FROM_CLASS(gobject_class), | |
929 G_SIGNAL_RUN_FIRST, | |
930 G_STRUCT_OFFSET(GtkIMHtmlClass, update_format), | |
931 NULL, | |
932 0, | |
933 g_cclosure_marshal_VOID__VOID, | |
934 G_TYPE_NONE, 0); | |
4032 | 935 gobject_class->finalize = gtk_imhtml_finalize; |
1428 | 936 } |
937 | |
3922 | 938 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 939 { |
3922 | 940 GtkTextIter iter; |
941 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
942 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
8677 | 943 imhtml->scrollpoint = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); |
3922 | 944 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); |
5105 | 945 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 946 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
8677 | 947 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); |
948 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(imhtml), 2); | |
8061 | 949 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
3922 | 950 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
8061 | 951 |
3922 | 952 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
8061 | 953 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ |
3922 | 954 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); |
955 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
956 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
957 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
958 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
959 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
960 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
7295 | 961 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
8677 | 962 |
3922 | 963 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
964 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
965 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
8061 | 966 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
2993 | 967 |
4253 | 968 imhtml->show_smileys = TRUE; |
6124 | 969 imhtml->show_comments = TRUE; |
4253 | 970 |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
971 imhtml->zoom = 1.0; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
972 imhtml->original_fsize = 0; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
973 |
4892 | 974 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 975 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 976 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 977 |
4944 | 978 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 979 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 980 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
6066 | 981 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
8677 | 982 g_signal_connect(G_OBJECT(imhtml), "button_press_event", G_CALLBACK(gtk_imhtml_button_press_event), NULL); |
983 g_signal_connect(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(preinsert_cb), imhtml); | |
8061 | 984 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
8091 | 985 |
986 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, | |
987 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | |
988 GDK_ACTION_COPY); | |
989 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | |
990 | |
7404
d889a99e0eb1
[gaim-migrate @ 8000]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
991 #if GTK_CHECK_VERSION(2,2,0) |
7353 | 992 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
8698 | 993 g_signal_connect(G_OBJECT(imhtml), "cut-clipboard", G_CALLBACK(cut_clipboard_cb), NULL); |
8061 | 994 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
8677 | 995 //g_signal_connect_after(G_OBJECT(imhtml), "button-release-event", G_CALLBACK(button_release_cb), imhtml); |
996 g_signal_connect_after(G_OBJECT(imhtml), "realize", G_CALLBACK(imhtml_realized_remove_primary), NULL); | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
997 g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
998 #endif |
8677 | 999 |
1000 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
1001 G_CALLBACK(mark_set_so_update_selection_cb), imhtml); | |
1002 | |
4944 | 1003 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
4735 | 1004 |
8681 | 1005 imhtml->clipboard_text_string = NULL; |
1006 imhtml->clipboard_html_string = NULL; | |
1007 | |
4735 | 1008 imhtml->tip = NULL; |
1009 imhtml->tip_timer = 0; | |
1010 imhtml->tip_window = NULL; | |
4895 | 1011 |
8677 | 1012 imhtml->edit.bold = FALSE; |
1013 imhtml->edit.italic = FALSE; | |
1014 imhtml->edit.underline = FALSE; | |
8061 | 1015 imhtml->edit.forecolor = NULL; |
1016 imhtml->edit.backcolor = NULL; | |
1017 imhtml->edit.fontface = NULL; | |
8677 | 1018 imhtml->edit.fontsize = 0; |
1019 imhtml->edit.link = NULL; | |
1020 | |
8061 | 1021 |
4895 | 1022 imhtml->scalables = NULL; |
8061 | 1023 |
1024 gtk_imhtml_set_editable(imhtml, FALSE); | |
8692 | 1025 |
1026 #ifdef _WIN32 | |
1027 /* Register HTML Format as desired clipboard format */ | |
1028 win_html_fmt = RegisterClipboardFormat("HTML Format"); | |
1029 #endif | |
2993 | 1030 } |
1031 | |
3922 | 1032 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 1033 { |
4635 | 1034 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 1035 } |
1036 | |
4635 | 1037 GType gtk_imhtml_get_type() |
1428 | 1038 { |
4635 | 1039 static GType imhtml_type = 0; |
1428 | 1040 |
1041 if (!imhtml_type) { | |
4635 | 1042 static const GTypeInfo imhtml_info = { |
1043 sizeof(GtkIMHtmlClass), | |
1044 NULL, | |
1045 NULL, | |
1046 (GClassInitFunc) gtk_imhtml_class_init, | |
1047 NULL, | |
1048 NULL, | |
1428 | 1049 sizeof (GtkIMHtml), |
4635 | 1050 0, |
1051 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 1052 }; |
4635 | 1053 |
1054 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
1055 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 1056 } |
1057 | |
1058 return imhtml_type; | |
1059 } | |
1060 | |
4417 | 1061 struct url_data { |
1062 GObject *object; | |
1063 gchar *url; | |
1064 }; | |
1065 | |
8677 | 1066 static void url_data_destroy(gpointer mydata) |
1067 { | |
1068 struct url_data *data = mydata; | |
1069 g_object_unref(data->object); | |
1070 g_free(data->url); | |
1071 g_free(data); | |
1072 } | |
1073 | |
4417 | 1074 static void url_open(GtkWidget *w, struct url_data *data) { |
1075 if(!data) return; | |
8061 | 1076 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
7988 | 1077 |
4417 | 1078 } |
5582 | 1079 |
4417 | 1080 static void url_copy(GtkWidget *w, gchar *url) { |
1081 GtkClipboard *clipboard; | |
1082 | |
5293
ead927e2543f
[gaim-migrate @ 5665]
Christian Hammond <chipx86@chipx86.com>
parents:
5282
diff
changeset
|
1083 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
4417 | 1084 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 1085 |
1086 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | |
1087 gtk_clipboard_set_text(clipboard, url, -1); | |
4417 | 1088 } |
1089 | |
1090 /* The callback for an event on a link tag. */ | |
8677 | 1091 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) { |
4417 | 1092 GdkEventButton *event_button = (GdkEventButton *) event; |
8061 | 1093 if (GTK_IMHTML(imhtml)->editable) |
1094 return FALSE; | |
3922 | 1095 if (event->type == GDK_BUTTON_RELEASE) { |
8061 | 1096 if (event_button->button == 1) { |
4417 | 1097 GtkTextIter start, end; |
1098 /* we shouldn't open a URL if the user has selected something: */ | |
8677 | 1099 if (gtk_text_buffer_get_selection_bounds( |
1100 gtk_text_iter_get_buffer(arg2), &start, &end)) | |
4417 | 1101 return FALSE; |
1102 | |
1103 /* A link was clicked--we emit the "url_clicked" signal | |
1104 * with the URL as the argument */ | |
8677 | 1105 g_object_ref(G_OBJECT(tag)); |
1106 g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url")); | |
1107 g_object_unref(G_OBJECT(tag)); | |
4417 | 1108 return FALSE; |
1109 } else if(event_button->button == 3) { | |
4745 | 1110 GtkWidget *img, *item, *menu; |
4417 | 1111 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 1112 tempdata->object = g_object_ref(imhtml); |
8677 | 1113 tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url")); |
4745 | 1114 |
5091 | 1115 /* Don't want the tooltip around if user right-clicked on link */ |
1116 if (GTK_IMHTML(imhtml)->tip_window) { | |
1117 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
1118 GTK_IMHTML(imhtml)->tip_window = NULL; | |
1119 } | |
1120 if (GTK_IMHTML(imhtml)->tip_timer) { | |
1121 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
1122 GTK_IMHTML(imhtml)->tip_timer = 0; | |
1123 } | |
8061 | 1124 if (GTK_IMHTML(imhtml)->editable) |
1125 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | |
1126 else | |
1127 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 1128 menu = gtk_menu_new(); |
8677 | 1129 g_object_set_data_full(G_OBJECT(menu), "x-imhtml-url-data", tempdata, url_data_destroy); |
4745 | 1130 |
4417 | 1131 /* buttons and such */ |
1132 | |
8677 | 1133 if (!strncmp(tempdata->url, "mailto:", 7)) |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1134 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1135 /* Copy E-Mail Address */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1136 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1137 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1138 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1139 _("_Copy E-Mail Address")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1140 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
|
1141 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1142 G_CALLBACK(url_copy), tempdata->url + 7); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1143 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1144 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1145 else |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1146 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1147 /* Copy Link Location */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1148 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1149 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1150 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1151 _("_Copy Link Location")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1152 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
|
1153 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1154 G_CALLBACK(url_copy), tempdata->url); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1155 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1156 |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1157 /* Open Link in Browser */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1158 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1159 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1160 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1161 _("_Open Link in Browser")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1162 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
|
1163 g_signal_connect(G_OBJECT(item), "activate", |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1164 G_CALLBACK(url_open), tempdata); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1165 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1166 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1167 |
4756 | 1168 |
4417 | 1169 gtk_widget_show_all(menu); |
4756 | 1170 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
1171 event_button->button, event_button->time); | |
4745 | 1172 |
4417 | 1173 return TRUE; |
1174 } | |
1428 | 1175 } |
4417 | 1176 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
1177 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1178 be caught by the regular GtkTextView menu */ | |
1179 else | |
1180 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 1181 } |
1182 | |
8091 | 1183 static void |
1184 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
1185 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) | |
1186 { | |
1187 if(gtk_imhtml_get_editable(imhtml) && sd->data){ | |
1188 gchar **links; | |
1189 gchar *link; | |
1190 | |
1191 gaim_str_strip_cr(sd->data); | |
1192 | |
1193 links = g_strsplit(sd->data, "\n", 0); | |
1194 while((link = *links++) != NULL){ | |
1195 if(gaim_str_has_prefix(link, "http://") || | |
1196 gaim_str_has_prefix(link, "https://") || | |
1197 gaim_str_has_prefix(link, "ftp://")){ | |
8677 | 1198 gtk_imhtml_insert_link(imhtml, gtk_text_buffer_get_insert(imhtml->text_buffer), link, link); |
8091 | 1199 } else if (link=='\0') { |
8177 | 1200 /* Ignore blank lines */ |
8091 | 1201 } else { |
8177 | 1202 /* Special reasons, aka images being put in via other tag, etc. */ |
8091 | 1203 } |
1204 } | |
1205 | |
1206 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1207 } else { | |
1208 gtk_drag_finish(dc, FALSE, FALSE, t); | |
1209 } | |
1210 } | |
1211 | |
4298 | 1212 /* this isn't used yet |
4032 | 1213 static void |
4263 | 1214 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
1215 GtkIMHtmlSmiley *smiley) | |
4032 | 1216 { |
1217 GtkSmileyTree *t = tree; | |
4263 | 1218 const gchar *x = smiley->smile; |
4032 | 1219 gint len = 0; |
1220 | |
1221 while (*x) { | |
1222 gchar *pos; | |
1223 | |
1224 if (!t->values) | |
1225 return; | |
1226 | |
1227 pos = strchr (t->values->str, *x); | |
1228 if (pos) | |
1229 t = t->children [(int) pos - (int) t->values->str]; | |
1230 else | |
1231 return; | |
1232 | |
1233 x++; len++; | |
1234 } | |
1235 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1236 if (t->image) { |
4032 | 1237 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1238 } |
4032 | 1239 } |
4298 | 1240 */ |
1241 | |
4032 | 1242 |
1243 static gint | |
1244 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
1245 const gchar *text) | |
1246 { | |
1247 GtkSmileyTree *t = tree; | |
1248 const gchar *x = text; | |
1249 gint len = 0; | |
8505 | 1250 gchar *amp; |
1251 gint alen; | |
4032 | 1252 |
1253 while (*x) { | |
1254 gchar *pos; | |
1255 | |
1256 if (!t->values) | |
1257 break; | |
1258 | |
8505 | 1259 if(*x == '&' && gtk_imhtml_is_amp_escape(x, &, &alen)) { |
1260 len += alen - strlen(amp); | |
1261 x += alen - strlen(amp); | |
1262 pos = strchr (t->values->str, *amp); | |
1263 } | |
1264 else | |
1265 pos = strchr (t->values->str, *x); | |
1266 | |
4032 | 1267 if (pos) |
7371 | 1268 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1269 else |
1270 break; | |
1271 | |
1272 x++; len++; | |
1273 } | |
1274 | |
1275 if (t->image) | |
1276 return len; | |
1277 | |
1278 return 0; | |
1279 } | |
1280 | |
1281 void | |
4263 | 1282 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
1283 gchar *sml, | |
1284 GtkIMHtmlSmiley *smiley) | |
4032 | 1285 { |
1286 GtkSmileyTree *tree; | |
1287 g_return_if_fail (imhtml != NULL); | |
1288 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
7371 | 1289 |
4032 | 1290 if (sml == NULL) |
1291 tree = imhtml->default_smilies; | |
1292 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
1293 } else { | |
1294 tree = gtk_smiley_tree_new(); | |
4892 | 1295 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 1296 } |
1297 | |
4263 | 1298 gtk_smiley_tree_insert (tree, smiley); |
4032 | 1299 } |
1300 | |
1301 static gboolean | |
1302 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
1303 GSList *fonts, | |
1304 const gchar *text, | |
1305 gint *len) | |
1306 { | |
1307 GtkSmileyTree *tree; | |
5967 | 1308 GtkIMHtmlFontDetail *font; |
4032 | 1309 char *sml = NULL; |
1310 | |
1311 if (fonts) { | |
1312 font = fonts->data; | |
1313 sml = font->sml; | |
1314 } | |
1315 | |
1316 if (sml == NULL) | |
1317 tree = imhtml->default_smilies; | |
1318 else { | |
1319 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
1320 } | |
1321 if (tree == NULL) | |
1322 return FALSE; | |
7371 | 1323 |
8505 | 1324 *len = gtk_smiley_tree_lookup (tree, text); |
4032 | 1325 return (*len > 0); |
1326 } | |
1327 | |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1328 GdkPixbufAnimation * |
4032 | 1329 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
1330 const gchar *sml, | |
1331 const gchar *text) | |
1332 { | |
1333 GtkSmileyTree *t; | |
1334 const gchar *x = text; | |
1335 if (sml == NULL) | |
1336 t = imhtml->default_smilies; | |
7371 | 1337 else |
4032 | 1338 t = g_hash_table_lookup(imhtml->smiley_data, sml); |
7371 | 1339 |
4032 | 1340 |
1341 if (t == NULL) | |
1342 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1343 | |
1344 while (*x) { | |
1345 gchar *pos; | |
1346 | |
1347 if (!t->values) { | |
1348 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1349 } | |
7371 | 1350 |
4032 | 1351 pos = strchr (t->values->str, *x); |
1352 if (pos) { | |
7371 | 1353 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1354 } else { |
1355 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1356 } | |
1357 x++; | |
1358 } | |
1359 | |
4263 | 1360 if (!t->image->icon) |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1361 t->image->icon = gdk_pixbuf_animation_new_from_file(t->image->file, NULL); |
4263 | 1362 |
1363 return t->image->icon; | |
4032 | 1364 } |
4793 | 1365 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 1366 *tag = g_strndup (string, strlen (x)); \ |
1367 *len = strlen (x) + 1; \ | |
1368 return TRUE; \ | |
1369 } \ | |
1370 (*type)++ | |
1428 | 1371 |
4793 | 1372 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 1373 const gchar *c = string + strlen (x " "); \ |
1374 gchar e = '"'; \ | |
1375 gboolean quote = FALSE; \ | |
1376 while (*c) { \ | |
1377 if (*c == '"' || *c == '\'') { \ | |
1378 if (quote && (*c == e)) \ | |
1379 quote = !quote; \ | |
1380 else if (!quote) { \ | |
1381 quote = !quote; \ | |
1382 e = *c; \ | |
1383 } \ | |
1384 } else if (!quote && (*c == '>')) \ | |
1385 break; \ | |
1386 c++; \ | |
1387 } \ | |
1388 if (*c) { \ | |
1389 *tag = g_strndup (string, c - string); \ | |
1390 *len = c - string + 1; \ | |
1391 return TRUE; \ | |
1392 } \ | |
1393 } \ | |
1394 (*type)++ | |
1428 | 1395 |
1396 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1397 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1398 gtk_imhtml_is_amp_escape (const gchar *string, |
7280 | 1399 gchar **replace, |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1400 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1401 { |
7287 | 1402 static char buf[7]; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1403 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1404 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1405 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1406 |
4793 | 1407 if (!g_ascii_strncasecmp (string, "&", 5)) { |
7280 | 1408 *replace = "&"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1409 *length = 5; |
4793 | 1410 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
7280 | 1411 *replace = "<"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1412 *length = 4; |
4793 | 1413 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
7280 | 1414 *replace = ">"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1415 *length = 4; |
4793 | 1416 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
7280 | 1417 *replace = " "; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1418 *length = 6; |
4793 | 1419 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
7280 | 1420 *replace = "©"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1421 *length = 6; |
4793 | 1422 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
7280 | 1423 *replace = "\""; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1424 *length = 6; |
4793 | 1425 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
7280 | 1426 *replace = "®"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1427 *length = 5; |
5093 | 1428 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
7280 | 1429 *replace = "\'"; |
5093 | 1430 *length = 6; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1431 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
1432 guint pound = 0; |
3004 | 1433 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
7287 | 1434 int buflen; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1435 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1436 return FALSE; |
7287 | 1437 buflen = g_unichar_to_utf8((gunichar)pound, buf); |
1438 buf[buflen] = '\0'; | |
7280 | 1439 *replace = buf; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1440 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1441 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1442 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1443 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1444 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1445 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1446 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1447 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1448 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1449 |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1450 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1451 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1452 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1453 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1454 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1455 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1456 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1457 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1458 { |
8061 | 1459 char *close; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1460 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1461 |
8118 | 1462 |
8061 | 1463 if (!(close = strchr (string, '>'))) |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1464 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1465 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1466 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1467 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1468 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1469 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1470 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1471 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1472 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1473 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1474 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1475 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1476 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1477 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1478 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1479 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1480 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1481 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1482 VALID_TAG ("SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1483 VALID_TAG ("/SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1484 VALID_TAG ("SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1485 VALID_TAG ("/SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1486 VALID_TAG ("PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1487 VALID_TAG ("/PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1488 VALID_TAG ("TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1489 VALID_TAG ("/TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1490 VALID_TAG ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1491 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1492 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1493 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1494 VALID_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1495 VALID_TAG ("/P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1496 VALID_TAG ("H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1497 VALID_TAG ("/H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1498 VALID_TAG ("HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1499 VALID_TAG ("/HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1500 VALID_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1501 VALID_TAG ("/BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1502 VALID_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1503 VALID_TAG ("HEAD"); |
2993 | 1504 VALID_TAG ("/HEAD"); |
1505 VALID_TAG ("BINARY"); | |
1506 VALID_TAG ("/BINARY"); | |
5093 | 1507 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1508 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1509 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1510 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1511 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1512 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1513 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1514 VALID_OPT_TAG ("H3"); |
5093 | 1515 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1516 |
5101 | 1517 VALID_TAG ("CITE"); |
1518 VALID_TAG ("/CITE"); | |
1519 VALID_TAG ("EM"); | |
1520 VALID_TAG ("/EM"); | |
1521 VALID_TAG ("STRONG"); | |
1522 VALID_TAG ("/STRONG"); | |
1523 | |
5104 | 1524 VALID_OPT_TAG ("SPAN"); |
1525 VALID_TAG ("/SPAN"); | |
5174 | 1526 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
6982 | 1527 VALID_TAG ("IMG"); |
8026 | 1528 VALID_TAG("SPAN"); |
8061 | 1529 VALID_OPT_TAG("BR"); |
7988 | 1530 |
4793 | 1531 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
1532 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1533 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1534 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1535 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1536 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1537 } |
8118 | 1538 } |
1539 | |
8061 | 1540 *type = -1; |
1541 *len = close - string + 1; | |
1542 *tag = g_strndup(string, *len - 1); | |
1543 return TRUE; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1544 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1545 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1546 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1547 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1548 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1549 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1550 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1551 gchar *e, *a; |
5177 | 1552 gchar *val; |
1553 gint len; | |
7280 | 1554 gchar *c; |
5177 | 1555 GString *ret; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1556 |
4793 | 1557 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1558 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1559 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1560 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1561 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1562 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1563 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1564 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1565 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1566 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1567 |
4793 | 1568 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1569 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1570 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1571 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1572 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1573 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1574 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1575 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1576 while (*e && (*e != *(t - 1))) e++; |
2993 | 1577 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1578 return NULL; |
5177 | 1579 } else |
1580 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1581 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1582 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1583 while (*e && !isspace ((gint) *e)) e++; |
5177 | 1584 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1585 } |
5177 | 1586 |
1587 ret = g_string_new(""); | |
1588 e = val; | |
1589 while(*e) { | |
1590 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
7280 | 1591 ret = g_string_append(ret, c); |
5177 | 1592 e += len; |
1593 } else { | |
1594 ret = g_string_append_c(ret, *e); | |
1595 e++; | |
1596 } | |
1597 } | |
1598 | |
1599 g_free(val); | |
8568 | 1600 |
1601 return g_string_free(ret, FALSE); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1602 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1603 |
8118 | 1604 /* Inline CSS Support - Douglas Thrift */ |
1605 static gchar* | |
1606 gtk_imhtml_get_css_opt (gchar *style, | |
1607 const gchar *opt) | |
1608 { | |
1609 gchar *t = style; | |
1610 gchar *e, *a; | |
1611 gchar *val; | |
1612 gint len; | |
1613 gchar *c; | |
1614 GString *ret; | |
1615 | |
1616 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
8177 | 1617 /* gboolean quote = FALSE; */ |
8118 | 1618 if (*t == '\0') break; |
1619 while (*t && !((*t == ' ') /*&& !quote*/)) { | |
1620 /* if (*t == '\"') | |
8177 | 1621 quote = ! quote; */ |
8118 | 1622 t++; |
1623 } | |
1624 while (*t && (*t == ' ')) t++; | |
1625 } | |
1626 | |
1627 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
1628 t += strlen (opt); | |
1629 } else { | |
1630 return NULL; | |
1631 } | |
1632 | |
1633 /* if ((*t == '\"') || (*t == '\'')) { | |
1634 e = a = ++t; | |
1635 while (*e && (*e != *(t - 1))) e++; | |
1636 if (*e == '\0') { | |
1637 return NULL; | |
1638 } else | |
1639 val = g_strndup(a, e - a); | |
1640 } else { | |
1641 e = a = t; | |
1642 while (*e && !isspace ((gint) *e)) e++; | |
1643 val = g_strndup(a, e - a); | |
1644 }*/ | |
1645 | |
1646 e = a = t; | |
1647 while (*e && *e != ';') e++; | |
1648 val = g_strndup(a, e - a); | |
1649 | |
1650 ret = g_string_new(""); | |
1651 e = val; | |
1652 while(*e) { | |
1653 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
1654 ret = g_string_append(ret, c); | |
1655 e += len; | |
1656 } else { | |
1657 ret = g_string_append_c(ret, *e); | |
1658 e++; | |
1659 } | |
1660 } | |
1661 | |
1662 g_free(val); | |
1663 val = ret->str; | |
1664 g_string_free(ret, FALSE); | |
1665 return val; | |
1666 } | |
3922 | 1667 |
8334 | 1668 static const char *accepted_protocols[] = { |
1669 "http://", | |
1670 "https://", | |
1671 "ftp://" | |
1672 }; | |
1673 | |
1674 static const int accepted_protocols_size = 3; | |
1675 | |
1676 /* returns if the beginning of the text is a protocol. If it is the protocol, returns the length so | |
1677 the caller knows how long the protocol string is. */ | |
1678 int gtk_imhtml_is_protocol(const char *text) | |
1679 { | |
1680 gint i; | |
1681 | |
1682 for(i=0; i<accepted_protocols_size; i++){ | |
1683 if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ | |
1684 return strlen(accepted_protocols[i]); | |
1685 } | |
1686 } | |
1687 return 0; | |
1688 } | |
1689 | |
8677 | 1690 /* |
1691 <KingAnt> marv: The two IM image functions in oscar are gaim_odc_send_im and gaim_odc_incoming | |
1692 | |
1693 | |
1694 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) | |
1695 [19:59] <KingAnt> marv: I think the image tag used by the core is something like <img id="#"/> | |
1696 [19:59] Ro0tSiEgE robert42 RobFlynn Robot101 ross22 roz | |
1697 [20:00] <KingAnt> marv: Where the ID is the what is returned when you add the image to the imgstore using gaim_imgstore_add | |
1698 [20:00] <marv> Robot101: so how does the image get passed to serv_got_im() and serv_send_im()? just as the <img id="#" and then the prpl looks it up from the store? | |
1699 [20:00] <KingAnt> marv: Right | |
1700 [20:00] <marv> alright | |
1701 | |
1702 Here's my plan with IMImages. make gtk_imhtml_[append|insert]_text_with_images instead just | |
1703 gtkimhtml_[append|insert]_text (hrm maybe it should be called html instead of text), add a | |
1704 function for gaim to register for look up images, i.e. gtk_imhtml_set_get_img_fnc, so that | |
1705 images can be looked up like that, instead of passing a GSList of them. | |
1706 */ | |
1707 | |
1708 void gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | |
1709 const gchar *text, | |
1710 GtkIMHtmlOptions options, | |
1711 GSList *unused) | |
1428 | 1712 { |
8677 | 1713 GtkTextIter iter, ins, sel; |
1714 GdkRectangle rect; | |
1715 int y, height, ins_offset = 0, sel_offset = 0; | |
1716 gboolean fixins = FALSE, fixsel = FALSE; | |
1717 | |
1718 g_return_if_fail (imhtml != NULL); | |
1719 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
1720 g_return_if_fail (text != NULL); | |
1721 | |
1722 | |
1723 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1724 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
1725 if (gtk_text_iter_equal(&iter, &ins) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1726 fixins = TRUE; | |
1727 ins_offset = gtk_text_iter_get_offset(&ins); | |
1728 } | |
1729 | |
1730 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &sel, gtk_text_buffer_get_selection_bound(imhtml->text_buffer)); | |
1731 if (gtk_text_iter_equal(&iter, &sel) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1732 fixsel = TRUE; | |
1733 sel_offset = gtk_text_iter_get_offset(&sel); | |
1734 } | |
1735 | |
1736 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1737 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1738 | |
1739 | |
1740 if(((y + height) - (rect.y + rect.height)) > height | |
1741 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1742 options |= GTK_IMHTML_NO_SCROLL; | |
1743 } | |
1744 | |
1745 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); | |
1746 | |
1747 if (fixins) { | |
1748 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins, ins_offset); | |
1749 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_insert(imhtml->text_buffer), &ins); | |
1750 } | |
1751 | |
1752 if (fixsel) { | |
1753 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &sel, sel_offset); | |
1754 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_selection_bound(imhtml->text_buffer), &sel); | |
1755 } | |
1756 | |
1757 if (!(options & GTK_IMHTML_NO_SCROLL)) { | |
8729 | 1758 gtk_imhtml_scroll_to_end(imhtml); |
8677 | 1759 } |
1760 } | |
1761 | |
8729 | 1762 void gtk_imhtml_scroll_to_end(GtkIMHtml *imhtml) |
1763 { | |
1764 GtkTextIter iter; | |
1765 /* If this seems backwards at first glance, well it's not. | |
1766 * It means scroll such that the mark is closest to the top, | |
1767 * and closest to the right as possible. Remember kids, you have | |
1768 * to scroll left to move a given spot closest to the right, | |
1769 * and scroll down to move a spot closest to the top. | |
1770 */ | |
1771 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1772 gtk_text_iter_set_line_offset(&iter, 0); | |
1773 gtk_text_buffer_move_mark(imhtml->text_buffer, imhtml->scrollpoint, &iter); | |
1774 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), imhtml->scrollpoint, | |
1775 0, TRUE, 1.0, 0.0); | |
1776 } | |
1777 | |
8677 | 1778 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, |
1779 const gchar *text, | |
1780 GtkIMHtmlOptions options, | |
1781 GtkTextIter *iter) | |
1782 { | |
8061 | 1783 GdkRectangle rect; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1784 gint pos = 0; |
3922 | 1785 gchar *ws; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1786 gchar *tag; |
3922 | 1787 gchar *bg = NULL; |
6982 | 1788 gint len; |
4032 | 1789 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1790 gint type; |
3922 | 1791 const gchar *c; |
7280 | 1792 gchar *amp; |
8334 | 1793 gint len_protocol; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1794 |
1428 | 1795 guint bold = 0, |
1796 italics = 0, | |
1797 underline = 0, | |
1798 strike = 0, | |
1799 sub = 0, | |
1800 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1801 title = 0, |
8061 | 1802 pre = 0; |
1428 | 1803 |
3922 | 1804 GSList *fonts = NULL; |
8506 | 1805 GObject *object; |
8061 | 1806 GtkIMHtmlScalable *scalable = NULL; |
8677 | 1807 |
1808 g_return_if_fail (imhtml != NULL); | |
1809 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
1810 g_return_if_fail (text != NULL); | |
3922 | 1811 c = text; |
6982 | 1812 len = strlen(text); |
3922 | 1813 ws = g_malloc(len + 1); |
1814 ws[0] = 0; | |
1428 | 1815 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1816 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1817 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1818 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1819 pos++; |
8061 | 1820 ws[wpos] = '\0'; |
1821 switch (type) | |
3922 | 1822 { |
1823 case 1: /* B */ | |
1824 case 2: /* BOLD */ | |
5101 | 1825 case 54: /* STRONG */ |
8677 | 1826 |
1827 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
1828 | |
1829 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD)) | |
8061 | 1830 gtk_imhtml_toggle_bold(imhtml); |
3922 | 1831 bold++; |
8061 | 1832 ws[0] = '\0'; wpos = 0; |
3922 | 1833 break; |
1834 case 3: /* /B */ | |
1835 case 4: /* /BOLD */ | |
5101 | 1836 case 55: /* /STRONG */ |
8677 | 1837 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1838 ws[0] = '\0'; wpos = 0; |
1839 | |
3922 | 1840 if (bold) |
1841 bold--; | |
8677 | 1842 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD) && !imhtml->wbfo) |
8061 | 1843 gtk_imhtml_toggle_bold(imhtml); |
3922 | 1844 break; |
1845 case 5: /* I */ | |
1846 case 6: /* ITALIC */ | |
5101 | 1847 case 52: /* EM */ |
8677 | 1848 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1849 ws[0] = '\0'; wpos = 0; |
8677 | 1850 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC)) |
8061 | 1851 gtk_imhtml_toggle_italic(imhtml); |
3922 | 1852 italics++; |
1853 break; | |
1854 case 7: /* /I */ | |
1855 case 8: /* /ITALIC */ | |
5101 | 1856 case 53: /* /EM */ |
8677 | 1857 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1858 ws[0] = '\0'; wpos = 0; |
3922 | 1859 if (italics) |
1860 italics--; | |
8677 | 1861 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC) && !imhtml->wbfo) |
8061 | 1862 gtk_imhtml_toggle_italic(imhtml); |
3922 | 1863 break; |
1864 case 9: /* U */ | |
1865 case 10: /* UNDERLINE */ | |
8677 | 1866 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1867 ws[0] = '\0'; wpos = 0; |
8677 | 1868 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
8061 | 1869 gtk_imhtml_toggle_underline(imhtml); |
3922 | 1870 underline++; |
1871 break; | |
1872 case 11: /* /U */ | |
1873 case 12: /* /UNDERLINE */ | |
8677 | 1874 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1875 ws[0] = '\0'; wpos = 0; |
3922 | 1876 if (underline) |
1877 underline--; | |
8677 | 1878 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE) && !imhtml->wbfo) |
8061 | 1879 gtk_imhtml_toggle_underline(imhtml); |
3922 | 1880 break; |
1881 case 13: /* S */ | |
1882 case 14: /* STRIKE */ | |
8677 | 1883 /* FIXME: reimplement this */ |
3922 | 1884 strike++; |
1885 break; | |
1886 case 15: /* /S */ | |
1887 case 16: /* /STRIKE */ | |
8677 | 1888 /* FIXME: reimplement this */ |
3922 | 1889 if (strike) |
1890 strike--; | |
1891 break; | |
1892 case 17: /* SUB */ | |
8677 | 1893 /* FIXME: reimpliment this */ |
3922 | 1894 sub++; |
1895 break; | |
1896 case 18: /* /SUB */ | |
8677 | 1897 /* FIXME: reimpliment this */ |
3922 | 1898 if (sub) |
1899 sub--; | |
1900 break; | |
1901 case 19: /* SUP */ | |
8677 | 1902 /* FIXME: reimplement this */ |
3922 | 1903 sup++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1904 break; |
3922 | 1905 case 20: /* /SUP */ |
8677 | 1906 /* FIXME: reimplement this */ |
3922 | 1907 if (sup) |
1908 sup--; | |
1909 break; | |
1910 case 21: /* PRE */ | |
8677 | 1911 /* FIXME: reimplement this */ |
3922 | 1912 pre++; |
1913 break; | |
1914 case 22: /* /PRE */ | |
8677 | 1915 /* FIXME: reimplement this */ |
3922 | 1916 if (pre) |
1917 pre--; | |
1918 break; | |
1919 case 23: /* TITLE */ | |
8677 | 1920 /* FIXME: what was this supposed to do anyway? */ |
3922 | 1921 title++; |
1922 break; | |
1923 case 24: /* /TITLE */ | |
8677 | 1924 /* FIXME: make this undo whatever 23 was supposed to do */ |
3922 | 1925 if (title) { |
1926 if (options & GTK_IMHTML_NO_TITLE) { | |
1927 wpos = 0; | |
1928 ws [wpos] = '\0'; | |
1929 } | |
1930 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1931 } |
3922 | 1932 break; |
1933 case 25: /* BR */ | |
5174 | 1934 case 58: /* BR/ */ |
8061 | 1935 case 61: /* BR (opt) */ |
3922 | 1936 ws[wpos] = '\n'; |
1937 wpos++; | |
6982 | 1938 break; |
3922 | 1939 case 26: /* HR */ |
1940 case 42: /* HR (opt) */ | |
8726 | 1941 { |
1942 int minus; | |
1943 | |
3922 | 1944 ws[wpos++] = '\n'; |
8677 | 1945 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1946 | |
5967 | 1947 scalable = gtk_imhtml_hr_new(); |
8061 | 1948 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
8677 | 1949 scalable->add_to(scalable, imhtml, iter); |
8726 | 1950 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + |
1951 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
1952 scalable->scale(scalable, rect.width - minus, rect.height); | |
8061 | 1953 imhtml->scalables = g_list_append(imhtml->scalables, scalable); |
1954 ws[0] = '\0'; wpos = 0; | |
7942 | 1955 ws[wpos++] = '\n'; |
8061 | 1956 |
3922 | 1957 break; |
8726 | 1958 } |
3922 | 1959 case 27: /* /FONT */ |
8677 | 1960 if (fonts && !imhtml->wbfo) { |
5967 | 1961 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 1962 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1963 ws[0] = '\0'; wpos = 0; |
8177 | 1964 /* NEW_BIT (NEW_TEXT_BIT); */ |
8677 | 1965 |
8698 | 1966 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) { |
8061 | 1967 gtk_imhtml_toggle_fontface(imhtml, NULL); |
3922 | 1968 g_free (font->face); |
8061 | 1969 } |
8698 | 1970 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
8061 | 1971 gtk_imhtml_toggle_forecolor(imhtml, NULL); |
3922 | 1972 g_free (font->fore); |
8061 | 1973 } |
8698 | 1974 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
8061 | 1975 gtk_imhtml_toggle_backcolor(imhtml, NULL); |
3922 | 1976 g_free (font->back); |
8061 | 1977 } |
4032 | 1978 if (font->sml) |
1979 g_free (font->sml); | |
3922 | 1980 g_free (font); |
8309 | 1981 |
8698 | 1982 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 1983 gtk_imhtml_font_set_size(imhtml, 3); |
1984 | |
1985 fonts = fonts->next; | |
1986 if (fonts) { | |
1987 GtkIMHtmlFontDetail *font = fonts->data; | |
8677 | 1988 |
8698 | 1989 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8309 | 1990 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8698 | 1991 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8309 | 1992 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8698 | 1993 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
8309 | 1994 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8698 | 1995 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 1996 gtk_imhtml_font_set_size(imhtml, font->size); |
1997 } | |
3922 | 1998 } |
8309 | 1999 break; |
3922 | 2000 case 28: /* /A */ |
8677 | 2001 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2002 gtk_imhtml_toggle_link(imhtml, NULL); | |
2003 ws[0] = '\0'; wpos = 0; | |
8061 | 2004 break; |
8118 | 2005 |
3922 | 2006 case 29: /* P */ |
2007 case 30: /* /P */ | |
2008 case 31: /* H3 */ | |
2009 case 32: /* /H3 */ | |
2010 case 33: /* HTML */ | |
2011 case 34: /* /HTML */ | |
2012 case 35: /* BODY */ | |
2013 case 36: /* /BODY */ | |
2014 case 37: /* FONT */ | |
2015 case 38: /* HEAD */ | |
2016 case 39: /* /HEAD */ | |
6982 | 2017 case 40: /* BINARY */ |
2018 case 41: /* /BINARY */ | |
3922 | 2019 break; |
2020 case 43: /* FONT (opt) */ | |
2021 { | |
4032 | 2022 gchar *color, *back, *face, *size, *sml; |
5967 | 2023 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 2024 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
2025 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
2026 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
2027 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 2028 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
2029 if (!(color || back || face || size || sml)) | |
3922 | 2030 break; |
8061 | 2031 |
8677 | 2032 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2033 ws[0] = '\0'; wpos = 0; |
2034 | |
5967 | 2035 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 2036 if (fonts) |
2037 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2038 |
8677 | 2039 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
3922 | 2040 font->fore = color; |
8061 | 2041 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8677 | 2042 } |
8309 | 2043 //else if (oldfont && oldfont->fore) |
2044 // font->fore = g_strdup(oldfont->fore); | |
8677 | 2045 |
2046 if (back && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { | |
3922 | 2047 font->back = back; |
8061 | 2048 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8309 | 2049 } |
2050 //else if (oldfont && oldfont->back) | |
2051 // font->back = g_strdup(oldfont->back); | |
8677 | 2052 |
2053 if (face && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) { | |
3922 | 2054 font->face = face; |
8061 | 2055 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8309 | 2056 } |
2057 //else if (oldfont && oldfont->face) | |
2058 // font->face = g_strdup(oldfont->face); | |
4032 | 2059 |
2060 if (sml) | |
2061 font->sml = sml; | |
2062 else if (oldfont && oldfont->sml) | |
2063 font->sml = g_strdup(oldfont->sml); | |
2064 | |
8677 | 2065 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) { |
3922 | 2066 if (*size == '+') { |
2067 sscanf (size + 1, "%hd", &font->size); | |
2068 font->size += 3; | |
2069 } else if (*size == '-') { | |
2070 sscanf (size + 1, "%hd", &font->size); | |
2071 font->size = MAX (0, 3 - font->size); | |
2072 } else if (isdigit (*size)) { | |
2073 sscanf (size, "%hd", &font->size); | |
8061 | 2074 } |
6042 | 2075 if (font->size > 100) |
2076 font->size = 100; | |
3922 | 2077 } else if (oldfont) |
2078 font->size = oldfont->size; | |
8309 | 2079 else |
2080 font->size = 3; | |
8698 | 2081 if ((imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
2082 gtk_imhtml_font_set_size(imhtml, font->size); | |
3922 | 2083 g_free(size); |
2084 fonts = g_slist_prepend (fonts, font); | |
2085 } | |
2086 break; | |
2087 case 44: /* BODY (opt) */ | |
2088 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
2089 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
8677 | 2090 if (bgcolor && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
2091 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2092 ws[0] = '\0'; wpos = 0; |
8177 | 2093 /* NEW_BIT(NEW_TEXT_BIT); */ |
3922 | 2094 if (bg) |
2095 g_free(bg); | |
2096 bg = bgcolor; | |
8061 | 2097 gtk_imhtml_toggle_backcolor(imhtml, bg); |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
2098 } |
1428 | 2099 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2100 break; |
3922 | 2101 case 45: /* A (opt) */ |
2102 { | |
2103 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
8677 | 2104 if (href && (imhtml->format_functions & GTK_IMHTML_LINK)) { |
2105 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2106 ws[0] = '\0'; wpos = 0; |
8677 | 2107 gtk_imhtml_toggle_link(imhtml, href); |
3922 | 2108 } |
2993 | 2109 } |
3922 | 2110 break; |
4895 | 2111 case 46: /* IMG (opt) */ |
6982 | 2112 case 59: /* IMG */ |
4895 | 2113 { |
8677 | 2114 #if 0 |
2115 /* disabling this for now, it's easy to add it back... */ | |
6982 | 2116 GdkPixbuf *img = NULL; |
2117 const gchar *filename = NULL; | |
4895 | 2118 |
8677 | 2119 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) |
2120 break; | |
2121 | |
6982 | 2122 if (images && images->data) { |
2123 img = images->data; | |
2124 images = images->next; | |
2125 filename = g_object_get_data(G_OBJECT(img), "filename"); | |
2126 g_object_ref(G_OBJECT(img)); | |
2127 } else { | |
2128 img = gtk_widget_render_icon(GTK_WIDGET(imhtml), | |
2129 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, | |
2130 "gtkimhtml-missing-image"); | |
2131 } | |
4895 | 2132 |
6982 | 2133 scalable = gtk_imhtml_image_new(img, filename); |
8177 | 2134 /* NEW_BIT(NEW_SCALABLE_BIT); */ |
8677 | 2135 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
2136 scalable->add_to(scalable, imhtml, iter); | |
2137 scalable->scale(scalable, rect.width, rect.height); | |
2138 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
2139 | |
6982 | 2140 g_object_unref(G_OBJECT(img)); |
8677 | 2141 #endif |
4895 | 2142 } |
3922 | 2143 case 47: /* P (opt) */ |
2144 case 48: /* H3 (opt) */ | |
5093 | 2145 case 49: /* HTML (opt) */ |
5101 | 2146 case 50: /* CITE */ |
2147 case 51: /* /CITE */ | |
8026 | 2148 case 56: /* SPAN (opt) */ |
8118 | 2149 /* Inline CSS Support - Douglas Thrift |
2150 * | |
2151 * color | |
8686 | 2152 * background |
8118 | 2153 * font-family |
2154 * font-size | |
8686 | 2155 * text-decoration: underline |
8118 | 2156 */ |
2157 { | |
8686 | 2158 gchar *style, *color, *background, *family, *size; |
2159 gchar *textdec; | |
8118 | 2160 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
2161 style = gtk_imhtml_get_html_opt (tag, "style="); | |
2162 | |
2163 if (!style) break; | |
2164 | |
2165 color = gtk_imhtml_get_css_opt (style, "color: "); | |
8686 | 2166 background = gtk_imhtml_get_css_opt (style, "background: "); |
8118 | 2167 family = gtk_imhtml_get_css_opt (style, |
2168 "font-family: "); | |
2169 size = gtk_imhtml_get_css_opt (style, "font-size: "); | |
8686 | 2170 textdec = gtk_imhtml_get_css_opt (style, "text-decoration: "); |
2171 | |
2172 if (!(color || family || size || background || textdec)) { | |
8120 | 2173 g_free(style); |
2174 break; | |
2175 } | |
8118 | 2176 |
8677 | 2177 |
2178 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8118 | 2179 ws[0] = '\0'; wpos = 0; |
8177 | 2180 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2181 |
2182 font = g_new0 (GtkIMHtmlFontDetail, 1); | |
2183 if (fonts) | |
2184 oldfont = fonts->data; | |
2185 | |
8677 | 2186 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8686 | 2187 { |
8118 | 2188 font->fore = color; |
8686 | 2189 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
2190 } | |
8118 | 2191 else if (oldfont && oldfont->fore) |
2192 font->fore = g_strdup(oldfont->fore); | |
2193 | |
8686 | 2194 if (background && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
2195 { | |
2196 font->back = background; | |
2197 gtk_imhtml_toggle_backcolor(imhtml, font->back); | |
2198 } | |
2199 else if (oldfont && oldfont->back) | |
8118 | 2200 font->back = g_strdup(oldfont->back); |
2201 | |
8677 | 2202 if (family && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8686 | 2203 { |
8118 | 2204 font->face = family; |
8686 | 2205 gtk_imhtml_toggle_fontface(imhtml, font->face); |
2206 } | |
8118 | 2207 else if (oldfont && oldfont->face) |
2208 font->face = g_strdup(oldfont->face); | |
2209 if (font->face && (atoi(font->face) > 100)) { | |
8677 | 2210 /* WTF is this? */ |
8118 | 2211 g_free(font->face); |
2212 font->face = g_strdup("100"); | |
2213 } | |
2214 | |
2215 if (oldfont && oldfont->sml) | |
2216 font->sml = g_strdup(oldfont->sml); | |
2217 | |
8677 | 2218 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_SHRINK|GTK_IMHTML_GROW))) { |
8686 | 2219 if (g_ascii_strcasecmp(size, "xx-small") == 0) |
2220 font->size = 1; | |
2221 else if (g_ascii_strcasecmp(size, "smaller") == 0 | |
2222 || g_ascii_strcasecmp(size, "x-small") == 0) | |
8118 | 2223 font->size = 2; |
8686 | 2224 else if (g_ascii_strcasecmp(size, "larger") == 0 |
2225 || g_ascii_strcasecmp(size, "medium") == 0) | |
8118 | 2226 font->size = 4; |
8686 | 2227 else if (g_ascii_strcasecmp(size, "large") == 0) |
2228 font->size = 5; | |
2229 else if (g_ascii_strcasecmp(size, "x-large") == 0) | |
2230 font->size = 6; | |
2231 else if (g_ascii_strcasecmp(size, "xx-large") == 0) | |
2232 font->size = 7; | |
8118 | 2233 else |
2234 font->size = 3; | |
8686 | 2235 gtk_imhtml_font_set_size(imhtml, font->size); |
2236 } | |
2237 else if (oldfont) | |
2238 { | |
2239 font->size = oldfont->size; | |
2240 } | |
2241 | |
2242 if (oldfont) | |
2243 { | |
2244 font->underline = oldfont->underline; | |
2245 } | |
2246 if (textdec && font->underline != 1 | |
2247 && g_ascii_strcasecmp(size, "underline") == 0 | |
2248 && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) | |
2249 { | |
2250 gtk_imhtml_toggle_underline(imhtml); | |
2251 font->underline = 1; | |
2252 } | |
8118 | 2253 |
2254 g_free(style); | |
2255 g_free(size); | |
2256 fonts = g_slist_prepend (fonts, font); | |
2257 } | |
2258 break; | |
5104 | 2259 case 57: /* /SPAN */ |
8118 | 2260 /* Inline CSS Support - Douglas Thrift */ |
8677 | 2261 if (fonts && !imhtml->wbfo) { |
8686 | 2262 GtkIMHtmlFontDetail *oldfont = NULL; |
8118 | 2263 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2264 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8118 | 2265 ws[0] = '\0'; wpos = 0; |
8177 | 2266 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2267 fonts = g_slist_remove (fonts, font); |
8692 | 2268 if (fonts) |
2269 oldfont = fonts->data; | |
2270 | |
2271 if (!oldfont) { | |
2272 gtk_imhtml_font_set_size(imhtml, 3); | |
2273 if (font->underline) | |
2274 gtk_imhtml_toggle_underline(imhtml); | |
2275 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
2276 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
2277 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
8686 | 2278 } |
8692 | 2279 else |
8686 | 2280 { |
8692 | 2281 |
2282 if (font->size != oldfont->size) | |
2283 gtk_imhtml_font_set_size(imhtml, oldfont->size); | |
2284 | |
2285 if (font->underline != oldfont->underline) | |
2286 gtk_imhtml_toggle_underline(imhtml); | |
2287 | |
2288 if (!oldfont->face || strcmp(font->face, oldfont->face) != 0) | |
2289 gtk_imhtml_toggle_fontface(imhtml, oldfont->face); | |
2290 | |
2291 if (!oldfont->fore || strcmp(font->fore, oldfont->fore) != 0) | |
2292 gtk_imhtml_toggle_forecolor(imhtml, oldfont->fore); | |
2293 | |
2294 if (!oldfont->back || strcmp(font->back, oldfont->back) != 0) | |
2295 gtk_imhtml_toggle_backcolor(imhtml, oldfont->back); | |
8686 | 2296 } |
8692 | 2297 |
2298 g_free (font->face); | |
2299 g_free (font->fore); | |
2300 g_free (font->back); | |
2301 g_free (font->sml); | |
2302 | |
8118 | 2303 g_free (font); |
2304 } | |
2305 break; | |
8026 | 2306 case 60: /* SPAN */ |
2993 | 2307 break; |
8061 | 2308 case 62: /* comment */ |
8177 | 2309 /* NEW_BIT (NEW_TEXT_BIT); */ |
8317 | 2310 ws[wpos] = '\0'; |
8677 | 2311 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2312 | |
6124 | 2313 if (imhtml->show_comments) |
2314 wpos = g_snprintf (ws, len, "%s", tag); | |
8177 | 2315 /* NEW_BIT (NEW_COMMENT_BIT); */ |
3922 | 2316 break; |
2317 default: | |
6882 | 2318 break; |
2993 | 2319 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2320 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2321 pos += tlen; |
4138 | 2322 if(tag) |
2323 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
8473 | 2324 } else if (imhtml->show_smileys && (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen))) { |
2325 GtkIMHtmlFontDetail *fd; | |
2326 | |
2327 gchar *sml = NULL; | |
2328 if (fonts) { | |
2329 fd = fonts->data; | |
2330 sml = fd->sml; | |
2331 } | |
8677 | 2332 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8505 | 2333 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
8473 | 2334 |
8677 | 2335 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, ws, iter); |
8473 | 2336 |
8505 | 2337 c += smilelen; |
2338 pos += smilelen; | |
8473 | 2339 wpos = 0; |
2340 ws[0] = 0; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2341 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
7280 | 2342 while(*amp) { |
2343 ws [wpos++] = *amp++; | |
2344 } | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2345 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2346 pos += tlen; |
1428 | 2347 } else if (*c == '\n') { |
2348 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 2349 ws[wpos] = '\n'; |
2350 wpos++; | |
8677 | 2351 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2352 ws[0] = '\0'; |
2353 wpos = 0; | |
8177 | 2354 /* NEW_BIT (NEW_TEXT_BIT); */ |
1428 | 2355 } |
2356 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2357 pos++; |
8334 | 2358 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
2359 while(len_protocol--){ | |
8677 | 2360 /* Skip the next len_protocol characters, but make sure they're |
8334 | 2361 copied into the ws array. |
2362 */ | |
2363 ws [wpos++] = *c++; | |
2364 pos++; | |
2365 } | |
8061 | 2366 } else if (*c) { |
1428 | 2367 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2368 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2369 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2370 break; |
1428 | 2371 } |
2372 } | |
8677 | 2373 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2374 ws[0] = '\0'; wpos = 0; |
2375 | |
8177 | 2376 /* NEW_BIT(NEW_TEXT_BIT); */ |
8061 | 2377 |
4032 | 2378 while (fonts) { |
5967 | 2379 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 2380 fonts = g_slist_remove (fonts, font); |
2381 if (font->face) | |
2382 g_free (font->face); | |
2383 if (font->fore) | |
2384 g_free (font->fore); | |
2385 if (font->back) | |
2386 g_free (font->back); | |
2387 if (font->sml) | |
2388 g_free (font->sml); | |
2389 g_free (font); | |
8677 | 2390 //if (str) |
2391 // str = g_string_append (str, "</FONT>"); | |
4032 | 2392 } |
8677 | 2393 #if 0 |
3922 | 2394 if (str) { |
1428 | 2395 while (bold) { |
8677 | 2396 // str = g_string_append (str, "</B>"); |
1428 | 2397 bold--; |
2398 } | |
2399 while (italics) { | |
8677 | 2400 // str = g_string_append (str, "</I>"); |
1428 | 2401 italics--; |
2402 } | |
2403 while (underline) { | |
8677 | 2404 //str = g_string_append (str, "</U>"); |
1428 | 2405 underline--; |
2406 } | |
2407 while (strike) { | |
8677 | 2408 //str = g_string_append (str, "</S>"); |
1428 | 2409 strike--; |
2410 } | |
2411 while (sub) { | |
8677 | 2412 //str = g_string_append (str, "</SUB>"); |
1428 | 2413 sub--; |
2414 } | |
2415 while (sup) { | |
8677 | 2416 //str = g_string_append (str, "</SUP>"); |
1428 | 2417 sup--; |
2418 } | |
2419 while (title) { | |
8677 | 2420 //str = g_string_append (str, "</TITLE>"); |
1428 | 2421 title--; |
2422 } | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2423 while (pre) { |
8677 | 2424 //str = g_string_append (str, "</PRE>"); |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2425 pre--; |
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2426 } |
1428 | 2427 } |
8677 | 2428 #endif |
4032 | 2429 g_free (ws); |
4630 | 2430 if(bg) |
2431 g_free(bg); | |
8677 | 2432 |
2433 if (!imhtml->wbfo) | |
8698 | 2434 gtk_imhtml_close_tags(imhtml, iter); |
8506 | 2435 |
2436 object = g_object_ref(G_OBJECT(imhtml)); | |
2437 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | |
2438 g_object_unref(object); | |
2439 | |
3922 | 2440 } |
2441 | |
4892 | 2442 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
2443 { | |
4288 | 2444 g_hash_table_destroy(imhtml->smiley_data); |
2445 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 2446 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 2447 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 2448 imhtml->default_smilies = gtk_smiley_tree_new(); |
2449 } | |
8481 | 2450 |
3922 | 2451 void gtk_imhtml_show_smileys (GtkIMHtml *imhtml, |
4253 | 2452 gboolean show) |
2453 { | |
2454 imhtml->show_smileys = show; | |
2455 } | |
3922 | 2456 |
2457 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, | |
4253 | 2458 gboolean show) |
2459 { | |
6124 | 2460 imhtml->show_comments = show; |
4253 | 2461 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2462 |
8456 | 2463 void gtk_imhtml_html_shortcuts (GtkIMHtml *imhtml, |
2464 gboolean allow) | |
2465 { | |
2466 imhtml->html_shortcuts = allow; | |
2467 } | |
2468 | |
2469 void gtk_imhtml_smiley_shortcuts (GtkIMHtml *imhtml, | |
2470 gboolean allow) | |
2471 { | |
2472 imhtml->smiley_shortcuts = allow; | |
2473 } | |
2474 | |
2475 void | |
2476 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, gchar *protocol_name) { | |
2477 imhtml->protocol_name = protocol_name; | |
2478 } | |
2479 | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2480 void |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2481 gtk_imhtml_clear (GtkIMHtml *imhtml) |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2482 { |
7991 | 2483 GList *del; |
3922 | 2484 GtkTextIter start, end; |
8427 | 2485 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
7991 | 2486 |
3922 | 2487 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
2488 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
2489 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
7991 | 2490 |
2491 for(del = imhtml->scalables; del; del = del->next) { | |
2492 GtkIMHtmlScalable *scale = del->data; | |
2493 scale->free(scale); | |
2494 } | |
2495 g_list_free(imhtml->scalables); | |
2496 imhtml->scalables = NULL; | |
8061 | 2497 |
8719 | 2498 gtk_imhtml_close_tags(imhtml, &start); |
8481 | 2499 |
8427 | 2500 g_signal_emit(object, signals[CLEAR_FORMAT], 0); |
2501 g_object_unref(object); | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2502 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
2503 |
4046 | 2504 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
2505 { | |
5282 | 2506 GdkRectangle rect; |
2507 GtkTextIter iter; | |
4046 | 2508 |
5282 | 2509 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
2510 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
2511 rect.y - rect.height); | |
2512 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
8061 | 2513 |
4046 | 2514 } |
5282 | 2515 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
2516 { | |
2517 GdkRectangle rect; | |
2518 GtkTextIter iter; | |
2519 | |
2520 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
2521 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
2522 rect.y + rect.height); | |
2523 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
2524 } | |
4735 | 2525 |
5967 | 2526 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
6982 | 2527 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) |
4735 | 2528 { |
5967 | 2529 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 2530 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 2531 |
5967 | 2532 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
2533 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
2534 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 2535 |
2536 im_image->pixbuf = img; | |
5012 | 2537 im_image->image = image; |
4895 | 2538 im_image->width = gdk_pixbuf_get_width(img); |
2539 im_image->height = gdk_pixbuf_get_height(img); | |
2540 im_image->mark = NULL; | |
6982 | 2541 im_image->filename = filename ? g_strdup(filename) : NULL; |
4895 | 2542 |
5046 | 2543 g_object_ref(img); |
4895 | 2544 return GTK_IMHTML_SCALABLE(im_image); |
2545 } | |
2546 | |
5967 | 2547 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 2548 { |
5967 | 2549 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 2550 |
2551 if(image->width > width || image->height > height){ | |
2552 GdkPixbuf *new_image = NULL; | |
2553 float factor; | |
2554 int new_width = image->width, new_height = image->height; | |
2555 | |
8588 | 2556 if(image->width > (width - 2)){ |
4895 | 2557 factor = (float)(width)/image->width; |
2558 new_width = width; | |
2559 new_height = image->height * factor; | |
2560 } | |
8588 | 2561 if(new_height >= (height - 2)){ |
4895 | 2562 factor = (float)(height)/new_height; |
2563 new_height = height; | |
2564 new_width = new_width * factor; | |
2565 } | |
2566 | |
5046 | 2567 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 2568 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 2569 g_object_unref(G_OBJECT(new_image)); |
2570 } | |
2571 } | |
2572 | |
5012 | 2573 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
2574 { | |
2575 const gchar *filename = gtk_file_selection_get_filename(sel); | |
5967 | 2576 gchar *dirname; |
2577 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
5012 | 2578 gchar *type = NULL; |
5019 | 2579 GError *error = NULL; |
5015 | 2580 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 2581 GSList *formats = gdk_pixbuf_get_formats(); |
6162 | 2582 #else |
2583 char *basename = g_path_get_basename(filename); | |
2584 char *ext = strrchr(basename, '.'); | |
5959 | 2585 #endif |
5012 | 2586 |
5967 | 2587 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
2588 /* append a / if needed */ | |
2589 if (filename[strlen(filename) - 1] != '/') { | |
2590 dirname = g_strconcat(filename, "/", NULL); | |
2591 } else { | |
2592 dirname = g_strdup(filename); | |
2593 } | |
2594 gtk_file_selection_set_filename(sel, dirname); | |
2595 g_free(dirname); | |
5959 | 2596 return; |
5967 | 2597 } |
5959 | 2598 |
2599 #if GTK_CHECK_VERSION(2,2,0) | |
5012 | 2600 while(formats){ |
2601 GdkPixbufFormat *format = formats->data; | |
2602 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
2603 gpointer p = extensions; | |
2604 | |
2605 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
2606 gchar *fmt_ext = extensions[0]; | |
2607 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
2608 | |
2609 if(!strcmp(fmt_ext, file_ext)){ | |
2610 type = gdk_pixbuf_format_get_name(format); | |
2611 break; | |
2612 } | |
2613 | |
2614 extensions++; | |
2615 } | |
2616 | |
2617 g_strfreev(p); | |
2618 | |
2619 if(type) | |
2620 break; | |
2621 | |
2622 formats = formats->next; | |
2623 } | |
2624 | |
5020 | 2625 g_slist_free(formats); |
2626 #else | |
2627 /* this is really ugly code, but I think it will work */ | |
2628 if(ext) { | |
2629 ext++; | |
2630 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
2631 type = g_strdup("jpeg"); | |
2632 else if(!g_ascii_strcasecmp(ext, "png")) | |
2633 type = g_strdup("png"); | |
2634 } | |
2635 | |
2636 g_free(basename); | |
2637 #endif | |
2638 | |
5012 | 2639 /* If I can't find a valid type, I will just tell the user about it and then assume |
2640 it's a png */ | |
2641 if(!type){ | |
2642 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
5967 | 2643 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
5012 | 2644 type = g_strdup("png"); |
2645 } | |
2646 | |
5046 | 2647 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 2648 |
2649 if(error){ | |
2650 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
2651 _("Error saving image: %s"), error->message); | |
2652 g_error_free(error); | |
2653 } | |
2654 | |
2655 g_free(type); | |
2656 } | |
2657 | |
5967 | 2658 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
5012 | 2659 { |
5967 | 2660 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
5012 | 2661 |
6982 | 2662 if (image->filename) |
2663 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
5967 | 2664 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
5012 | 2665 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
2666 G_CALLBACK(write_img_to_file), sel); | |
2667 | |
2668 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
2669 G_CALLBACK(gtk_widget_destroy), sel); | |
2670 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
8061 | 2671 G_CALLBACK(gtk_widget_destroy), sel); |
5012 | 2672 |
2673 gtk_widget_show(sel); | |
2674 } | |
2675 | |
5967 | 2676 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 2677 { |
2678 GdkEventButton *event_button = (GdkEventButton *) event; | |
2679 | |
2680 if (event->type == GDK_BUTTON_RELEASE) { | |
2681 if(event_button->button == 3) { | |
2682 GtkWidget *img, *item, *menu; | |
2683 gchar *text = g_strdup_printf(_("_Save Image...")); | |
2684 menu = gtk_menu_new(); | |
2685 | |
2686 /* buttons and such */ | |
2687 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
2688 item = gtk_image_menu_item_new_with_mnemonic(text); | |
2689 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 2690 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 2691 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
2692 | |
2693 gtk_widget_show_all(menu); | |
2694 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
2695 event_button->button, event_button->time); | |
2696 | |
2697 g_free(text); | |
2698 return TRUE; | |
2699 } | |
2700 } | |
2701 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
2702 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
2703 be caught by the regular GtkTextView menu */ | |
2704 else | |
2705 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
2706 | |
2707 } | |
5967 | 2708 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
2709 { | |
2710 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
2711 | |
2712 g_object_unref(image->pixbuf); | |
6982 | 2713 if (image->filename) |
2714 g_free(image->filename); | |
5967 | 2715 g_free(scale); |
2716 } | |
2717 | |
2718 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
2719 { | |
2720 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
2721 GtkWidget *box = gtk_event_box_new(); | |
2722 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
2723 | |
2724 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
2725 | |
2726 gtk_widget_show(GTK_WIDGET(image->image)); | |
2727 gtk_widget_show(box); | |
2728 | |
2729 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
2730 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
2731 } | |
2732 | |
2733 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
2734 { | |
2735 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
2736 | |
2737 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
2738 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
2739 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
2740 | |
2741 hr->sep = gtk_hseparator_new(); | |
2742 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
2743 gtk_widget_show(hr->sep); | |
2744 | |
2745 return GTK_IMHTML_SCALABLE(hr); | |
2746 } | |
2747 | |
2748 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
2749 { | |
8588 | 2750 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); |
5967 | 2751 } |
2752 | |
2753 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
2754 { | |
2755 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
2756 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
8698 | 2757 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); |
2758 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); | |
5967 | 2759 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
2760 } | |
2761 | |
2762 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
2763 { | |
2764 g_free(scale); | |
2765 } | |
7295 | 2766 |
2767 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | |
2768 { | |
2769 GtkTextIter iter, start, end; | |
2770 gboolean new_search = TRUE; | |
2771 | |
2772 g_return_val_if_fail(imhtml != NULL, FALSE); | |
2773 g_return_val_if_fail(text != NULL, FALSE); | |
8061 | 2774 |
7295 | 2775 if (imhtml->search_string && !strcmp(text, imhtml->search_string)) |
2776 new_search = FALSE; | |
8061 | 2777 |
7295 | 2778 if (new_search) { |
2779 gtk_imhtml_search_clear(imhtml); | |
2780 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
2781 } else { | |
2782 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, | |
8061 | 2783 gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); |
7295 | 2784 } |
2785 imhtml->search_string = g_strdup(text); | |
2786 | |
7358 | 2787 if (gtk_source_iter_forward_search(&iter, imhtml->search_string, |
2788 GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, | |
7295 | 2789 &start, &end, NULL)) { |
2790 | |
2791 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0); | |
2792 gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); | |
2793 if (new_search) { | |
2794 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); | |
8061 | 2795 do |
7295 | 2796 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); |
8061 | 2797 while (gtk_source_iter_forward_search(&end, imhtml->search_string, |
2798 GTK_SOURCE_SEARCH_VISIBLE_ONLY | | |
7358 | 2799 GTK_SOURCE_SEARCH_CASE_INSENSITIVE, |
7295 | 2800 &start, &end, NULL)); |
2801 } | |
2802 return TRUE; | |
2803 } | |
8061 | 2804 |
2805 gtk_imhtml_search_clear(imhtml); | |
2806 | |
7295 | 2807 return FALSE; |
2808 } | |
2809 | |
2810 void gtk_imhtml_search_clear(GtkIMHtml *imhtml) | |
2811 { | |
2812 GtkTextIter start, end; | |
8061 | 2813 |
7295 | 2814 g_return_if_fail(imhtml != NULL); |
8061 | 2815 |
7295 | 2816 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
2817 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
2818 | |
2819 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end); | |
2820 if (imhtml->search_string) | |
2821 g_free(imhtml->search_string); | |
2822 imhtml->search_string = NULL; | |
2823 } | |
8061 | 2824 |
8677 | 2825 static GtkTextTag *find_font_forecolor_tag(GtkIMHtml *imhtml, gchar *color) |
2826 { | |
2827 gchar str[18]; | |
2828 GtkTextTag *tag; | |
2829 | |
2830 g_snprintf(str, sizeof(str), "FORECOLOR %s", color); | |
2831 | |
2832 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2833 if (!tag) | |
2834 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", color, NULL); | |
2835 | |
2836 return tag; | |
2837 } | |
2838 | |
2839 static GtkTextTag *find_font_backcolor_tag(GtkIMHtml *imhtml, gchar *color) | |
2840 { | |
2841 gchar str[18]; | |
2842 GtkTextTag *tag; | |
2843 | |
2844 g_snprintf(str, sizeof(str), "BACKCOLOR %s", color); | |
2845 | |
2846 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2847 if (!tag) | |
2848 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "background", color, NULL); | |
2849 | |
2850 return tag; | |
2851 } | |
2852 | |
2853 static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) | |
8061 | 2854 { |
8677 | 2855 gchar str[256]; |
2856 GtkTextTag *tag; | |
2857 | |
2858 g_snprintf(str, sizeof(str), "FONT FACE %s", face); | |
2859 str[255] = '\0'; | |
2860 | |
2861 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2862 if (!tag) | |
2863 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "family", face, NULL); | |
2864 | |
2865 return tag; | |
2866 } | |
2867 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2868 static void _init_original_fsize(GtkIMHtml *imhtml) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2869 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2870 GtkTextAttributes *attr; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2871 attr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(imhtml)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2872 imhtml->original_fsize = pango_font_description_get_size(attr->font); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2873 gtk_text_attributes_unref(attr); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2874 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2875 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2876 static void _recalculate_font_sizes(GtkTextTag *tag, gpointer imhtml) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2877 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2878 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2879 int size; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2880 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2881 size = strtol(tag->name + 10, NULL, 10); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2882 g_object_set(G_OBJECT(tag), "size", |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2883 (gint) (GTK_IMHTML(imhtml)->original_fsize * |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2884 ((double) _point_sizes[size-1] * GTK_IMHTML(imhtml)->zoom)), NULL); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2885 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2886 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2887 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2888 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2889 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2890 void gtk_imhtml_font_zoom(GtkIMHtml *imhtml, double zoom) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2891 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2892 GtkRcStyle *s; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2893 PangoFontDescription *font_desc = pango_font_description_new(); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2894 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2895 imhtml->zoom = zoom; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2896 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2897 if (!imhtml->original_fsize) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2898 _init_original_fsize(imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2899 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2900 gtk_text_tag_table_foreach(gtk_text_buffer_get_tag_table(imhtml->text_buffer), |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2901 _recalculate_font_sizes, imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2902 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2903 pango_font_description_set_size(font_desc, (gint)((double) imhtml->original_fsize * zoom)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2904 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2905 s = gtk_widget_get_modifier_style(GTK_WIDGET(imhtml)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2906 s->font_desc = font_desc; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2907 gtk_widget_modify_style(GTK_WIDGET(imhtml), s); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2908 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2909 |
8677 | 2910 static GtkTextTag *find_font_size_tag(GtkIMHtml *imhtml, int size) |
2911 { | |
2912 gchar str[24]; | |
2913 GtkTextTag *tag; | |
2914 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2915 if (!imhtml->original_fsize) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2916 _init_original_fsize(imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2917 |
8677 | 2918 g_snprintf(str, sizeof(str), "FONT SIZE %d", size); |
2919 str[23] = '\0'; | |
2920 | |
2921 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2922 if (!tag) { | |
2923 /* For reasons I don't understand, setting "scale" here scaled based on some default | |
2924 * size other than my theme's default size. Our size 4 was actually smaller than | |
2925 * our size 3 for me. So this works around that oddity. | |
2926 */ | |
2927 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "size", | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2928 (gint) (imhtml->original_fsize * |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2929 ((double) _point_sizes[size-1] * imhtml->zoom)), NULL); |
8061 | 2930 } |
2931 | |
8677 | 2932 return tag; |
2933 } | |
2934 | |
2935 static void remove_tag_by_prefix(GtkIMHtml *imhtml, const GtkTextIter *i, const GtkTextIter *e, | |
2936 const char *prefix, guint len, gboolean homo) | |
2937 { | |
2938 GSList *tags, *l; | |
2939 GtkTextIter iter; | |
2940 | |
2941 tags = gtk_text_iter_get_tags(i); | |
2942 | |
2943 for (l = tags; l; l = l->next) { | |
2944 GtkTextTag *tag = l->data; | |
2945 | |
2946 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2947 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); | |
8061 | 2948 } |
2949 | |
8677 | 2950 g_slist_free(tags); |
2951 | |
2952 if (homo) | |
2953 return; | |
2954 | |
2955 iter = *i; | |
2956 | |
2957 while (gtk_text_iter_forward_char(&iter) && !gtk_text_iter_equal(&iter, e)) { | |
2958 if (gtk_text_iter_begins_tag(&iter, NULL)) { | |
2959 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); | |
2960 | |
2961 for (l = tags; l; l = l->next) { | |
2962 GtkTextTag *tag = l->data; | |
2963 | |
2964 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2965 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); | |
2966 } | |
2967 | |
2968 g_slist_free(tags); | |
2969 } | |
8061 | 2970 } |
8677 | 2971 } |
2972 | |
2973 static void remove_font_size(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2974 { | |
2975 remove_tag_by_prefix(imhtml, i, e, "FONT SIZE ", 10, homo); | |
2976 } | |
2977 | |
2978 static void remove_font_face(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2979 { | |
2980 remove_tag_by_prefix(imhtml, i, e, "FONT FACE ", 10, homo); | |
2981 } | |
2982 | |
2983 static void remove_font_forecolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2984 { | |
2985 remove_tag_by_prefix(imhtml, i, e, "FORECOLOR ", 10, homo); | |
2986 } | |
2987 | |
2988 static void remove_font_backcolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2989 { | |
2990 remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); | |
2991 } | |
2992 | |
2993 static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2994 { | |
2995 remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); | |
2996 } | |
2997 | |
2998 /* Editable stuff */ | |
2999 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | |
3000 { | |
3001 imhtml->insert_offset = gtk_text_iter_get_offset(iter); | |
3002 } | |
3003 | |
3004 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) | |
3005 { | |
3006 GtkTextIter start; | |
3007 | |
3008 if (!len) | |
3009 return; | |
3010 | |
3011 start = *end; | |
3012 gtk_text_iter_set_offset(&start, imhtml->insert_offset); | |
3013 | |
3014 if (imhtml->edit.bold) | |
3015 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); | |
3016 else | |
3017 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); | |
3018 | |
3019 if (imhtml->edit.italic) | |
3020 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); | |
3021 else | |
3022 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); | |
3023 | |
3024 if (imhtml->edit.underline) | |
3025 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); | |
3026 else | |
3027 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); | |
3028 | |
3029 if (imhtml->edit.forecolor) { | |
3030 remove_font_forecolor(imhtml, &start, end, TRUE); | |
3031 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3032 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
3033 &start, end); | |
8061 | 3034 } |
3035 | |
8677 | 3036 if (imhtml->edit.backcolor) { |
3037 remove_font_backcolor(imhtml, &start, end, TRUE); | |
3038 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3039 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), | |
3040 &start, end); | |
3041 } | |
3042 | |
3043 if (imhtml->edit.fontface) { | |
3044 remove_font_face(imhtml, &start, end, TRUE); | |
3045 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3046 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
3047 &start, end); | |
8061 | 3048 } |
8677 | 3049 |
3050 if (imhtml->edit.fontsize) { | |
3051 remove_font_size(imhtml, &start, end, TRUE); | |
3052 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3053 find_font_size_tag(imhtml, imhtml->edit.fontsize), | |
3054 &start, end); | |
3055 } | |
3056 | |
3057 if (imhtml->edit.link) { | |
3058 remove_font_link(imhtml, &start, end, TRUE); | |
3059 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3060 imhtml->edit.link, | |
3061 &start, end); | |
3062 } | |
3063 | |
8061 | 3064 } |
3065 | |
3066 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | |
3067 { | |
3068 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | |
8177 | 3069 /* |
3070 * We need a visible caret for accessibility, so mouseless | |
3071 * people can highlight stuff. | |
3072 */ | |
3073 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | |
8061 | 3074 imhtml->editable = editable; |
8677 | 3075 imhtml->format_functions = GTK_IMHTML_ALL; |
3076 | |
3077 if (editable) | |
3078 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
3079 G_CALLBACK(mark_set_cb), imhtml); | |
3080 } | |
3081 | |
3082 void gtk_imhtml_set_whole_buffer_formatting_only(GtkIMHtml *imhtml, gboolean wbfo) | |
3083 { | |
3084 g_return_if_fail(imhtml != NULL); | |
3085 | |
3086 imhtml->wbfo = wbfo; | |
8420 | 3087 } |
3088 | |
3089 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | |
3090 { | |
3091 GObject *object = g_object_ref(G_OBJECT(imhtml)); | |
8677 | 3092 imhtml->format_functions = buttons; |
8420 | 3093 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); |
3094 g_object_unref(object); | |
8061 | 3095 } |
3096 | |
8516 | 3097 |
3098 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, | |
3099 gboolean *italic, gboolean *underline) | |
8481 | 3100 { |
8677 | 3101 if (imhtml->edit.bold) |
3102 (*bold) = TRUE; | |
3103 if (imhtml->edit.italic) | |
3104 (*italic) = TRUE; | |
3105 if (imhtml->edit.underline) | |
3106 (*underline) = TRUE; | |
8481 | 3107 } |
3108 | |
8061 | 3109 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) |
3110 { | |
3111 return imhtml->editable; | |
3112 } | |
3113 | |
8677 | 3114 /* |
3115 * I had this crazy idea about changing the text cursor color to reflex the foreground color | |
3116 * of the text about to be entered. This is the place you'd do it, along with the place where | |
3117 * we actually set a new foreground color. | |
3118 * I may not do this, because people will bitch about Gaim overriding their gtk theme's cursor | |
3119 * colors. | |
3120 * | |
3121 * Just in case I do do this, I asked about what to set the secondary text cursor to. | |
3122 * | |
8719 | 3123 * (12:45:27) ?? ???: secondary_cursor_color = (rgb(background) + rgb(primary_cursor_color) ) / 2 |
3124 * (12:45:55) ?? ???: understand? | |
8677 | 3125 * (12:46:14) Tim: yeah. i didn't know there was an exact formula |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8729
diff
changeset
|
3126 * (12:46:56) ?? ???: u might need to extract separate each color from RGB |
8677 | 3127 */ |
3128 | |
3129 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, | |
3130 GtkIMHtml *imhtml) | |
3131 { | |
3132 GSList *tags, *l; | |
3133 GtkTextIter iter; | |
3134 | |
3135 if (mark != gtk_text_buffer_get_insert(buffer)) | |
3136 return; | |
3137 | |
3138 if (!gtk_text_buffer_get_char_count(buffer)) | |
3139 return; | |
3140 | |
3141 imhtml->edit.bold = imhtml->edit.italic = imhtml->edit.underline = FALSE; | |
3142 if (imhtml->edit.forecolor) | |
3143 g_free(imhtml->edit.forecolor); | |
3144 imhtml->edit.forecolor = NULL; | |
3145 if (imhtml->edit.backcolor) | |
3146 g_free(imhtml->edit.backcolor); | |
3147 imhtml->edit.backcolor = NULL; | |
3148 if (imhtml->edit.fontface) | |
3149 g_free(imhtml->edit.fontface); | |
3150 imhtml->edit.fontface = NULL; | |
3151 imhtml->edit.fontsize = 0; | |
3152 imhtml->edit.link = NULL; | |
3153 | |
3154 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3155 | |
3156 | |
3157 if (gtk_text_iter_is_end(&iter)) | |
3158 tags = gtk_text_iter_get_toggled_tags(&iter, FALSE); | |
3159 else | |
3160 tags = gtk_text_iter_get_tags(&iter); | |
3161 | |
3162 for (l = tags; l != NULL; l = l->next) { | |
3163 GtkTextTag *tag = GTK_TEXT_TAG(l->data); | |
3164 | |
3165 if (tag->name) { | |
3166 if (strcmp(tag->name, "BOLD") == 0) | |
3167 imhtml->edit.bold = TRUE; | |
3168 if (strcmp(tag->name, "ITALICS") == 0) | |
3169 imhtml->edit.italic = TRUE; | |
3170 if (strcmp(tag->name, "UNDERLINE") == 0) | |
3171 imhtml->edit.underline = TRUE; | |
3172 if (strncmp(tag->name, "FORECOLOR ", 10) == 0) | |
3173 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); | |
3174 if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) | |
3175 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); | |
3176 if (strncmp(tag->name, "FONT FACE ", 10) == 0) | |
3177 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); | |
3178 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) | |
3179 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); | |
8719 | 3180 if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) |
8677 | 3181 imhtml->edit.link = tag; |
3182 } | |
3183 } | |
3184 | |
3185 g_slist_free(tags); | |
3186 } | |
3187 | |
8061 | 3188 gboolean gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) |
3189 { | |
8481 | 3190 GObject *object; |
8677 | 3191 GtkTextIter start, end; |
3192 | |
3193 imhtml->edit.bold = !imhtml->edit.bold; | |
3194 | |
3195 if (imhtml->wbfo) { | |
3196 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3197 if (imhtml->edit.bold) | |
3198 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3199 else | |
3200 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3201 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3202 if (imhtml->edit.bold) | |
3203 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3204 else | |
3205 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3206 | |
8061 | 3207 } |
8481 | 3208 object = g_object_ref(G_OBJECT(imhtml)); |
3209 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); | |
3210 g_object_unref(object); | |
3211 | |
8677 | 3212 return (imhtml->edit.bold != FALSE); |
8061 | 3213 } |
3214 | |
3215 gboolean gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) | |
3216 { | |
8481 | 3217 GObject *object; |
8677 | 3218 GtkTextIter start, end; |
3219 | |
3220 imhtml->edit.italic = !imhtml->edit.italic; | |
3221 | |
3222 if (imhtml->wbfo) { | |
3223 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3224 if (imhtml->edit.italic) | |
3225 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3226 else | |
3227 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3228 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3229 if (imhtml->edit.italic) | |
3230 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3231 else | |
3232 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
8061 | 3233 } |
8481 | 3234 object = g_object_ref(G_OBJECT(imhtml)); |
3235 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); | |
3236 g_object_unref(object); | |
3237 | |
8677 | 3238 return imhtml->edit.italic != FALSE; |
8061 | 3239 } |
3240 | |
3241 gboolean gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) | |
3242 { | |
8481 | 3243 GObject *object; |
8677 | 3244 GtkTextIter start, end; |
3245 | |
3246 imhtml->edit.underline = !imhtml->edit.underline; | |
3247 | |
3248 if (imhtml->wbfo) { | |
3249 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3250 if (imhtml->edit.underline) | |
3251 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3252 else | |
3253 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3254 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3255 if (imhtml->edit.underline) | |
3256 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3257 else | |
3258 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
8061 | 3259 } |
8481 | 3260 object = g_object_ref(G_OBJECT(imhtml)); |
3261 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); | |
3262 g_object_unref(object); | |
3263 | |
8677 | 3264 return imhtml->edit.underline != FALSE; |
8061 | 3265 } |
3266 | |
3267 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) | |
3268 { | |
8677 | 3269 GtkTextIter start, end; |
8061 | 3270 |
3271 imhtml->edit.fontsize = size; | |
3272 | |
8677 | 3273 |
3274 if (imhtml->wbfo) { | |
3275 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3276 remove_font_size(imhtml, &start, &end, TRUE); | |
3277 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3278 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3279 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3280 remove_font_size(imhtml, &start, &end, FALSE); | |
3281 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3282 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3283 } |
8677 | 3284 |
8061 | 3285 } |
3286 | |
3287 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) | |
3288 { | |
8677 | 3289 GtkTextIter start, end; |
3290 | |
8061 | 3291 if (imhtml->edit.fontsize == 1) |
3292 return; | |
3293 | |
8677 | 3294 if (!imhtml->edit.fontsize) |
3295 imhtml->edit.fontsize = 2; | |
3296 else | |
3297 imhtml->edit.fontsize--; | |
3298 | |
3299 if (imhtml->wbfo) { | |
3300 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3301 remove_font_size(imhtml, &start, &end, TRUE); | |
3302 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3303 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3304 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3305 remove_font_size(imhtml, &start, &end, FALSE); | |
3306 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3307 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3308 } |
3309 } | |
3310 | |
3311 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) | |
3312 { | |
8677 | 3313 GtkTextIter start, end; |
3314 | |
8061 | 3315 if (imhtml->edit.fontsize == MAX_FONT_SIZE) |
3316 return; | |
3317 | |
8677 | 3318 if (!imhtml->edit.fontsize) |
3319 imhtml->edit.fontsize = 4; | |
3320 else | |
3321 imhtml->edit.fontsize++; | |
3322 | |
3323 if (imhtml->wbfo) { | |
3324 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3325 remove_font_size(imhtml, &start, &end, TRUE); | |
3326 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3327 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3328 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3329 remove_font_size(imhtml, &start, &end, FALSE); | |
3330 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3331 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3332 } |
3333 } | |
3334 | |
3335 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) | |
3336 { | |
8677 | 3337 GtkTextIter start, end; |
3338 | |
3339 if (imhtml->edit.forecolor != NULL) | |
3340 g_free(imhtml->edit.forecolor); | |
3341 | |
8429 | 3342 if (color) { |
8677 | 3343 imhtml->edit.forecolor = g_strdup(color); |
3344 if (imhtml->wbfo) { | |
3345 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3346 remove_font_forecolor(imhtml, &start, &end, TRUE); | |
3347 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3348 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), &start, &end); | |
3349 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3350 remove_font_forecolor(imhtml, &start, &end, FALSE); | |
3351 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3352 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
3353 &start, &end); | |
3354 } | |
8061 | 3355 } else { |
3356 imhtml->edit.forecolor = NULL; | |
3357 } | |
3358 | |
3359 return imhtml->edit.forecolor != NULL; | |
3360 } | |
3361 | |
3362 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
3363 { | |
8677 | 3364 GtkTextIter start, end; |
3365 | |
3366 if (imhtml->edit.backcolor != NULL) | |
3367 g_free(imhtml->edit.backcolor); | |
3368 | |
8429 | 3369 if (color) { |
8677 | 3370 imhtml->edit.backcolor = g_strdup(color); |
3371 | |
3372 if (imhtml->wbfo) { | |
3373 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3374 remove_font_backcolor(imhtml, &start, &end, TRUE); | |
3375 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3376 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), &start, &end); | |
3377 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3378 remove_font_backcolor(imhtml, &start, &end, FALSE); | |
3379 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3380 find_font_backcolor_tag(imhtml, | |
3381 imhtml->edit.backcolor), &start, &end); | |
3382 } | |
8061 | 3383 } else { |
3384 imhtml->edit.backcolor = NULL; | |
3385 } | |
8677 | 3386 |
8061 | 3387 return imhtml->edit.backcolor != NULL; |
3388 } | |
3389 | |
3390 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
3391 { | |
8677 | 3392 GtkTextIter start, end; |
3393 | |
3394 if (imhtml->edit.fontface != NULL) | |
3395 g_free(imhtml->edit.fontface); | |
3396 | |
8429 | 3397 if (face) { |
8677 | 3398 imhtml->edit.fontface = g_strdup(face); |
3399 | |
3400 if (imhtml->wbfo) { | |
3401 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3402 remove_font_face(imhtml, &start, &end, TRUE); | |
3403 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3404 find_font_face_tag(imhtml, imhtml->edit.fontface), &start, &end); | |
3405 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3406 remove_font_face(imhtml, &start, &end, FALSE); | |
3407 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3408 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
3409 &start, &end); | |
3410 } | |
8061 | 3411 } else { |
3412 imhtml->edit.fontface = NULL; | |
3413 } | |
8677 | 3414 |
8061 | 3415 return imhtml->edit.fontface != NULL; |
3416 } | |
3417 | |
8677 | 3418 void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) |
8061 | 3419 { |
8677 | 3420 GtkTextIter start, end; |
3421 GtkTextTag *linktag; | |
3422 static guint linkno = 0; | |
3423 gchar str[48]; | |
3424 | |
3425 imhtml->edit.link = NULL; | |
3426 | |
3427 | |
3428 | |
3429 if (url) { | |
3430 g_snprintf(str, sizeof(str), "LINK %d", linkno++); | |
3431 str[47] = '\0'; | |
3432 | |
3433 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
3434 g_object_set_data_full(G_OBJECT(linktag), "link_url", g_strdup(url), g_free); | |
3435 g_signal_connect(G_OBJECT(linktag), "event", G_CALLBACK(tag_event), NULL); | |
3436 | |
3437 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3438 remove_font_link(imhtml, &start, &end, FALSE); | |
3439 gtk_text_buffer_apply_tag(imhtml->text_buffer, linktag, &start, &end); | |
3440 } | |
3441 } | |
3442 } | |
3443 | |
3444 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, GtkTextMark *mark, const char *url, const char *text) | |
3445 { | |
8061 | 3446 GtkTextIter iter; |
8677 | 3447 |
3448 gtk_imhtml_toggle_link(imhtml, url); | |
8061 | 3449 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
8677 | 3450 gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); |
3451 gtk_imhtml_toggle_link(imhtml, NULL); | |
8061 | 3452 } |
3453 | |
3454 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
3455 { | |
8677 | 3456 GtkTextMark *mark; |
8061 | 3457 GtkTextIter iter; |
8677 | 3458 |
3459 mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
3460 | |
3461 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3462 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); | |
3463 } | |
3464 | |
3465 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) | |
3466 { | |
8061 | 3467 GdkPixbuf *pixbuf = NULL; |
3468 GdkPixbufAnimation *annipixbuf = NULL; | |
3469 GtkWidget *icon = NULL; | |
3470 GtkTextChildAnchor *anchor; | |
8505 | 3471 char *unescaped = gaim_unescape_html(smiley); |
8061 | 3472 |
8515 | 3473 if (!imhtml->show_smileys) { |
8677 | 3474 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, strlen(smiley)); |
8515 | 3475 return; |
3476 } | |
3477 | |
8677 | 3478 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
8698 | 3479 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", unescaped, g_free); |
3480 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); | |
8505 | 3481 |
3482 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); | |
8061 | 3483 if(annipixbuf) { |
3484 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
3485 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); | |
3486 if(pixbuf) | |
3487 icon = gtk_image_new_from_pixbuf(pixbuf); | |
3488 } else { | |
3489 icon = gtk_image_new_from_animation(annipixbuf); | |
3490 } | |
3491 } | |
3492 | |
3493 if (icon) { | |
3494 gtk_widget_show(icon); | |
3495 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | |
3496 } | |
3497 } | |
3498 | |
8677 | 3499 static const gchar *tag_to_html_start(GtkTextTag *tag) |
8061 | 3500 { |
8677 | 3501 const gchar *name; |
3502 static gchar buf[1024]; | |
3503 | |
3504 name = tag->name; | |
3505 g_return_val_if_fail(name != NULL, ""); | |
3506 | |
3507 if (strcmp(name, "BOLD") == 0) { | |
3508 return "<b>"; | |
3509 } else if (strcmp(name, "ITALICS") == 0) { | |
3510 return "<i>"; | |
3511 } else if (strcmp(name, "UNDERLINE") == 0) { | |
3512 return "<u>"; | |
3513 } else if (strncmp(name, "LINK ", 5) == 0) { | |
3514 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); | |
3515 if (tmp) { | |
3516 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); | |
3517 buf[sizeof(buf)-1] = '\0'; | |
3518 return buf; | |
3519 } else { | |
3520 return ""; | |
3521 } | |
3522 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3523 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); | |
3524 return buf; | |
3525 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3526 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); | |
3527 return buf; | |
3528 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3529 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); | |
3530 return buf; | |
3531 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3532 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); | |
3533 return buf; | |
3534 } else { | |
3535 return ""; | |
3536 } | |
8061 | 3537 } |
3538 | |
8677 | 3539 static const gchar *tag_to_html_end(GtkTextTag *tag) |
8061 | 3540 { |
8677 | 3541 const gchar *name; |
3542 | |
3543 name = tag->name; | |
3544 g_return_val_if_fail(name != NULL, ""); | |
3545 | |
3546 if (strcmp(name, "BOLD") == 0) { | |
3547 return "</b>"; | |
3548 } else if (strcmp(name, "ITALICS") == 0) { | |
3549 return "</i>"; | |
3550 } else if (strcmp(name, "UNDERLINE") == 0) { | |
3551 return "</u>"; | |
3552 } else if (strncmp(name, "LINK ", 5) == 0) { | |
3553 return "</a>"; | |
3554 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3555 return "</font>"; | |
3556 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3557 return "</font>"; | |
3558 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3559 return "</font>"; | |
3560 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3561 return "</font>"; | |
3562 } else { | |
3563 return ""; | |
3564 } | |
3565 } | |
3566 | |
3567 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) | |
3568 { | |
3569 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && | |
3570 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || | |
3571 gtk_text_iter_is_end(niter)); | |
8061 | 3572 } |
3573 | |
3574 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | |
3575 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | |
8677 | 3576 * check for tags that are toggled on, insert their html form, and push them on the queue. Then insert |
3577 * the actual text. Then check for tags that are toggled off and insert them, after checking the queue. | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8729
diff
changeset
|
3578 * Finally, replace <, >, &, and " with their HTML equivalent. |
8677 | 3579 */ |
8061 | 3580 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
3581 { | |
3582 gunichar c; | |
8677 | 3583 GtkTextIter iter, nextiter; |
8061 | 3584 GString *str = g_string_new(""); |
8677 | 3585 GSList *tags, *sl; |
3586 GQueue *q, *r; | |
3587 GtkTextTag *tag; | |
3588 | |
3589 q = g_queue_new(); | |
3590 r = g_queue_new(); | |
3591 | |
8061 | 3592 |
3593 gtk_text_iter_order(start, end); | |
8677 | 3594 nextiter = iter = *start; |
3595 gtk_text_iter_forward_char(&nextiter); | |
3596 | |
3597 /* First add the tags that are already in progress */ | |
3598 tags = gtk_text_iter_get_tags(start); | |
3599 | |
3600 for (sl = tags; sl; sl = sl->next) { | |
3601 tag = sl->data; | |
3602 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { | |
3603 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); | |
3604 g_queue_push_tail(q, tag); | |
8061 | 3605 } |
3606 } | |
8677 | 3607 g_slist_free(tags); |
8061 | 3608 |
3609 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
8677 | 3610 |
3611 tags = gtk_text_iter_get_tags(&iter); | |
3612 | |
3613 for (sl = tags; sl; sl = sl->next) { | |
3614 tag = sl->data; | |
3615 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { | |
3616 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); | |
3617 g_queue_push_tail(q, tag); | |
3618 } | |
3619 } | |
3620 | |
3621 | |
8061 | 3622 if (c == 0xFFFC) { |
3623 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | |
8698 | 3624 char *text = NULL; |
3625 if (anchor) | |
3626 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext"); | |
3627 if (text) | |
3628 str = g_string_append(str, text); | |
8677 | 3629 } else if (c == '<') { |
3630 str = g_string_append(str, "<"); | |
3631 } else if (c == '>') { | |
3632 str = g_string_append(str, ">"); | |
3633 } else if (c == '&') { | |
3634 str = g_string_append(str, "&"); | |
3635 } else if (c == '"') { | |
3636 str = g_string_append(str, """); | |
3637 } else if (c == '\n') { | |
3638 str = g_string_append(str, "<br>"); | |
8061 | 3639 } else { |
8677 | 3640 str = g_string_append_unichar(str, c); |
3641 } | |
3642 | |
3643 tags = g_slist_reverse(tags); | |
3644 for (sl = tags; sl; sl = sl->next) { | |
3645 tag = sl->data; | |
3646 if (tag_ends_here(tag, &iter, &nextiter)) { | |
3647 | |
3648 GtkTextTag *tmp; | |
3649 | |
3650 while ((tmp = g_queue_pop_tail(q)) != tag) { | |
3651 if (tmp == NULL) | |
3652 break; | |
3653 | |
3654 if (!tag_ends_here(tmp, &iter, &nextiter)) | |
3655 g_queue_push_tail(r, tmp); | |
3656 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); | |
3657 } | |
3658 | |
3659 if (tmp == NULL) | |
3660 gaim_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); | |
3661 else | |
3662 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
3663 | |
3664 while ((tmp = g_queue_pop_head(r))) { | |
3665 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); | |
3666 g_queue_push_tail(q, tmp); | |
8061 | 3667 } |
3668 } | |
3669 } | |
8677 | 3670 |
3671 g_slist_free(tags); | |
8061 | 3672 gtk_text_iter_forward_char(&iter); |
8677 | 3673 gtk_text_iter_forward_char(&nextiter); |
8061 | 3674 } |
8677 | 3675 |
3676 while ((tag = g_queue_pop_tail(q))) | |
3677 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
3678 | |
3679 g_queue_free(q); | |
3680 g_queue_free(r); | |
8061 | 3681 return g_string_free(str, FALSE); |
3682 } | |
3683 | |
8698 | 3684 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter) |
8061 | 3685 { |
3686 if (imhtml->edit.bold) | |
3687 gtk_imhtml_toggle_bold(imhtml); | |
3688 | |
3689 if (imhtml->edit.italic) | |
3690 gtk_imhtml_toggle_italic(imhtml); | |
3691 | |
3692 if (imhtml->edit.underline) | |
3693 gtk_imhtml_toggle_underline(imhtml); | |
3694 | |
3695 if (imhtml->edit.forecolor) | |
3696 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
3697 | |
3698 if (imhtml->edit.backcolor) | |
3699 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
3700 | |
3701 if (imhtml->edit.fontface) | |
3702 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
3703 | |
8677 | 3704 imhtml->edit.fontsize = 0; |
3705 | |
8719 | 3706 if (imhtml->edit.link) |
3707 gtk_imhtml_toggle_link(imhtml, NULL); | |
3708 | |
8698 | 3709 gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter); |
8061 | 3710 |
3711 } | |
3712 | |
3713 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
3714 { | |
3715 GtkTextIter start, end; | |
3716 | |
3717 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
3718 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3719 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
3720 } | |
3721 | |
8677 | 3722 char **gtk_imhtml_get_markup_lines(GtkIMHtml *imhtml) |
3723 { | |
3724 int i, j, lines; | |
3725 GtkTextIter start, end; | |
3726 char **ret; | |
3727 | |
3728 lines = gtk_text_buffer_get_line_count(imhtml->text_buffer); | |
3729 ret = g_new0(char *, lines + 1); | |
3730 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
3731 end = start; | |
3732 gtk_text_iter_forward_to_line_end(&end); | |
3733 | |
3734 for (i = 0, j = 0; i < lines; i++) { | |
3735 ret[j] = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
3736 if (ret[j] != NULL) | |
3737 j++; | |
3738 gtk_text_iter_forward_line(&start); | |
3739 end = start; | |
3740 gtk_text_iter_forward_to_line_end(&end); | |
3741 } | |
3742 | |
3743 return ret; | |
3744 } | |
3745 | |
3746 char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop) | |
8061 | 3747 { |
8519 | 3748 GString *str = g_string_new(""); |
3749 GtkTextIter iter, end; | |
3750 gunichar c; | |
3751 | |
8677 | 3752 if (start == NULL) |
3753 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
3754 else | |
3755 iter = *start; | |
3756 | |
3757 if (stop == NULL) | |
3758 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3759 else | |
3760 end = *stop; | |
3761 | |
3762 gtk_text_iter_order(&iter, &end); | |
8519 | 3763 |
3764 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { | |
3765 if (c == 0xFFFC) { | |
8677 | 3766 GtkTextChildAnchor* anchor; |
3767 char *text = NULL; | |
3768 | |
3769 anchor = gtk_text_iter_get_child_anchor(&iter); | |
3770 if (anchor) | |
8698 | 3771 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_plaintext"); |
8677 | 3772 if (text) |
3773 str = g_string_append(str, text); | |
8519 | 3774 } else { |
3775 g_string_append_unichar(str, c); | |
3776 } | |
3777 gtk_text_iter_forward_char(&iter); | |
3778 } | |
3779 | |
3780 return g_string_free(str, FALSE); | |
8061 | 3781 } |