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