Mercurial > pidgin
annotate src/gtkimhtml.c @ 8957:97a1f314b051
[gaim-migrate @ 9731]
(2004-05-16 16:56:38) lschiere2: anyone have any thoughts on https://sourceforge.net/tracker/?func=detail&atid=300235&aid=951479&group_id=235
(2004-05-16 17:07:14) TimRingenbach: my thoughts are "i should make middle click open links"
(2004-05-16 17:08:58) lschiere2: lol yes
(2004-05-16 17:09:03) lschiere2: that would be cool ;-)
(2004-05-16 17:11:19) TimRingenbach: it should be easy enough to do, if you really want me to. i always middle click because i'm used to for opening new tabs in mozilla
(2004-05-16 17:12:08) lschiere2: *nods* i'm using galeon, not mozilla, but otherwise yes, i'm constantly middle clicking
This does that. It makes middle clicking a link work exactly like left
clicking one. There's only one problem, the mouse gesters plugin will
steal the middle clicks and so it won't work if that plugin is loaded.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Sun, 16 May 2004 22:43:41 +0000 |
parents | 849507541e86 |
children | 4ff4c34b7500 |
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; |
8061 | 908 |
4138 | 909 g_hash_table_destroy(imhtml->smiley_data); |
4032 | 910 gtk_smiley_tree_destroy(imhtml->default_smilies); |
4138 | 911 gdk_cursor_unref(imhtml->hand_cursor); |
912 gdk_cursor_unref(imhtml->arrow_cursor); | |
8061 | 913 gdk_cursor_unref(imhtml->text_cursor); |
8677 | 914 |
4735 | 915 if(imhtml->tip_window){ |
916 gtk_widget_destroy(imhtml->tip_window); | |
917 } | |
918 if(imhtml->tip_timer) | |
919 gtk_timeout_remove(imhtml->tip_timer); | |
920 | |
4895 | 921 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
922 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | |
923 scale->free(scale); | |
924 } | |
7991 | 925 |
8681 | 926 if (imhtml->clipboard_text_string) { |
927 g_free(imhtml->clipboard_text_string); | |
928 g_free(imhtml->clipboard_html_string); | |
929 } | |
930 | |
4895 | 931 g_list_free(imhtml->scalables); |
4032 | 932 G_OBJECT_CLASS(parent_class)->finalize (object); |
933 } | |
1428 | 934 |
3922 | 935 /* Boring GTK stuff */ |
8519 | 936 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) |
1428 | 937 { |
3922 | 938 GtkObjectClass *object_class; |
4032 | 939 GObjectClass *gobject_class; |
8519 | 940 object_class = (GtkObjectClass*) klass; |
941 gobject_class = (GObjectClass*) klass; | |
4032 | 942 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); |
4417 | 943 signals[URL_CLICKED] = g_signal_new("url_clicked", |
944 G_TYPE_FROM_CLASS(gobject_class), | |
945 G_SIGNAL_RUN_FIRST, | |
946 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
947 NULL, | |
948 0, | |
949 g_cclosure_marshal_VOID__POINTER, | |
950 G_TYPE_NONE, 1, | |
951 G_TYPE_POINTER); | |
8506 | 952 signals[BUTTONS_UPDATE] = g_signal_new("format_buttons_update", |
8420 | 953 G_TYPE_FROM_CLASS(gobject_class), |
954 G_SIGNAL_RUN_FIRST, | |
955 G_STRUCT_OFFSET(GtkIMHtmlClass, buttons_update), | |
956 NULL, | |
957 0, | |
958 g_cclosure_marshal_VOID__POINTER, | |
959 G_TYPE_NONE, 1, | |
960 G_TYPE_INT); | |
961 signals[TOGGLE_FORMAT] = g_signal_new("format_function_toggle", | |
962 G_TYPE_FROM_CLASS(gobject_class), | |
963 G_SIGNAL_RUN_FIRST, | |
964 G_STRUCT_OFFSET(GtkIMHtmlClass, toggle_format), | |
965 NULL, | |
966 0, | |
967 g_cclosure_marshal_VOID__POINTER, | |
8427 | 968 G_TYPE_NONE, 1, |
8420 | 969 G_TYPE_INT); |
8427 | 970 signals[CLEAR_FORMAT] = g_signal_new("format_function_clear", |
971 G_TYPE_FROM_CLASS(gobject_class), | |
972 G_SIGNAL_RUN_FIRST, | |
973 G_STRUCT_OFFSET(GtkIMHtmlClass, clear_format), | |
974 NULL, | |
975 0, | |
8481 | 976 g_cclosure_marshal_VOID__VOID, |
977 G_TYPE_NONE, 0); | |
8506 | 978 signals[UPDATE_FORMAT] = g_signal_new("format_function_update", |
979 G_TYPE_FROM_CLASS(gobject_class), | |
980 G_SIGNAL_RUN_FIRST, | |
981 G_STRUCT_OFFSET(GtkIMHtmlClass, update_format), | |
982 NULL, | |
983 0, | |
984 g_cclosure_marshal_VOID__VOID, | |
985 G_TYPE_NONE, 0); | |
4032 | 986 gobject_class->finalize = gtk_imhtml_finalize; |
1428 | 987 } |
988 | |
3922 | 989 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 990 { |
3922 | 991 GtkTextIter iter; |
992 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
993 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
8677 | 994 imhtml->scrollpoint = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); |
3922 | 995 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); |
5105 | 996 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 997 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
8677 | 998 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); |
999 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(imhtml), 2); | |
8061 | 1000 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
3922 | 1001 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
8061 | 1002 |
3922 | 1003 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
8932 | 1004 * other tags (color, size, face, etc.) will have to be created and applied dynamically |
1005 * Note that even though we created STRIKE, SUB, SUP, and PRE tags here, we don't really | |
1006 * apply them anywhere yet. */ | |
3922 | 1007 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); |
1008 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
1009 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
1010 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
1011 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
1012 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
1013 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
7295 | 1014 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
8677 | 1015 |
3922 | 1016 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
1017 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
1018 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
8061 | 1019 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
2993 | 1020 |
6124 | 1021 imhtml->show_comments = TRUE; |
4253 | 1022 |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1023 imhtml->zoom = 1.0; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1024 imhtml->original_fsize = 0; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1025 |
4892 | 1026 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1027 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 1028 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 1029 |
4944 | 1030 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 1031 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 1032 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
6066 | 1033 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
8677 | 1034 g_signal_connect(G_OBJECT(imhtml), "button_press_event", G_CALLBACK(gtk_imhtml_button_press_event), NULL); |
1035 g_signal_connect(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(preinsert_cb), imhtml); | |
8061 | 1036 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
8091 | 1037 |
1038 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, | |
1039 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | |
1040 GDK_ACTION_COPY); | |
1041 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | |
1042 | |
7353 | 1043 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
8698 | 1044 g_signal_connect(G_OBJECT(imhtml), "cut-clipboard", G_CALLBACK(cut_clipboard_cb), NULL); |
8061 | 1045 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
8677 | 1046 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
|
1047 g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); |
8677 | 1048 |
1049 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
1050 G_CALLBACK(mark_set_so_update_selection_cb), imhtml); | |
1051 | |
4944 | 1052 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
4735 | 1053 |
8681 | 1054 imhtml->clipboard_text_string = NULL; |
1055 imhtml->clipboard_html_string = NULL; | |
1056 | |
4735 | 1057 imhtml->tip = NULL; |
1058 imhtml->tip_timer = 0; | |
1059 imhtml->tip_window = NULL; | |
4895 | 1060 |
8677 | 1061 imhtml->edit.bold = FALSE; |
1062 imhtml->edit.italic = FALSE; | |
1063 imhtml->edit.underline = FALSE; | |
8061 | 1064 imhtml->edit.forecolor = NULL; |
1065 imhtml->edit.backcolor = NULL; | |
1066 imhtml->edit.fontface = NULL; | |
8677 | 1067 imhtml->edit.fontsize = 0; |
1068 imhtml->edit.link = NULL; | |
1069 | |
8061 | 1070 |
4895 | 1071 imhtml->scalables = NULL; |
8061 | 1072 |
1073 gtk_imhtml_set_editable(imhtml, FALSE); | |
8692 | 1074 |
8931 | 1075 g_signal_connect(G_OBJECT(imhtml), "populate-popup", |
1076 G_CALLBACK(hijack_menu_cb), NULL); | |
1077 | |
8692 | 1078 #ifdef _WIN32 |
1079 /* Register HTML Format as desired clipboard format */ | |
1080 win_html_fmt = RegisterClipboardFormat("HTML Format"); | |
1081 #endif | |
2993 | 1082 } |
1083 | |
3922 | 1084 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 1085 { |
4635 | 1086 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 1087 } |
1088 | |
4635 | 1089 GType gtk_imhtml_get_type() |
1428 | 1090 { |
4635 | 1091 static GType imhtml_type = 0; |
1428 | 1092 |
1093 if (!imhtml_type) { | |
4635 | 1094 static const GTypeInfo imhtml_info = { |
1095 sizeof(GtkIMHtmlClass), | |
1096 NULL, | |
1097 NULL, | |
1098 (GClassInitFunc) gtk_imhtml_class_init, | |
1099 NULL, | |
1100 NULL, | |
1428 | 1101 sizeof (GtkIMHtml), |
4635 | 1102 0, |
1103 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 1104 }; |
4635 | 1105 |
1106 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
1107 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 1108 } |
1109 | |
1110 return imhtml_type; | |
1111 } | |
1112 | |
4417 | 1113 struct url_data { |
1114 GObject *object; | |
1115 gchar *url; | |
1116 }; | |
1117 | |
8677 | 1118 static void url_data_destroy(gpointer mydata) |
1119 { | |
1120 struct url_data *data = mydata; | |
1121 g_object_unref(data->object); | |
1122 g_free(data->url); | |
1123 g_free(data); | |
1124 } | |
1125 | |
4417 | 1126 static void url_open(GtkWidget *w, struct url_data *data) { |
1127 if(!data) return; | |
8061 | 1128 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
7988 | 1129 |
4417 | 1130 } |
5582 | 1131 |
4417 | 1132 static void url_copy(GtkWidget *w, gchar *url) { |
1133 GtkClipboard *clipboard; | |
1134 | |
8931 | 1135 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY); |
4417 | 1136 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 1137 |
8931 | 1138 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_CLIPBOARD); |
5582 | 1139 gtk_clipboard_set_text(clipboard, url, -1); |
4417 | 1140 } |
1141 | |
1142 /* The callback for an event on a link tag. */ | |
8677 | 1143 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) { |
4417 | 1144 GdkEventButton *event_button = (GdkEventButton *) event; |
8061 | 1145 if (GTK_IMHTML(imhtml)->editable) |
1146 return FALSE; | |
3922 | 1147 if (event->type == GDK_BUTTON_RELEASE) { |
8957 | 1148 if ((event_button->button == 1) || (event_button->button == 2)) { |
4417 | 1149 GtkTextIter start, end; |
1150 /* we shouldn't open a URL if the user has selected something: */ | |
8677 | 1151 if (gtk_text_buffer_get_selection_bounds( |
1152 gtk_text_iter_get_buffer(arg2), &start, &end)) | |
4417 | 1153 return FALSE; |
1154 | |
1155 /* A link was clicked--we emit the "url_clicked" signal | |
1156 * with the URL as the argument */ | |
8677 | 1157 g_object_ref(G_OBJECT(tag)); |
1158 g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url")); | |
1159 g_object_unref(G_OBJECT(tag)); | |
4417 | 1160 return FALSE; |
1161 } else if(event_button->button == 3) { | |
4745 | 1162 GtkWidget *img, *item, *menu; |
4417 | 1163 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 1164 tempdata->object = g_object_ref(imhtml); |
8677 | 1165 tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url")); |
4745 | 1166 |
5091 | 1167 /* Don't want the tooltip around if user right-clicked on link */ |
1168 if (GTK_IMHTML(imhtml)->tip_window) { | |
1169 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
1170 GTK_IMHTML(imhtml)->tip_window = NULL; | |
1171 } | |
1172 if (GTK_IMHTML(imhtml)->tip_timer) { | |
1173 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
1174 GTK_IMHTML(imhtml)->tip_timer = 0; | |
1175 } | |
8061 | 1176 if (GTK_IMHTML(imhtml)->editable) |
1177 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | |
1178 else | |
1179 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 1180 menu = gtk_menu_new(); |
8677 | 1181 g_object_set_data_full(G_OBJECT(menu), "x-imhtml-url-data", tempdata, url_data_destroy); |
4745 | 1182 |
4417 | 1183 /* buttons and such */ |
1184 | |
8677 | 1185 if (!strncmp(tempdata->url, "mailto:", 7)) |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1186 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1187 /* Copy E-Mail Address */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1188 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1189 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1190 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1191 _("_Copy E-Mail Address")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1192 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
|
1193 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1194 G_CALLBACK(url_copy), tempdata->url + 7); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1195 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1196 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1197 else |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1198 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1199 /* Copy Link Location */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1200 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1201 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1202 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1203 _("_Copy Link Location")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1204 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
|
1205 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1206 G_CALLBACK(url_copy), tempdata->url); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1207 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1208 |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1209 /* Open Link in Browser */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1210 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1211 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1212 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1213 _("_Open Link in Browser")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1214 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
|
1215 g_signal_connect(G_OBJECT(item), "activate", |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1216 G_CALLBACK(url_open), tempdata); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1217 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1218 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1219 |
4756 | 1220 |
4417 | 1221 gtk_widget_show_all(menu); |
4756 | 1222 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
1223 event_button->button, event_button->time); | |
4745 | 1224 |
4417 | 1225 return TRUE; |
1226 } | |
1428 | 1227 } |
4417 | 1228 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
1229 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1230 be caught by the regular GtkTextView menu */ | |
1231 else | |
1232 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 1233 } |
1234 | |
8091 | 1235 static void |
1236 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
1237 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) | |
1238 { | |
1239 if(gtk_imhtml_get_editable(imhtml) && sd->data){ | |
1240 gchar **links; | |
1241 gchar *link; | |
1242 | |
1243 gaim_str_strip_cr(sd->data); | |
1244 | |
1245 links = g_strsplit(sd->data, "\n", 0); | |
1246 while((link = *links++) != NULL){ | |
1247 if(gaim_str_has_prefix(link, "http://") || | |
1248 gaim_str_has_prefix(link, "https://") || | |
1249 gaim_str_has_prefix(link, "ftp://")){ | |
8677 | 1250 gtk_imhtml_insert_link(imhtml, gtk_text_buffer_get_insert(imhtml->text_buffer), link, link); |
8091 | 1251 } else if (link=='\0') { |
8177 | 1252 /* Ignore blank lines */ |
8091 | 1253 } else { |
8177 | 1254 /* Special reasons, aka images being put in via other tag, etc. */ |
8091 | 1255 } |
1256 } | |
1257 | |
1258 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1259 } else { | |
1260 gtk_drag_finish(dc, FALSE, FALSE, t); | |
1261 } | |
1262 } | |
1263 | |
4298 | 1264 /* this isn't used yet |
4032 | 1265 static void |
4263 | 1266 gtk_smiley_tree_remove (GtkSmileyTree *tree, |
1267 GtkIMHtmlSmiley *smiley) | |
4032 | 1268 { |
1269 GtkSmileyTree *t = tree; | |
4263 | 1270 const gchar *x = smiley->smile; |
4032 | 1271 gint len = 0; |
1272 | |
1273 while (*x) { | |
1274 gchar *pos; | |
1275 | |
1276 if (!t->values) | |
1277 return; | |
1278 | |
1279 pos = strchr (t->values->str, *x); | |
1280 if (pos) | |
1281 t = t->children [(int) pos - (int) t->values->str]; | |
1282 else | |
1283 return; | |
1284 | |
1285 x++; len++; | |
1286 } | |
1287 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1288 if (t->image) { |
4032 | 1289 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1290 } |
4032 | 1291 } |
4298 | 1292 */ |
1293 | |
4032 | 1294 |
1295 static gint | |
1296 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
1297 const gchar *text) | |
1298 { | |
1299 GtkSmileyTree *t = tree; | |
1300 const gchar *x = text; | |
1301 gint len = 0; | |
8505 | 1302 gchar *amp; |
1303 gint alen; | |
4032 | 1304 |
1305 while (*x) { | |
1306 gchar *pos; | |
1307 | |
1308 if (!t->values) | |
1309 break; | |
1310 | |
8505 | 1311 if(*x == '&' && gtk_imhtml_is_amp_escape(x, &, &alen)) { |
1312 len += alen - strlen(amp); | |
1313 x += alen - strlen(amp); | |
1314 pos = strchr (t->values->str, *amp); | |
1315 } | |
1316 else | |
1317 pos = strchr (t->values->str, *x); | |
1318 | |
4032 | 1319 if (pos) |
7371 | 1320 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1321 else |
1322 break; | |
1323 | |
1324 x++; len++; | |
1325 } | |
1326 | |
1327 if (t->image) | |
1328 return len; | |
1329 | |
1330 return 0; | |
1331 } | |
1332 | |
1333 void | |
4263 | 1334 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
1335 gchar *sml, | |
1336 GtkIMHtmlSmiley *smiley) | |
4032 | 1337 { |
1338 GtkSmileyTree *tree; | |
1339 g_return_if_fail (imhtml != NULL); | |
1340 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
7371 | 1341 |
4032 | 1342 if (sml == NULL) |
1343 tree = imhtml->default_smilies; | |
1344 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
1345 } else { | |
1346 tree = gtk_smiley_tree_new(); | |
4892 | 1347 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 1348 } |
1349 | |
4263 | 1350 gtk_smiley_tree_insert (tree, smiley); |
4032 | 1351 } |
1352 | |
1353 static gboolean | |
1354 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
1355 GSList *fonts, | |
1356 const gchar *text, | |
1357 gint *len) | |
1358 { | |
1359 GtkSmileyTree *tree; | |
5967 | 1360 GtkIMHtmlFontDetail *font; |
4032 | 1361 char *sml = NULL; |
1362 | |
1363 if (fonts) { | |
1364 font = fonts->data; | |
1365 sml = font->sml; | |
1366 } | |
1367 | |
1368 if (sml == NULL) | |
1369 tree = imhtml->default_smilies; | |
1370 else { | |
1371 tree = g_hash_table_lookup(imhtml->smiley_data, sml); | |
1372 } | |
1373 if (tree == NULL) | |
1374 return FALSE; | |
7371 | 1375 |
8505 | 1376 *len = gtk_smiley_tree_lookup (tree, text); |
4032 | 1377 return (*len > 0); |
1378 } | |
1379 | |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1380 GdkPixbufAnimation * |
4032 | 1381 gtk_smiley_tree_image (GtkIMHtml *imhtml, |
1382 const gchar *sml, | |
1383 const gchar *text) | |
1384 { | |
1385 GtkSmileyTree *t; | |
1386 const gchar *x = text; | |
1387 if (sml == NULL) | |
1388 t = imhtml->default_smilies; | |
7371 | 1389 else |
4032 | 1390 t = g_hash_table_lookup(imhtml->smiley_data, sml); |
7371 | 1391 |
4032 | 1392 |
1393 if (t == NULL) | |
1394 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1395 | |
1396 while (*x) { | |
1397 gchar *pos; | |
1398 | |
1399 if (!t->values) { | |
1400 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1401 } | |
7371 | 1402 |
4032 | 1403 pos = strchr (t->values->str, *x); |
1404 if (pos) { | |
7371 | 1405 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1406 } else { |
1407 return sml ? gtk_smiley_tree_image(imhtml, NULL, text) : NULL; | |
1408 } | |
1409 x++; | |
1410 } | |
1411 | |
8890 | 1412 if (!t->image->file) |
1413 return NULL; | |
1414 | |
4263 | 1415 if (!t->image->icon) |
6814
782907a6ae65
[gaim-migrate @ 7354]
Christian Hammond <chipx86@chipx86.com>
parents:
6648
diff
changeset
|
1416 t->image->icon = gdk_pixbuf_animation_new_from_file(t->image->file, NULL); |
4263 | 1417 |
1418 return t->image->icon; | |
4032 | 1419 } |
8890 | 1420 |
4793 | 1421 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 1422 *tag = g_strndup (string, strlen (x)); \ |
1423 *len = strlen (x) + 1; \ | |
1424 return TRUE; \ | |
1425 } \ | |
1426 (*type)++ | |
1428 | 1427 |
4793 | 1428 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 1429 const gchar *c = string + strlen (x " "); \ |
1430 gchar e = '"'; \ | |
1431 gboolean quote = FALSE; \ | |
1432 while (*c) { \ | |
1433 if (*c == '"' || *c == '\'') { \ | |
1434 if (quote && (*c == e)) \ | |
1435 quote = !quote; \ | |
1436 else if (!quote) { \ | |
1437 quote = !quote; \ | |
1438 e = *c; \ | |
1439 } \ | |
1440 } else if (!quote && (*c == '>')) \ | |
1441 break; \ | |
1442 c++; \ | |
1443 } \ | |
1444 if (*c) { \ | |
1445 *tag = g_strndup (string, c - string); \ | |
1446 *len = c - string + 1; \ | |
1447 return TRUE; \ | |
1448 } \ | |
1449 } \ | |
1450 (*type)++ | |
1428 | 1451 |
1452 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1453 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1454 gtk_imhtml_is_amp_escape (const gchar *string, |
7280 | 1455 gchar **replace, |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1456 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1457 { |
7287 | 1458 static char buf[7]; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1459 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1460 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1461 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1462 |
4793 | 1463 if (!g_ascii_strncasecmp (string, "&", 5)) { |
7280 | 1464 *replace = "&"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1465 *length = 5; |
4793 | 1466 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
7280 | 1467 *replace = "<"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1468 *length = 4; |
4793 | 1469 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
7280 | 1470 *replace = ">"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1471 *length = 4; |
4793 | 1472 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
7280 | 1473 *replace = " "; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1474 *length = 6; |
4793 | 1475 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
7280 | 1476 *replace = "©"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1477 *length = 6; |
4793 | 1478 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
7280 | 1479 *replace = "\""; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1480 *length = 6; |
4793 | 1481 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
7280 | 1482 *replace = "®"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1483 *length = 5; |
5093 | 1484 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
7280 | 1485 *replace = "\'"; |
5093 | 1486 *length = 6; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1487 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
1488 guint pound = 0; |
3004 | 1489 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
7287 | 1490 int buflen; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1491 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1492 return FALSE; |
7287 | 1493 buflen = g_unichar_to_utf8((gunichar)pound, buf); |
1494 buf[buflen] = '\0'; | |
7280 | 1495 *replace = buf; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1496 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1497 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1498 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1499 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1500 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1501 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1502 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1503 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1504 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1505 |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1506 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1507 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1508 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1509 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1510 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1511 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1512 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1513 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1514 { |
8061 | 1515 char *close; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1516 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1517 |
8118 | 1518 |
8061 | 1519 if (!(close = strchr (string, '>'))) |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1520 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1521 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1522 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1523 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1524 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1525 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1526 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1527 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1528 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1529 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1530 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1531 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1532 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1533 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1534 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1535 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1536 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1537 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1538 VALID_TAG ("SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1539 VALID_TAG ("/SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1540 VALID_TAG ("SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1541 VALID_TAG ("/SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1542 VALID_TAG ("PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1543 VALID_TAG ("/PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1544 VALID_TAG ("TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1545 VALID_TAG ("/TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1546 VALID_TAG ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1547 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1548 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1549 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1550 VALID_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1551 VALID_TAG ("/P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1552 VALID_TAG ("H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1553 VALID_TAG ("/H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1554 VALID_TAG ("HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1555 VALID_TAG ("/HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1556 VALID_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1557 VALID_TAG ("/BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1558 VALID_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1559 VALID_TAG ("HEAD"); |
2993 | 1560 VALID_TAG ("/HEAD"); |
1561 VALID_TAG ("BINARY"); | |
1562 VALID_TAG ("/BINARY"); | |
5093 | 1563 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1564 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1565 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1566 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1567 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1568 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1569 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1570 VALID_OPT_TAG ("H3"); |
5093 | 1571 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1572 |
5101 | 1573 VALID_TAG ("CITE"); |
1574 VALID_TAG ("/CITE"); | |
1575 VALID_TAG ("EM"); | |
1576 VALID_TAG ("/EM"); | |
1577 VALID_TAG ("STRONG"); | |
1578 VALID_TAG ("/STRONG"); | |
1579 | |
5104 | 1580 VALID_OPT_TAG ("SPAN"); |
1581 VALID_TAG ("/SPAN"); | |
5174 | 1582 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
6982 | 1583 VALID_TAG ("IMG"); |
8026 | 1584 VALID_TAG("SPAN"); |
8061 | 1585 VALID_OPT_TAG("BR"); |
7988 | 1586 |
4793 | 1587 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
1588 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1589 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1590 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1591 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1592 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1593 } |
8118 | 1594 } |
1595 | |
8061 | 1596 *type = -1; |
1597 *len = close - string + 1; | |
1598 *tag = g_strndup(string, *len - 1); | |
1599 return TRUE; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1600 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1601 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1602 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1603 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1604 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1605 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1606 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1607 gchar *e, *a; |
5177 | 1608 gchar *val; |
1609 gint len; | |
7280 | 1610 gchar *c; |
5177 | 1611 GString *ret; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1612 |
4793 | 1613 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1614 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1615 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1616 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1617 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1618 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1619 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1620 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1621 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1622 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1623 |
4793 | 1624 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1625 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1626 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1627 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1628 } |
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 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1631 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1632 while (*e && (*e != *(t - 1))) e++; |
2993 | 1633 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1634 return NULL; |
5177 | 1635 } else |
1636 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1637 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1638 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1639 while (*e && !isspace ((gint) *e)) e++; |
5177 | 1640 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1641 } |
5177 | 1642 |
1643 ret = g_string_new(""); | |
1644 e = val; | |
1645 while(*e) { | |
1646 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
7280 | 1647 ret = g_string_append(ret, c); |
5177 | 1648 e += len; |
1649 } else { | |
1650 ret = g_string_append_c(ret, *e); | |
1651 e++; | |
1652 } | |
1653 } | |
1654 | |
1655 g_free(val); | |
8568 | 1656 |
1657 return g_string_free(ret, FALSE); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1658 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1659 |
8118 | 1660 /* Inline CSS Support - Douglas Thrift */ |
1661 static gchar* | |
1662 gtk_imhtml_get_css_opt (gchar *style, | |
1663 const gchar *opt) | |
1664 { | |
1665 gchar *t = style; | |
1666 gchar *e, *a; | |
1667 gchar *val; | |
1668 gint len; | |
1669 gchar *c; | |
1670 GString *ret; | |
1671 | |
1672 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
8177 | 1673 /* gboolean quote = FALSE; */ |
8118 | 1674 if (*t == '\0') break; |
1675 while (*t && !((*t == ' ') /*&& !quote*/)) { | |
1676 /* if (*t == '\"') | |
8177 | 1677 quote = ! quote; */ |
8118 | 1678 t++; |
1679 } | |
1680 while (*t && (*t == ' ')) t++; | |
1681 } | |
1682 | |
1683 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
1684 t += strlen (opt); | |
1685 } else { | |
1686 return NULL; | |
1687 } | |
1688 | |
1689 /* if ((*t == '\"') || (*t == '\'')) { | |
1690 e = a = ++t; | |
1691 while (*e && (*e != *(t - 1))) e++; | |
1692 if (*e == '\0') { | |
1693 return NULL; | |
1694 } else | |
1695 val = g_strndup(a, e - a); | |
1696 } else { | |
1697 e = a = t; | |
1698 while (*e && !isspace ((gint) *e)) e++; | |
1699 val = g_strndup(a, e - a); | |
1700 }*/ | |
1701 | |
1702 e = a = t; | |
1703 while (*e && *e != ';') e++; | |
1704 val = g_strndup(a, e - a); | |
1705 | |
1706 ret = g_string_new(""); | |
1707 e = val; | |
1708 while(*e) { | |
1709 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
1710 ret = g_string_append(ret, c); | |
1711 e += len; | |
1712 } else { | |
1713 ret = g_string_append_c(ret, *e); | |
1714 e++; | |
1715 } | |
1716 } | |
1717 | |
1718 g_free(val); | |
1719 val = ret->str; | |
1720 g_string_free(ret, FALSE); | |
1721 return val; | |
1722 } | |
3922 | 1723 |
8334 | 1724 static const char *accepted_protocols[] = { |
1725 "http://", | |
1726 "https://", | |
1727 "ftp://" | |
1728 }; | |
1729 | |
1730 static const int accepted_protocols_size = 3; | |
1731 | |
1732 /* returns if the beginning of the text is a protocol. If it is the protocol, returns the length so | |
1733 the caller knows how long the protocol string is. */ | |
1734 int gtk_imhtml_is_protocol(const char *text) | |
1735 { | |
1736 gint i; | |
1737 | |
1738 for(i=0; i<accepted_protocols_size; i++){ | |
1739 if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ | |
1740 return strlen(accepted_protocols[i]); | |
1741 } | |
1742 } | |
1743 return 0; | |
1744 } | |
1745 | |
8677 | 1746 /* |
1747 <KingAnt> marv: The two IM image functions in oscar are gaim_odc_send_im and gaim_odc_incoming | |
1748 | |
1749 | |
1750 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) | |
1751 [19:59] <KingAnt> marv: I think the image tag used by the core is something like <img id="#"/> | |
1752 [19:59] Ro0tSiEgE robert42 RobFlynn Robot101 ross22 roz | |
1753 [20:00] <KingAnt> marv: Where the ID is the what is returned when you add the image to the imgstore using gaim_imgstore_add | |
1754 [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? | |
1755 [20:00] <KingAnt> marv: Right | |
1756 [20:00] <marv> alright | |
1757 | |
1758 Here's my plan with IMImages. make gtk_imhtml_[append|insert]_text_with_images instead just | |
1759 gtkimhtml_[append|insert]_text (hrm maybe it should be called html instead of text), add a | |
1760 function for gaim to register for look up images, i.e. gtk_imhtml_set_get_img_fnc, so that | |
1761 images can be looked up like that, instead of passing a GSList of them. | |
1762 */ | |
1763 | |
1764 void gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | |
1765 const gchar *text, | |
1766 GtkIMHtmlOptions options, | |
1767 GSList *unused) | |
1428 | 1768 { |
8677 | 1769 GtkTextIter iter, ins, sel; |
1770 GdkRectangle rect; | |
1771 int y, height, ins_offset = 0, sel_offset = 0; | |
1772 gboolean fixins = FALSE, fixsel = FALSE; | |
1773 | |
1774 g_return_if_fail (imhtml != NULL); | |
1775 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
1776 g_return_if_fail (text != NULL); | |
1777 | |
1778 | |
1779 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1780 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
1781 if (gtk_text_iter_equal(&iter, &ins) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1782 fixins = TRUE; | |
1783 ins_offset = gtk_text_iter_get_offset(&ins); | |
1784 } | |
1785 | |
1786 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &sel, gtk_text_buffer_get_selection_bound(imhtml->text_buffer)); | |
1787 if (gtk_text_iter_equal(&iter, &sel) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1788 fixsel = TRUE; | |
1789 sel_offset = gtk_text_iter_get_offset(&sel); | |
1790 } | |
1791 | |
1792 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1793 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1794 | |
1795 | |
1796 if(((y + height) - (rect.y + rect.height)) > height | |
1797 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1798 options |= GTK_IMHTML_NO_SCROLL; | |
1799 } | |
1800 | |
1801 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); | |
1802 | |
1803 if (fixins) { | |
1804 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins, ins_offset); | |
1805 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_insert(imhtml->text_buffer), &ins); | |
1806 } | |
1807 | |
1808 if (fixsel) { | |
1809 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &sel, sel_offset); | |
1810 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_selection_bound(imhtml->text_buffer), &sel); | |
1811 } | |
1812 | |
1813 if (!(options & GTK_IMHTML_NO_SCROLL)) { | |
8729 | 1814 gtk_imhtml_scroll_to_end(imhtml); |
8677 | 1815 } |
1816 } | |
1817 | |
8729 | 1818 void gtk_imhtml_scroll_to_end(GtkIMHtml *imhtml) |
1819 { | |
1820 GtkTextIter iter; | |
1821 /* If this seems backwards at first glance, well it's not. | |
1822 * It means scroll such that the mark is closest to the top, | |
1823 * and closest to the right as possible. Remember kids, you have | |
1824 * to scroll left to move a given spot closest to the right, | |
1825 * and scroll down to move a spot closest to the top. | |
1826 */ | |
1827 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1828 gtk_text_iter_set_line_offset(&iter, 0); | |
1829 gtk_text_buffer_move_mark(imhtml->text_buffer, imhtml->scrollpoint, &iter); | |
1830 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), imhtml->scrollpoint, | |
1831 0, TRUE, 1.0, 0.0); | |
1832 } | |
1833 | |
8677 | 1834 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, |
1835 const gchar *text, | |
1836 GtkIMHtmlOptions options, | |
1837 GtkTextIter *iter) | |
1838 { | |
8061 | 1839 GdkRectangle rect; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1840 gint pos = 0; |
3922 | 1841 gchar *ws; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1842 gchar *tag; |
3922 | 1843 gchar *bg = NULL; |
6982 | 1844 gint len; |
4032 | 1845 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1846 gint type; |
3922 | 1847 const gchar *c; |
7280 | 1848 gchar *amp; |
8334 | 1849 gint len_protocol; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1850 |
1428 | 1851 guint bold = 0, |
1852 italics = 0, | |
1853 underline = 0, | |
1854 strike = 0, | |
1855 sub = 0, | |
1856 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
1857 title = 0, |
8061 | 1858 pre = 0; |
1428 | 1859 |
3922 | 1860 GSList *fonts = NULL; |
8506 | 1861 GObject *object; |
8061 | 1862 GtkIMHtmlScalable *scalable = NULL; |
8677 | 1863 |
1864 g_return_if_fail (imhtml != NULL); | |
1865 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
1866 g_return_if_fail (text != NULL); | |
3922 | 1867 c = text; |
6982 | 1868 len = strlen(text); |
3922 | 1869 ws = g_malloc(len + 1); |
1870 ws[0] = 0; | |
1428 | 1871 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1872 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1873 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1874 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1875 pos++; |
8061 | 1876 ws[wpos] = '\0'; |
1877 switch (type) | |
3922 | 1878 { |
1879 case 1: /* B */ | |
1880 case 2: /* BOLD */ | |
5101 | 1881 case 54: /* STRONG */ |
8677 | 1882 |
1883 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
1884 | |
1885 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD)) | |
8061 | 1886 gtk_imhtml_toggle_bold(imhtml); |
3922 | 1887 bold++; |
8061 | 1888 ws[0] = '\0'; wpos = 0; |
3922 | 1889 break; |
1890 case 3: /* /B */ | |
1891 case 4: /* /BOLD */ | |
5101 | 1892 case 55: /* /STRONG */ |
8677 | 1893 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1894 ws[0] = '\0'; wpos = 0; |
1895 | |
3922 | 1896 if (bold) |
1897 bold--; | |
8677 | 1898 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD) && !imhtml->wbfo) |
8061 | 1899 gtk_imhtml_toggle_bold(imhtml); |
3922 | 1900 break; |
1901 case 5: /* I */ | |
1902 case 6: /* ITALIC */ | |
5101 | 1903 case 52: /* EM */ |
8677 | 1904 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1905 ws[0] = '\0'; wpos = 0; |
8677 | 1906 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC)) |
8061 | 1907 gtk_imhtml_toggle_italic(imhtml); |
3922 | 1908 italics++; |
1909 break; | |
1910 case 7: /* /I */ | |
1911 case 8: /* /ITALIC */ | |
5101 | 1912 case 53: /* /EM */ |
8677 | 1913 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1914 ws[0] = '\0'; wpos = 0; |
3922 | 1915 if (italics) |
1916 italics--; | |
8677 | 1917 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC) && !imhtml->wbfo) |
8061 | 1918 gtk_imhtml_toggle_italic(imhtml); |
3922 | 1919 break; |
1920 case 9: /* U */ | |
1921 case 10: /* UNDERLINE */ | |
8677 | 1922 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1923 ws[0] = '\0'; wpos = 0; |
8677 | 1924 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
8061 | 1925 gtk_imhtml_toggle_underline(imhtml); |
3922 | 1926 underline++; |
1927 break; | |
1928 case 11: /* /U */ | |
1929 case 12: /* /UNDERLINE */ | |
8677 | 1930 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 1931 ws[0] = '\0'; wpos = 0; |
3922 | 1932 if (underline) |
1933 underline--; | |
8677 | 1934 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE) && !imhtml->wbfo) |
8061 | 1935 gtk_imhtml_toggle_underline(imhtml); |
3922 | 1936 break; |
1937 case 13: /* S */ | |
1938 case 14: /* STRIKE */ | |
8677 | 1939 /* FIXME: reimplement this */ |
3922 | 1940 strike++; |
1941 break; | |
1942 case 15: /* /S */ | |
1943 case 16: /* /STRIKE */ | |
8677 | 1944 /* FIXME: reimplement this */ |
3922 | 1945 if (strike) |
1946 strike--; | |
1947 break; | |
1948 case 17: /* SUB */ | |
8677 | 1949 /* FIXME: reimpliment this */ |
3922 | 1950 sub++; |
1951 break; | |
1952 case 18: /* /SUB */ | |
8677 | 1953 /* FIXME: reimpliment this */ |
3922 | 1954 if (sub) |
1955 sub--; | |
1956 break; | |
1957 case 19: /* SUP */ | |
8677 | 1958 /* FIXME: reimplement this */ |
3922 | 1959 sup++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1960 break; |
3922 | 1961 case 20: /* /SUP */ |
8677 | 1962 /* FIXME: reimplement this */ |
3922 | 1963 if (sup) |
1964 sup--; | |
1965 break; | |
1966 case 21: /* PRE */ | |
8677 | 1967 /* FIXME: reimplement this */ |
3922 | 1968 pre++; |
1969 break; | |
1970 case 22: /* /PRE */ | |
8677 | 1971 /* FIXME: reimplement this */ |
3922 | 1972 if (pre) |
1973 pre--; | |
1974 break; | |
1975 case 23: /* TITLE */ | |
8677 | 1976 /* FIXME: what was this supposed to do anyway? */ |
3922 | 1977 title++; |
1978 break; | |
1979 case 24: /* /TITLE */ | |
8677 | 1980 /* FIXME: make this undo whatever 23 was supposed to do */ |
3922 | 1981 if (title) { |
1982 if (options & GTK_IMHTML_NO_TITLE) { | |
1983 wpos = 0; | |
1984 ws [wpos] = '\0'; | |
1985 } | |
1986 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1987 } |
3922 | 1988 break; |
1989 case 25: /* BR */ | |
5174 | 1990 case 58: /* BR/ */ |
8061 | 1991 case 61: /* BR (opt) */ |
3922 | 1992 ws[wpos] = '\n'; |
1993 wpos++; | |
6982 | 1994 break; |
3922 | 1995 case 26: /* HR */ |
1996 case 42: /* HR (opt) */ | |
8726 | 1997 { |
1998 int minus; | |
1999 | |
3922 | 2000 ws[wpos++] = '\n'; |
8677 | 2001 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2002 | |
5967 | 2003 scalable = gtk_imhtml_hr_new(); |
8061 | 2004 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
8677 | 2005 scalable->add_to(scalable, imhtml, iter); |
8726 | 2006 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + |
2007 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
2008 scalable->scale(scalable, rect.width - minus, rect.height); | |
8061 | 2009 imhtml->scalables = g_list_append(imhtml->scalables, scalable); |
2010 ws[0] = '\0'; wpos = 0; | |
7942 | 2011 ws[wpos++] = '\n'; |
8061 | 2012 |
3922 | 2013 break; |
8726 | 2014 } |
3922 | 2015 case 27: /* /FONT */ |
8677 | 2016 if (fonts && !imhtml->wbfo) { |
5967 | 2017 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2018 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2019 ws[0] = '\0'; wpos = 0; |
8177 | 2020 /* NEW_BIT (NEW_TEXT_BIT); */ |
8677 | 2021 |
8698 | 2022 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) { |
8061 | 2023 gtk_imhtml_toggle_fontface(imhtml, NULL); |
3922 | 2024 g_free (font->face); |
8061 | 2025 } |
8698 | 2026 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
8061 | 2027 gtk_imhtml_toggle_forecolor(imhtml, NULL); |
3922 | 2028 g_free (font->fore); |
8061 | 2029 } |
8698 | 2030 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
8061 | 2031 gtk_imhtml_toggle_backcolor(imhtml, NULL); |
3922 | 2032 g_free (font->back); |
8061 | 2033 } |
4032 | 2034 if (font->sml) |
2035 g_free (font->sml); | |
3922 | 2036 g_free (font); |
8309 | 2037 |
8698 | 2038 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2039 gtk_imhtml_font_set_size(imhtml, 3); |
2040 | |
2041 fonts = fonts->next; | |
2042 if (fonts) { | |
2043 GtkIMHtmlFontDetail *font = fonts->data; | |
8677 | 2044 |
8698 | 2045 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8309 | 2046 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8698 | 2047 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8309 | 2048 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8698 | 2049 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
8309 | 2050 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8698 | 2051 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2052 gtk_imhtml_font_set_size(imhtml, font->size); |
2053 } | |
3922 | 2054 } |
8309 | 2055 break; |
3922 | 2056 case 28: /* /A */ |
8677 | 2057 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2058 gtk_imhtml_toggle_link(imhtml, NULL); | |
2059 ws[0] = '\0'; wpos = 0; | |
8061 | 2060 break; |
8118 | 2061 |
3922 | 2062 case 29: /* P */ |
2063 case 30: /* /P */ | |
2064 case 31: /* H3 */ | |
2065 case 32: /* /H3 */ | |
2066 case 33: /* HTML */ | |
2067 case 34: /* /HTML */ | |
2068 case 35: /* BODY */ | |
2069 case 36: /* /BODY */ | |
2070 case 37: /* FONT */ | |
2071 case 38: /* HEAD */ | |
2072 case 39: /* /HEAD */ | |
6982 | 2073 case 40: /* BINARY */ |
2074 case 41: /* /BINARY */ | |
3922 | 2075 break; |
2076 case 43: /* FONT (opt) */ | |
2077 { | |
4032 | 2078 gchar *color, *back, *face, *size, *sml; |
5967 | 2079 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 2080 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
2081 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
2082 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
2083 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 2084 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
2085 if (!(color || back || face || size || sml)) | |
3922 | 2086 break; |
8061 | 2087 |
8677 | 2088 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2089 ws[0] = '\0'; wpos = 0; |
2090 | |
5967 | 2091 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 2092 if (fonts) |
2093 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2094 |
8677 | 2095 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
3922 | 2096 font->fore = color; |
8061 | 2097 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8677 | 2098 } |
8309 | 2099 //else if (oldfont && oldfont->fore) |
2100 // font->fore = g_strdup(oldfont->fore); | |
8677 | 2101 |
2102 if (back && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { | |
3922 | 2103 font->back = back; |
8061 | 2104 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8309 | 2105 } |
2106 //else if (oldfont && oldfont->back) | |
2107 // font->back = g_strdup(oldfont->back); | |
8677 | 2108 |
2109 if (face && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) { | |
3922 | 2110 font->face = face; |
8061 | 2111 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8309 | 2112 } |
2113 //else if (oldfont && oldfont->face) | |
2114 // font->face = g_strdup(oldfont->face); | |
4032 | 2115 |
2116 if (sml) | |
2117 font->sml = sml; | |
2118 else if (oldfont && oldfont->sml) | |
2119 font->sml = g_strdup(oldfont->sml); | |
2120 | |
8677 | 2121 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) { |
3922 | 2122 if (*size == '+') { |
2123 sscanf (size + 1, "%hd", &font->size); | |
2124 font->size += 3; | |
2125 } else if (*size == '-') { | |
2126 sscanf (size + 1, "%hd", &font->size); | |
2127 font->size = MAX (0, 3 - font->size); | |
2128 } else if (isdigit (*size)) { | |
2129 sscanf (size, "%hd", &font->size); | |
8061 | 2130 } |
6042 | 2131 if (font->size > 100) |
2132 font->size = 100; | |
3922 | 2133 } else if (oldfont) |
2134 font->size = oldfont->size; | |
8309 | 2135 else |
2136 font->size = 3; | |
8698 | 2137 if ((imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
2138 gtk_imhtml_font_set_size(imhtml, font->size); | |
3922 | 2139 g_free(size); |
2140 fonts = g_slist_prepend (fonts, font); | |
2141 } | |
2142 break; | |
2143 case 44: /* BODY (opt) */ | |
2144 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
2145 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
8677 | 2146 if (bgcolor && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
2147 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2148 ws[0] = '\0'; wpos = 0; |
8177 | 2149 /* NEW_BIT(NEW_TEXT_BIT); */ |
3922 | 2150 if (bg) |
2151 g_free(bg); | |
2152 bg = bgcolor; | |
8061 | 2153 gtk_imhtml_toggle_backcolor(imhtml, bg); |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
2154 } |
1428 | 2155 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2156 break; |
3922 | 2157 case 45: /* A (opt) */ |
2158 { | |
2159 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
8677 | 2160 if (href && (imhtml->format_functions & GTK_IMHTML_LINK)) { |
2161 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2162 ws[0] = '\0'; wpos = 0; |
8677 | 2163 gtk_imhtml_toggle_link(imhtml, href); |
3922 | 2164 } |
2993 | 2165 } |
3922 | 2166 break; |
4895 | 2167 case 46: /* IMG (opt) */ |
6982 | 2168 case 59: /* IMG */ |
4895 | 2169 { |
8677 | 2170 #if 0 |
2171 /* disabling this for now, it's easy to add it back... */ | |
6982 | 2172 GdkPixbuf *img = NULL; |
2173 const gchar *filename = NULL; | |
4895 | 2174 |
8677 | 2175 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) |
2176 break; | |
2177 | |
6982 | 2178 if (images && images->data) { |
2179 img = images->data; | |
2180 images = images->next; | |
2181 filename = g_object_get_data(G_OBJECT(img), "filename"); | |
2182 g_object_ref(G_OBJECT(img)); | |
2183 } else { | |
2184 img = gtk_widget_render_icon(GTK_WIDGET(imhtml), | |
2185 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, | |
2186 "gtkimhtml-missing-image"); | |
2187 } | |
4895 | 2188 |
6982 | 2189 scalable = gtk_imhtml_image_new(img, filename); |
8177 | 2190 /* NEW_BIT(NEW_SCALABLE_BIT); */ |
8677 | 2191 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
2192 scalable->add_to(scalable, imhtml, iter); | |
2193 scalable->scale(scalable, rect.width, rect.height); | |
2194 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
2195 | |
6982 | 2196 g_object_unref(G_OBJECT(img)); |
8677 | 2197 #endif |
4895 | 2198 } |
3922 | 2199 case 47: /* P (opt) */ |
2200 case 48: /* H3 (opt) */ | |
5093 | 2201 case 49: /* HTML (opt) */ |
5101 | 2202 case 50: /* CITE */ |
2203 case 51: /* /CITE */ | |
8026 | 2204 case 56: /* SPAN (opt) */ |
8118 | 2205 /* Inline CSS Support - Douglas Thrift |
2206 * | |
2207 * color | |
8686 | 2208 * background |
8118 | 2209 * font-family |
2210 * font-size | |
8686 | 2211 * text-decoration: underline |
8118 | 2212 */ |
2213 { | |
8686 | 2214 gchar *style, *color, *background, *family, *size; |
2215 gchar *textdec; | |
8118 | 2216 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
2217 style = gtk_imhtml_get_html_opt (tag, "style="); | |
2218 | |
2219 if (!style) break; | |
2220 | |
2221 color = gtk_imhtml_get_css_opt (style, "color: "); | |
8686 | 2222 background = gtk_imhtml_get_css_opt (style, "background: "); |
8118 | 2223 family = gtk_imhtml_get_css_opt (style, |
2224 "font-family: "); | |
2225 size = gtk_imhtml_get_css_opt (style, "font-size: "); | |
8686 | 2226 textdec = gtk_imhtml_get_css_opt (style, "text-decoration: "); |
2227 | |
2228 if (!(color || family || size || background || textdec)) { | |
8120 | 2229 g_free(style); |
2230 break; | |
2231 } | |
8118 | 2232 |
8677 | 2233 |
2234 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8118 | 2235 ws[0] = '\0'; wpos = 0; |
8177 | 2236 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2237 |
2238 font = g_new0 (GtkIMHtmlFontDetail, 1); | |
2239 if (fonts) | |
2240 oldfont = fonts->data; | |
2241 | |
8677 | 2242 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8686 | 2243 { |
8118 | 2244 font->fore = color; |
8686 | 2245 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
2246 } | |
8118 | 2247 else if (oldfont && oldfont->fore) |
2248 font->fore = g_strdup(oldfont->fore); | |
2249 | |
8686 | 2250 if (background && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
2251 { | |
2252 font->back = background; | |
2253 gtk_imhtml_toggle_backcolor(imhtml, font->back); | |
2254 } | |
2255 else if (oldfont && oldfont->back) | |
8118 | 2256 font->back = g_strdup(oldfont->back); |
2257 | |
8677 | 2258 if (family && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8686 | 2259 { |
8118 | 2260 font->face = family; |
8686 | 2261 gtk_imhtml_toggle_fontface(imhtml, font->face); |
2262 } | |
8118 | 2263 else if (oldfont && oldfont->face) |
2264 font->face = g_strdup(oldfont->face); | |
2265 if (font->face && (atoi(font->face) > 100)) { | |
8677 | 2266 /* WTF is this? */ |
8118 | 2267 g_free(font->face); |
2268 font->face = g_strdup("100"); | |
2269 } | |
2270 | |
2271 if (oldfont && oldfont->sml) | |
2272 font->sml = g_strdup(oldfont->sml); | |
2273 | |
8677 | 2274 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_SHRINK|GTK_IMHTML_GROW))) { |
8686 | 2275 if (g_ascii_strcasecmp(size, "xx-small") == 0) |
2276 font->size = 1; | |
2277 else if (g_ascii_strcasecmp(size, "smaller") == 0 | |
2278 || g_ascii_strcasecmp(size, "x-small") == 0) | |
8118 | 2279 font->size = 2; |
8686 | 2280 else if (g_ascii_strcasecmp(size, "larger") == 0 |
2281 || g_ascii_strcasecmp(size, "medium") == 0) | |
8118 | 2282 font->size = 4; |
8686 | 2283 else if (g_ascii_strcasecmp(size, "large") == 0) |
2284 font->size = 5; | |
2285 else if (g_ascii_strcasecmp(size, "x-large") == 0) | |
2286 font->size = 6; | |
2287 else if (g_ascii_strcasecmp(size, "xx-large") == 0) | |
2288 font->size = 7; | |
8118 | 2289 else |
2290 font->size = 3; | |
8686 | 2291 gtk_imhtml_font_set_size(imhtml, font->size); |
2292 } | |
2293 else if (oldfont) | |
2294 { | |
2295 font->size = oldfont->size; | |
2296 } | |
2297 | |
2298 if (oldfont) | |
2299 { | |
2300 font->underline = oldfont->underline; | |
2301 } | |
2302 if (textdec && font->underline != 1 | |
8858 | 2303 && size |
8686 | 2304 && g_ascii_strcasecmp(size, "underline") == 0 |
2305 && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) | |
2306 { | |
2307 gtk_imhtml_toggle_underline(imhtml); | |
2308 font->underline = 1; | |
2309 } | |
8118 | 2310 |
2311 g_free(style); | |
2312 g_free(size); | |
2313 fonts = g_slist_prepend (fonts, font); | |
2314 } | |
2315 break; | |
5104 | 2316 case 57: /* /SPAN */ |
8118 | 2317 /* Inline CSS Support - Douglas Thrift */ |
8677 | 2318 if (fonts && !imhtml->wbfo) { |
8686 | 2319 GtkIMHtmlFontDetail *oldfont = NULL; |
8118 | 2320 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2321 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8118 | 2322 ws[0] = '\0'; wpos = 0; |
8177 | 2323 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2324 fonts = g_slist_remove (fonts, font); |
8692 | 2325 if (fonts) |
2326 oldfont = fonts->data; | |
2327 | |
2328 if (!oldfont) { | |
2329 gtk_imhtml_font_set_size(imhtml, 3); | |
2330 if (font->underline) | |
2331 gtk_imhtml_toggle_underline(imhtml); | |
2332 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
2333 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
2334 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
8686 | 2335 } |
8692 | 2336 else |
8686 | 2337 { |
8692 | 2338 |
2339 if (font->size != oldfont->size) | |
2340 gtk_imhtml_font_set_size(imhtml, oldfont->size); | |
2341 | |
2342 if (font->underline != oldfont->underline) | |
2343 gtk_imhtml_toggle_underline(imhtml); | |
2344 | |
2345 if (!oldfont->face || strcmp(font->face, oldfont->face) != 0) | |
2346 gtk_imhtml_toggle_fontface(imhtml, oldfont->face); | |
2347 | |
2348 if (!oldfont->fore || strcmp(font->fore, oldfont->fore) != 0) | |
2349 gtk_imhtml_toggle_forecolor(imhtml, oldfont->fore); | |
2350 | |
2351 if (!oldfont->back || strcmp(font->back, oldfont->back) != 0) | |
2352 gtk_imhtml_toggle_backcolor(imhtml, oldfont->back); | |
8686 | 2353 } |
8692 | 2354 |
2355 g_free (font->face); | |
2356 g_free (font->fore); | |
2357 g_free (font->back); | |
2358 g_free (font->sml); | |
2359 | |
8118 | 2360 g_free (font); |
2361 } | |
2362 break; | |
8026 | 2363 case 60: /* SPAN */ |
2993 | 2364 break; |
8061 | 2365 case 62: /* comment */ |
8177 | 2366 /* NEW_BIT (NEW_TEXT_BIT); */ |
8317 | 2367 ws[wpos] = '\0'; |
8677 | 2368 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2369 | |
6124 | 2370 if (imhtml->show_comments) |
2371 wpos = g_snprintf (ws, len, "%s", tag); | |
8177 | 2372 /* NEW_BIT (NEW_COMMENT_BIT); */ |
3922 | 2373 break; |
2374 default: | |
6882 | 2375 break; |
2993 | 2376 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2377 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2378 pos += tlen; |
4138 | 2379 if(tag) |
2380 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
8881 | 2381 } else if (gtk_imhtml_is_smiley (imhtml, fonts, c, &smilelen) || gtk_imhtml_is_smiley(imhtml, NULL, c, &smilelen)) { |
8473 | 2382 GtkIMHtmlFontDetail *fd; |
2383 | |
2384 gchar *sml = NULL; | |
2385 if (fonts) { | |
2386 fd = fonts->data; | |
2387 sml = fd->sml; | |
2388 } | |
8677 | 2389 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8505 | 2390 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
8473 | 2391 |
8677 | 2392 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, ws, iter); |
8473 | 2393 |
8505 | 2394 c += smilelen; |
2395 pos += smilelen; | |
8473 | 2396 wpos = 0; |
2397 ws[0] = 0; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2398 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
7280 | 2399 while(*amp) { |
2400 ws [wpos++] = *amp++; | |
2401 } | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2402 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2403 pos += tlen; |
1428 | 2404 } else if (*c == '\n') { |
2405 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 2406 ws[wpos] = '\n'; |
2407 wpos++; | |
8677 | 2408 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2409 ws[0] = '\0'; |
2410 wpos = 0; | |
8177 | 2411 /* NEW_BIT (NEW_TEXT_BIT); */ |
1428 | 2412 } |
2413 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2414 pos++; |
8334 | 2415 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
2416 while(len_protocol--){ | |
8677 | 2417 /* Skip the next len_protocol characters, but make sure they're |
8334 | 2418 copied into the ws array. |
2419 */ | |
2420 ws [wpos++] = *c++; | |
2421 pos++; | |
2422 } | |
8061 | 2423 } else if (*c) { |
1428 | 2424 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2425 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2426 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2427 break; |
1428 | 2428 } |
2429 } | |
8677 | 2430 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2431 ws[0] = '\0'; wpos = 0; |
2432 | |
8177 | 2433 /* NEW_BIT(NEW_TEXT_BIT); */ |
8061 | 2434 |
4032 | 2435 while (fonts) { |
5967 | 2436 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 2437 fonts = g_slist_remove (fonts, font); |
2438 if (font->face) | |
2439 g_free (font->face); | |
2440 if (font->fore) | |
2441 g_free (font->fore); | |
2442 if (font->back) | |
2443 g_free (font->back); | |
2444 if (font->sml) | |
2445 g_free (font->sml); | |
2446 g_free (font); | |
2447 } | |
8932 | 2448 |
2449 g_free(ws); | |
2450 if (bg) | |
4630 | 2451 g_free(bg); |
8677 | 2452 |
2453 if (!imhtml->wbfo) | |
8698 | 2454 gtk_imhtml_close_tags(imhtml, iter); |
8506 | 2455 |
2456 object = g_object_ref(G_OBJECT(imhtml)); | |
2457 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | |
2458 g_object_unref(object); | |
2459 | |
3922 | 2460 } |
2461 | |
4892 | 2462 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
2463 { | |
4288 | 2464 g_hash_table_destroy(imhtml->smiley_data); |
2465 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 2466 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 2467 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 2468 imhtml->default_smilies = gtk_smiley_tree_new(); |
2469 } | |
8481 | 2470 |
3922 | 2471 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, |
4253 | 2472 gboolean show) |
2473 { | |
6124 | 2474 imhtml->show_comments = show; |
4253 | 2475 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2476 |
8456 | 2477 void gtk_imhtml_html_shortcuts (GtkIMHtml *imhtml, |
2478 gboolean allow) | |
2479 { | |
2480 imhtml->html_shortcuts = allow; | |
2481 } | |
2482 | |
2483 void gtk_imhtml_smiley_shortcuts (GtkIMHtml *imhtml, | |
2484 gboolean allow) | |
2485 { | |
2486 imhtml->smiley_shortcuts = allow; | |
2487 } | |
2488 | |
2489 void | |
2490 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, gchar *protocol_name) { | |
2491 imhtml->protocol_name = protocol_name; | |
2492 } | |
2493 | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2494 void |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2495 gtk_imhtml_clear (GtkIMHtml *imhtml) |
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2496 { |
7991 | 2497 GList *del; |
3922 | 2498 GtkTextIter start, end; |
8427 | 2499 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
7991 | 2500 |
3922 | 2501 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
2502 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
2503 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | |
7991 | 2504 |
2505 for(del = imhtml->scalables; del; del = del->next) { | |
2506 GtkIMHtmlScalable *scale = del->data; | |
2507 scale->free(scale); | |
2508 } | |
2509 g_list_free(imhtml->scalables); | |
2510 imhtml->scalables = NULL; | |
8061 | 2511 |
8719 | 2512 gtk_imhtml_close_tags(imhtml, &start); |
8481 | 2513 |
8427 | 2514 g_signal_emit(object, signals[CLEAR_FORMAT], 0); |
2515 g_object_unref(object); | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2516 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
2517 |
4046 | 2518 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
2519 { | |
5282 | 2520 GdkRectangle rect; |
2521 GtkTextIter iter; | |
4046 | 2522 |
5282 | 2523 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
2524 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
2525 rect.y - rect.height); | |
2526 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
8061 | 2527 |
4046 | 2528 } |
5282 | 2529 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
2530 { | |
2531 GdkRectangle rect; | |
2532 GtkTextIter iter; | |
2533 | |
2534 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
2535 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
2536 rect.y + rect.height); | |
2537 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
2538 } | |
4735 | 2539 |
5967 | 2540 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
6982 | 2541 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) |
4735 | 2542 { |
5967 | 2543 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 2544 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 2545 |
5967 | 2546 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
2547 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
2548 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 2549 |
2550 im_image->pixbuf = img; | |
5012 | 2551 im_image->image = image; |
4895 | 2552 im_image->width = gdk_pixbuf_get_width(img); |
2553 im_image->height = gdk_pixbuf_get_height(img); | |
2554 im_image->mark = NULL; | |
6982 | 2555 im_image->filename = filename ? g_strdup(filename) : NULL; |
4895 | 2556 |
5046 | 2557 g_object_ref(img); |
4895 | 2558 return GTK_IMHTML_SCALABLE(im_image); |
2559 } | |
2560 | |
5967 | 2561 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 2562 { |
5967 | 2563 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 2564 |
2565 if(image->width > width || image->height > height){ | |
2566 GdkPixbuf *new_image = NULL; | |
2567 float factor; | |
2568 int new_width = image->width, new_height = image->height; | |
2569 | |
8588 | 2570 if(image->width > (width - 2)){ |
4895 | 2571 factor = (float)(width)/image->width; |
2572 new_width = width; | |
2573 new_height = image->height * factor; | |
2574 } | |
8588 | 2575 if(new_height >= (height - 2)){ |
4895 | 2576 factor = (float)(height)/new_height; |
2577 new_height = height; | |
2578 new_width = new_width * factor; | |
2579 } | |
2580 | |
5046 | 2581 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 2582 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 2583 g_object_unref(G_OBJECT(new_image)); |
2584 } | |
2585 } | |
2586 | |
5012 | 2587 static void write_img_to_file(GtkWidget *w, GtkFileSelection *sel) |
2588 { | |
2589 const gchar *filename = gtk_file_selection_get_filename(sel); | |
5967 | 2590 gchar *dirname; |
2591 GtkIMHtmlImage *image = g_object_get_data(G_OBJECT(sel), "GtkIMHtmlImage"); | |
5012 | 2592 gchar *type = NULL; |
5019 | 2593 GError *error = NULL; |
5015 | 2594 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 2595 GSList *formats = gdk_pixbuf_get_formats(); |
6162 | 2596 #else |
2597 char *basename = g_path_get_basename(filename); | |
2598 char *ext = strrchr(basename, '.'); | |
5959 | 2599 #endif |
5012 | 2600 |
5967 | 2601 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
2602 /* append a / if needed */ | |
2603 if (filename[strlen(filename) - 1] != '/') { | |
2604 dirname = g_strconcat(filename, "/", NULL); | |
2605 } else { | |
2606 dirname = g_strdup(filename); | |
2607 } | |
2608 gtk_file_selection_set_filename(sel, dirname); | |
2609 g_free(dirname); | |
5959 | 2610 return; |
5967 | 2611 } |
5959 | 2612 |
2613 #if GTK_CHECK_VERSION(2,2,0) | |
5012 | 2614 while(formats){ |
2615 GdkPixbufFormat *format = formats->data; | |
2616 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
2617 gpointer p = extensions; | |
2618 | |
2619 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
2620 gchar *fmt_ext = extensions[0]; | |
2621 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
2622 | |
2623 if(!strcmp(fmt_ext, file_ext)){ | |
2624 type = gdk_pixbuf_format_get_name(format); | |
2625 break; | |
2626 } | |
2627 | |
2628 extensions++; | |
2629 } | |
2630 | |
2631 g_strfreev(p); | |
2632 | |
2633 if(type) | |
2634 break; | |
2635 | |
2636 formats = formats->next; | |
2637 } | |
2638 | |
5020 | 2639 g_slist_free(formats); |
2640 #else | |
2641 /* this is really ugly code, but I think it will work */ | |
2642 if(ext) { | |
2643 ext++; | |
2644 if(!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) | |
2645 type = g_strdup("jpeg"); | |
2646 else if(!g_ascii_strcasecmp(ext, "png")) | |
2647 type = g_strdup("png"); | |
2648 } | |
2649 | |
2650 g_free(basename); | |
2651 #endif | |
2652 | |
5012 | 2653 /* If I can't find a valid type, I will just tell the user about it and then assume |
2654 it's a png */ | |
2655 if(!type){ | |
2656 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
5967 | 2657 _("Unable to guess the image type based on the file extension supplied. Defaulting to PNG.")); |
5012 | 2658 type = g_strdup("png"); |
2659 } | |
2660 | |
5046 | 2661 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 2662 |
2663 if(error){ | |
2664 gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, | |
2665 _("Error saving image: %s"), error->message); | |
2666 g_error_free(error); | |
2667 } | |
2668 | |
2669 g_free(type); | |
2670 } | |
2671 | |
5967 | 2672 static void gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) |
5012 | 2673 { |
5967 | 2674 GtkWidget *sel = gtk_file_selection_new(_("Save Image")); |
5012 | 2675 |
6982 | 2676 if (image->filename) |
2677 gtk_file_selection_set_filename(GTK_FILE_SELECTION(sel), image->filename); | |
5967 | 2678 g_object_set_data(G_OBJECT(sel), "GtkIMHtmlImage", image); |
5012 | 2679 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", |
2680 G_CALLBACK(write_img_to_file), sel); | |
2681 | |
2682 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->ok_button), "clicked", | |
2683 G_CALLBACK(gtk_widget_destroy), sel); | |
2684 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(sel)->cancel_button), "clicked", | |
8061 | 2685 G_CALLBACK(gtk_widget_destroy), sel); |
5012 | 2686 |
2687 gtk_widget_show(sel); | |
2688 } | |
2689 | |
5967 | 2690 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 2691 { |
2692 GdkEventButton *event_button = (GdkEventButton *) event; | |
2693 | |
2694 if (event->type == GDK_BUTTON_RELEASE) { | |
2695 if(event_button->button == 3) { | |
2696 GtkWidget *img, *item, *menu; | |
2697 gchar *text = g_strdup_printf(_("_Save Image...")); | |
2698 menu = gtk_menu_new(); | |
2699 | |
2700 /* buttons and such */ | |
2701 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
2702 item = gtk_image_menu_item_new_with_mnemonic(text); | |
2703 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 2704 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 2705 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
2706 | |
2707 gtk_widget_show_all(menu); | |
2708 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
2709 event_button->button, event_button->time); | |
2710 | |
2711 g_free(text); | |
2712 return TRUE; | |
2713 } | |
2714 } | |
2715 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
2716 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
2717 be caught by the regular GtkTextView menu */ | |
2718 else | |
2719 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
2720 | |
2721 } | |
5967 | 2722 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
2723 { | |
2724 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
2725 | |
2726 g_object_unref(image->pixbuf); | |
6982 | 2727 if (image->filename) |
2728 g_free(image->filename); | |
5967 | 2729 g_free(scale); |
2730 } | |
2731 | |
2732 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
2733 { | |
2734 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
2735 GtkWidget *box = gtk_event_box_new(); | |
2736 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
2737 | |
2738 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
2739 | |
2740 gtk_widget_show(GTK_WIDGET(image->image)); | |
2741 gtk_widget_show(box); | |
2742 | |
2743 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | |
2744 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
2745 } | |
2746 | |
2747 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
2748 { | |
2749 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
2750 | |
2751 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
2752 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
2753 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
2754 | |
2755 hr->sep = gtk_hseparator_new(); | |
2756 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
2757 gtk_widget_show(hr->sep); | |
2758 | |
2759 return GTK_IMHTML_SCALABLE(hr); | |
2760 } | |
2761 | |
2762 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
2763 { | |
8588 | 2764 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); |
5967 | 2765 } |
2766 | |
2767 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
2768 { | |
2769 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
2770 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
8698 | 2771 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); |
2772 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); | |
5967 | 2773 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
2774 } | |
2775 | |
2776 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
2777 { | |
2778 g_free(scale); | |
2779 } | |
7295 | 2780 |
2781 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | |
2782 { | |
2783 GtkTextIter iter, start, end; | |
2784 gboolean new_search = TRUE; | |
2785 | |
2786 g_return_val_if_fail(imhtml != NULL, FALSE); | |
2787 g_return_val_if_fail(text != NULL, FALSE); | |
8061 | 2788 |
7295 | 2789 if (imhtml->search_string && !strcmp(text, imhtml->search_string)) |
2790 new_search = FALSE; | |
8061 | 2791 |
7295 | 2792 if (new_search) { |
2793 gtk_imhtml_search_clear(imhtml); | |
2794 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
2795 } else { | |
2796 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, | |
8061 | 2797 gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); |
7295 | 2798 } |
2799 imhtml->search_string = g_strdup(text); | |
2800 | |
7358 | 2801 if (gtk_source_iter_forward_search(&iter, imhtml->search_string, |
2802 GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, | |
7295 | 2803 &start, &end, NULL)) { |
2804 | |
2805 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0); | |
2806 gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); | |
2807 if (new_search) { | |
2808 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); | |
8061 | 2809 do |
7295 | 2810 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); |
8061 | 2811 while (gtk_source_iter_forward_search(&end, imhtml->search_string, |
2812 GTK_SOURCE_SEARCH_VISIBLE_ONLY | | |
7358 | 2813 GTK_SOURCE_SEARCH_CASE_INSENSITIVE, |
7295 | 2814 &start, &end, NULL)); |
2815 } | |
2816 return TRUE; | |
2817 } | |
8061 | 2818 |
2819 gtk_imhtml_search_clear(imhtml); | |
2820 | |
7295 | 2821 return FALSE; |
2822 } | |
2823 | |
2824 void gtk_imhtml_search_clear(GtkIMHtml *imhtml) | |
2825 { | |
2826 GtkTextIter start, end; | |
8061 | 2827 |
7295 | 2828 g_return_if_fail(imhtml != NULL); |
8061 | 2829 |
7295 | 2830 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
2831 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
2832 | |
2833 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end); | |
2834 if (imhtml->search_string) | |
2835 g_free(imhtml->search_string); | |
2836 imhtml->search_string = NULL; | |
2837 } | |
8061 | 2838 |
8677 | 2839 static GtkTextTag *find_font_forecolor_tag(GtkIMHtml *imhtml, gchar *color) |
2840 { | |
2841 gchar str[18]; | |
2842 GtkTextTag *tag; | |
2843 | |
2844 g_snprintf(str, sizeof(str), "FORECOLOR %s", color); | |
2845 | |
2846 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2847 if (!tag) | |
2848 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", color, NULL); | |
2849 | |
2850 return tag; | |
2851 } | |
2852 | |
2853 static GtkTextTag *find_font_backcolor_tag(GtkIMHtml *imhtml, gchar *color) | |
2854 { | |
2855 gchar str[18]; | |
2856 GtkTextTag *tag; | |
2857 | |
2858 g_snprintf(str, sizeof(str), "BACKCOLOR %s", color); | |
2859 | |
2860 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2861 if (!tag) | |
2862 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "background", color, NULL); | |
2863 | |
2864 return tag; | |
2865 } | |
2866 | |
2867 static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) | |
8061 | 2868 { |
8677 | 2869 gchar str[256]; |
2870 GtkTextTag *tag; | |
2871 | |
2872 g_snprintf(str, sizeof(str), "FONT FACE %s", face); | |
2873 str[255] = '\0'; | |
2874 | |
2875 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2876 if (!tag) | |
2877 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "family", face, NULL); | |
2878 | |
2879 return tag; | |
2880 } | |
2881 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2882 static void _init_original_fsize(GtkIMHtml *imhtml) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2883 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2884 GtkTextAttributes *attr; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2885 attr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(imhtml)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2886 imhtml->original_fsize = pango_font_description_get_size(attr->font); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2887 gtk_text_attributes_unref(attr); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2888 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2889 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2890 static void _recalculate_font_sizes(GtkTextTag *tag, gpointer imhtml) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2891 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2892 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2893 int size; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2894 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2895 size = strtol(tag->name + 10, NULL, 10); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2896 g_object_set(G_OBJECT(tag), "size", |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2897 (gint) (GTK_IMHTML(imhtml)->original_fsize * |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2898 ((double) _point_sizes[size-1] * GTK_IMHTML(imhtml)->zoom)), NULL); |
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 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2904 void gtk_imhtml_font_zoom(GtkIMHtml *imhtml, double zoom) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2905 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2906 GtkRcStyle *s; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2907 PangoFontDescription *font_desc = pango_font_description_new(); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2908 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2909 imhtml->zoom = zoom; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2910 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2911 if (!imhtml->original_fsize) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2912 _init_original_fsize(imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2913 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2914 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
|
2915 _recalculate_font_sizes, imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2916 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2917 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
|
2918 |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2919 s = gtk_widget_get_modifier_style(GTK_WIDGET(imhtml)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2920 s->font_desc = font_desc; |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2921 gtk_widget_modify_style(GTK_WIDGET(imhtml), s); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2922 } |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2923 |
8677 | 2924 static GtkTextTag *find_font_size_tag(GtkIMHtml *imhtml, int size) |
2925 { | |
2926 gchar str[24]; | |
2927 GtkTextTag *tag; | |
2928 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2929 if (!imhtml->original_fsize) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2930 _init_original_fsize(imhtml); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2931 |
8677 | 2932 g_snprintf(str, sizeof(str), "FONT SIZE %d", size); |
2933 str[23] = '\0'; | |
2934 | |
2935 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2936 if (!tag) { | |
2937 /* For reasons I don't understand, setting "scale" here scaled based on some default | |
2938 * size other than my theme's default size. Our size 4 was actually smaller than | |
2939 * our size 3 for me. So this works around that oddity. | |
2940 */ | |
2941 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
|
2942 (gint) (imhtml->original_fsize * |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
2943 ((double) _point_sizes[size-1] * imhtml->zoom)), NULL); |
8061 | 2944 } |
2945 | |
8677 | 2946 return tag; |
2947 } | |
2948 | |
2949 static void remove_tag_by_prefix(GtkIMHtml *imhtml, const GtkTextIter *i, const GtkTextIter *e, | |
2950 const char *prefix, guint len, gboolean homo) | |
2951 { | |
2952 GSList *tags, *l; | |
2953 GtkTextIter iter; | |
2954 | |
2955 tags = gtk_text_iter_get_tags(i); | |
2956 | |
2957 for (l = tags; l; l = l->next) { | |
2958 GtkTextTag *tag = l->data; | |
2959 | |
2960 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2961 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); | |
8061 | 2962 } |
2963 | |
8677 | 2964 g_slist_free(tags); |
2965 | |
2966 if (homo) | |
2967 return; | |
2968 | |
2969 iter = *i; | |
2970 | |
2971 while (gtk_text_iter_forward_char(&iter) && !gtk_text_iter_equal(&iter, e)) { | |
2972 if (gtk_text_iter_begins_tag(&iter, NULL)) { | |
2973 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); | |
2974 | |
2975 for (l = tags; l; l = l->next) { | |
2976 GtkTextTag *tag = l->data; | |
2977 | |
2978 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2979 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); | |
2980 } | |
2981 | |
2982 g_slist_free(tags); | |
2983 } | |
8061 | 2984 } |
8677 | 2985 } |
2986 | |
2987 static void remove_font_size(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2988 { | |
2989 remove_tag_by_prefix(imhtml, i, e, "FONT SIZE ", 10, homo); | |
2990 } | |
2991 | |
2992 static void remove_font_face(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2993 { | |
2994 remove_tag_by_prefix(imhtml, i, e, "FONT FACE ", 10, homo); | |
2995 } | |
2996 | |
2997 static void remove_font_forecolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2998 { | |
2999 remove_tag_by_prefix(imhtml, i, e, "FORECOLOR ", 10, homo); | |
3000 } | |
3001 | |
3002 static void remove_font_backcolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3003 { | |
3004 remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); | |
3005 } | |
3006 | |
3007 static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3008 { | |
3009 remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); | |
3010 } | |
3011 | |
3012 /* Editable stuff */ | |
3013 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | |
3014 { | |
3015 imhtml->insert_offset = gtk_text_iter_get_offset(iter); | |
3016 } | |
3017 | |
3018 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) | |
3019 { | |
3020 GtkTextIter start; | |
3021 | |
3022 if (!len) | |
3023 return; | |
3024 | |
3025 start = *end; | |
3026 gtk_text_iter_set_offset(&start, imhtml->insert_offset); | |
3027 | |
3028 if (imhtml->edit.bold) | |
3029 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); | |
3030 else | |
3031 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); | |
3032 | |
3033 if (imhtml->edit.italic) | |
3034 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); | |
3035 else | |
3036 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); | |
3037 | |
3038 if (imhtml->edit.underline) | |
3039 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); | |
3040 else | |
3041 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); | |
3042 | |
3043 if (imhtml->edit.forecolor) { | |
3044 remove_font_forecolor(imhtml, &start, end, TRUE); | |
3045 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3046 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
3047 &start, end); | |
8061 | 3048 } |
3049 | |
8677 | 3050 if (imhtml->edit.backcolor) { |
3051 remove_font_backcolor(imhtml, &start, end, TRUE); | |
3052 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3053 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), | |
3054 &start, end); | |
3055 } | |
3056 | |
3057 if (imhtml->edit.fontface) { | |
3058 remove_font_face(imhtml, &start, end, TRUE); | |
3059 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3060 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
3061 &start, end); | |
8061 | 3062 } |
8677 | 3063 |
3064 if (imhtml->edit.fontsize) { | |
3065 remove_font_size(imhtml, &start, end, TRUE); | |
3066 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3067 find_font_size_tag(imhtml, imhtml->edit.fontsize), | |
3068 &start, end); | |
3069 } | |
3070 | |
3071 if (imhtml->edit.link) { | |
3072 remove_font_link(imhtml, &start, end, TRUE); | |
3073 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3074 imhtml->edit.link, | |
3075 &start, end); | |
3076 } | |
3077 | |
8061 | 3078 } |
3079 | |
3080 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | |
3081 { | |
3082 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | |
8177 | 3083 /* |
3084 * We need a visible caret for accessibility, so mouseless | |
3085 * people can highlight stuff. | |
3086 */ | |
3087 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | |
8061 | 3088 imhtml->editable = editable; |
8677 | 3089 imhtml->format_functions = GTK_IMHTML_ALL; |
3090 | |
3091 if (editable) | |
3092 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
3093 G_CALLBACK(mark_set_cb), imhtml); | |
3094 } | |
3095 | |
3096 void gtk_imhtml_set_whole_buffer_formatting_only(GtkIMHtml *imhtml, gboolean wbfo) | |
3097 { | |
3098 g_return_if_fail(imhtml != NULL); | |
3099 | |
3100 imhtml->wbfo = wbfo; | |
8420 | 3101 } |
3102 | |
3103 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | |
3104 { | |
3105 GObject *object = g_object_ref(G_OBJECT(imhtml)); | |
8677 | 3106 imhtml->format_functions = buttons; |
8420 | 3107 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); |
3108 g_object_unref(object); | |
8061 | 3109 } |
3110 | |
8788 | 3111 GtkIMHtmlButtons gtk_imhtml_get_format_functions(GtkIMHtml *imhtml) |
3112 { | |
3113 return imhtml->format_functions; | |
3114 } | |
8516 | 3115 |
3116 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, | |
3117 gboolean *italic, gboolean *underline) | |
8481 | 3118 { |
8677 | 3119 if (imhtml->edit.bold) |
3120 (*bold) = TRUE; | |
3121 if (imhtml->edit.italic) | |
3122 (*italic) = TRUE; | |
3123 if (imhtml->edit.underline) | |
3124 (*underline) = TRUE; | |
8481 | 3125 } |
3126 | |
8061 | 3127 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) |
3128 { | |
3129 return imhtml->editable; | |
3130 } | |
3131 | |
8677 | 3132 /* |
3133 * I had this crazy idea about changing the text cursor color to reflex the foreground color | |
3134 * of the text about to be entered. This is the place you'd do it, along with the place where | |
3135 * we actually set a new foreground color. | |
3136 * I may not do this, because people will bitch about Gaim overriding their gtk theme's cursor | |
3137 * colors. | |
3138 * | |
3139 * Just in case I do do this, I asked about what to set the secondary text cursor to. | |
3140 * | |
8719 | 3141 * (12:45:27) ?? ???: secondary_cursor_color = (rgb(background) + rgb(primary_cursor_color) ) / 2 |
3142 * (12:45:55) ?? ???: understand? | |
8677 | 3143 * (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
|
3144 * (12:46:56) ?? ???: u might need to extract separate each color from RGB |
8677 | 3145 */ |
3146 | |
3147 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, | |
3148 GtkIMHtml *imhtml) | |
3149 { | |
3150 GSList *tags, *l; | |
3151 GtkTextIter iter; | |
3152 | |
3153 if (mark != gtk_text_buffer_get_insert(buffer)) | |
3154 return; | |
3155 | |
3156 if (!gtk_text_buffer_get_char_count(buffer)) | |
3157 return; | |
3158 | |
3159 imhtml->edit.bold = imhtml->edit.italic = imhtml->edit.underline = FALSE; | |
3160 if (imhtml->edit.forecolor) | |
3161 g_free(imhtml->edit.forecolor); | |
3162 imhtml->edit.forecolor = NULL; | |
3163 if (imhtml->edit.backcolor) | |
3164 g_free(imhtml->edit.backcolor); | |
3165 imhtml->edit.backcolor = NULL; | |
3166 if (imhtml->edit.fontface) | |
3167 g_free(imhtml->edit.fontface); | |
3168 imhtml->edit.fontface = NULL; | |
3169 imhtml->edit.fontsize = 0; | |
3170 imhtml->edit.link = NULL; | |
3171 | |
3172 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3173 | |
3174 | |
3175 if (gtk_text_iter_is_end(&iter)) | |
3176 tags = gtk_text_iter_get_toggled_tags(&iter, FALSE); | |
3177 else | |
3178 tags = gtk_text_iter_get_tags(&iter); | |
3179 | |
3180 for (l = tags; l != NULL; l = l->next) { | |
3181 GtkTextTag *tag = GTK_TEXT_TAG(l->data); | |
3182 | |
3183 if (tag->name) { | |
3184 if (strcmp(tag->name, "BOLD") == 0) | |
3185 imhtml->edit.bold = TRUE; | |
3186 if (strcmp(tag->name, "ITALICS") == 0) | |
3187 imhtml->edit.italic = TRUE; | |
3188 if (strcmp(tag->name, "UNDERLINE") == 0) | |
3189 imhtml->edit.underline = TRUE; | |
3190 if (strncmp(tag->name, "FORECOLOR ", 10) == 0) | |
3191 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); | |
3192 if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) | |
3193 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); | |
3194 if (strncmp(tag->name, "FONT FACE ", 10) == 0) | |
3195 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); | |
3196 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) | |
3197 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); | |
8719 | 3198 if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) |
8677 | 3199 imhtml->edit.link = tag; |
3200 } | |
3201 } | |
3202 | |
3203 g_slist_free(tags); | |
3204 } | |
3205 | |
8061 | 3206 gboolean gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) |
3207 { | |
8481 | 3208 GObject *object; |
8677 | 3209 GtkTextIter start, end; |
3210 | |
3211 imhtml->edit.bold = !imhtml->edit.bold; | |
3212 | |
3213 if (imhtml->wbfo) { | |
3214 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3215 if (imhtml->edit.bold) | |
3216 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3217 else | |
3218 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3219 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3220 if (imhtml->edit.bold) | |
3221 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3222 else | |
3223 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3224 | |
8061 | 3225 } |
8481 | 3226 object = g_object_ref(G_OBJECT(imhtml)); |
3227 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); | |
3228 g_object_unref(object); | |
3229 | |
8677 | 3230 return (imhtml->edit.bold != FALSE); |
8061 | 3231 } |
3232 | |
3233 gboolean gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) | |
3234 { | |
8481 | 3235 GObject *object; |
8677 | 3236 GtkTextIter start, end; |
3237 | |
3238 imhtml->edit.italic = !imhtml->edit.italic; | |
3239 | |
3240 if (imhtml->wbfo) { | |
3241 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3242 if (imhtml->edit.italic) | |
3243 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3244 else | |
3245 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3246 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3247 if (imhtml->edit.italic) | |
3248 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
3249 else | |
3250 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
8061 | 3251 } |
8481 | 3252 object = g_object_ref(G_OBJECT(imhtml)); |
3253 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); | |
3254 g_object_unref(object); | |
3255 | |
8677 | 3256 return imhtml->edit.italic != FALSE; |
8061 | 3257 } |
3258 | |
3259 gboolean gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) | |
3260 { | |
8481 | 3261 GObject *object; |
8677 | 3262 GtkTextIter start, end; |
3263 | |
3264 imhtml->edit.underline = !imhtml->edit.underline; | |
3265 | |
3266 if (imhtml->wbfo) { | |
3267 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3268 if (imhtml->edit.underline) | |
3269 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3270 else | |
3271 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3272 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3273 if (imhtml->edit.underline) | |
3274 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
3275 else | |
3276 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
8061 | 3277 } |
8481 | 3278 object = g_object_ref(G_OBJECT(imhtml)); |
3279 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); | |
3280 g_object_unref(object); | |
3281 | |
8677 | 3282 return imhtml->edit.underline != FALSE; |
8061 | 3283 } |
3284 | |
3285 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) | |
3286 { | |
8677 | 3287 GtkTextIter start, end; |
8061 | 3288 |
3289 imhtml->edit.fontsize = size; | |
3290 | |
8677 | 3291 |
3292 if (imhtml->wbfo) { | |
3293 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3294 remove_font_size(imhtml, &start, &end, TRUE); | |
3295 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3296 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3297 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3298 remove_font_size(imhtml, &start, &end, FALSE); | |
3299 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3300 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3301 } |
8677 | 3302 |
8061 | 3303 } |
3304 | |
3305 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) | |
3306 { | |
8677 | 3307 GtkTextIter start, end; |
3308 | |
8061 | 3309 if (imhtml->edit.fontsize == 1) |
3310 return; | |
3311 | |
8677 | 3312 if (!imhtml->edit.fontsize) |
3313 imhtml->edit.fontsize = 2; | |
3314 else | |
3315 imhtml->edit.fontsize--; | |
3316 | |
3317 if (imhtml->wbfo) { | |
3318 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3319 remove_font_size(imhtml, &start, &end, TRUE); | |
3320 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3321 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3322 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3323 remove_font_size(imhtml, &start, &end, FALSE); | |
3324 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3325 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3326 } |
3327 } | |
3328 | |
3329 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) | |
3330 { | |
8677 | 3331 GtkTextIter start, end; |
3332 | |
8061 | 3333 if (imhtml->edit.fontsize == MAX_FONT_SIZE) |
3334 return; | |
3335 | |
8677 | 3336 if (!imhtml->edit.fontsize) |
3337 imhtml->edit.fontsize = 4; | |
3338 else | |
3339 imhtml->edit.fontsize++; | |
3340 | |
3341 if (imhtml->wbfo) { | |
3342 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3343 remove_font_size(imhtml, &start, &end, TRUE); | |
3344 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3345 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
3346 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3347 remove_font_size(imhtml, &start, &end, FALSE); | |
3348 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3349 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 3350 } |
3351 } | |
3352 | |
3353 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) | |
3354 { | |
8677 | 3355 GtkTextIter start, end; |
3356 | |
3357 if (imhtml->edit.forecolor != NULL) | |
3358 g_free(imhtml->edit.forecolor); | |
3359 | |
8429 | 3360 if (color) { |
8677 | 3361 imhtml->edit.forecolor = g_strdup(color); |
3362 if (imhtml->wbfo) { | |
3363 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3364 remove_font_forecolor(imhtml, &start, &end, TRUE); | |
3365 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3366 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), &start, &end); | |
3367 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3368 remove_font_forecolor(imhtml, &start, &end, FALSE); | |
3369 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3370 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
3371 &start, &end); | |
3372 } | |
8061 | 3373 } else { |
3374 imhtml->edit.forecolor = NULL; | |
3375 } | |
3376 | |
3377 return imhtml->edit.forecolor != NULL; | |
3378 } | |
3379 | |
3380 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
3381 { | |
8677 | 3382 GtkTextIter start, end; |
3383 | |
3384 if (imhtml->edit.backcolor != NULL) | |
3385 g_free(imhtml->edit.backcolor); | |
3386 | |
8429 | 3387 if (color) { |
8677 | 3388 imhtml->edit.backcolor = g_strdup(color); |
3389 | |
3390 if (imhtml->wbfo) { | |
3391 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3392 remove_font_backcolor(imhtml, &start, &end, TRUE); | |
3393 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3394 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), &start, &end); | |
3395 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3396 remove_font_backcolor(imhtml, &start, &end, FALSE); | |
3397 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3398 find_font_backcolor_tag(imhtml, | |
3399 imhtml->edit.backcolor), &start, &end); | |
3400 } | |
8061 | 3401 } else { |
3402 imhtml->edit.backcolor = NULL; | |
3403 } | |
8677 | 3404 |
8061 | 3405 return imhtml->edit.backcolor != NULL; |
3406 } | |
3407 | |
3408 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
3409 { | |
8677 | 3410 GtkTextIter start, end; |
3411 | |
3412 if (imhtml->edit.fontface != NULL) | |
3413 g_free(imhtml->edit.fontface); | |
3414 | |
8429 | 3415 if (face) { |
8677 | 3416 imhtml->edit.fontface = g_strdup(face); |
3417 | |
3418 if (imhtml->wbfo) { | |
3419 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3420 remove_font_face(imhtml, &start, &end, TRUE); | |
3421 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3422 find_font_face_tag(imhtml, imhtml->edit.fontface), &start, &end); | |
3423 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3424 remove_font_face(imhtml, &start, &end, FALSE); | |
3425 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3426 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
3427 &start, &end); | |
3428 } | |
8061 | 3429 } else { |
3430 imhtml->edit.fontface = NULL; | |
3431 } | |
8677 | 3432 |
8061 | 3433 return imhtml->edit.fontface != NULL; |
3434 } | |
3435 | |
8677 | 3436 void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) |
8061 | 3437 { |
8677 | 3438 GtkTextIter start, end; |
3439 GtkTextTag *linktag; | |
3440 static guint linkno = 0; | |
3441 gchar str[48]; | |
3442 | |
3443 imhtml->edit.link = NULL; | |
3444 | |
3445 | |
3446 | |
3447 if (url) { | |
3448 g_snprintf(str, sizeof(str), "LINK %d", linkno++); | |
3449 str[47] = '\0'; | |
3450 | |
3451 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
3452 g_object_set_data_full(G_OBJECT(linktag), "link_url", g_strdup(url), g_free); | |
3453 g_signal_connect(G_OBJECT(linktag), "event", G_CALLBACK(tag_event), NULL); | |
3454 | |
3455 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3456 remove_font_link(imhtml, &start, &end, FALSE); | |
3457 gtk_text_buffer_apply_tag(imhtml->text_buffer, linktag, &start, &end); | |
3458 } | |
3459 } | |
3460 } | |
3461 | |
3462 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, GtkTextMark *mark, const char *url, const char *text) | |
3463 { | |
8061 | 3464 GtkTextIter iter; |
8677 | 3465 |
3466 gtk_imhtml_toggle_link(imhtml, url); | |
8061 | 3467 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
8677 | 3468 gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); |
3469 gtk_imhtml_toggle_link(imhtml, NULL); | |
8061 | 3470 } |
3471 | |
3472 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
3473 { | |
8677 | 3474 GtkTextMark *mark; |
8061 | 3475 GtkTextIter iter; |
8677 | 3476 |
3477 mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
3478 | |
3479 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3480 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); | |
3481 } | |
3482 | |
3483 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) | |
3484 { | |
8061 | 3485 GdkPixbuf *pixbuf = NULL; |
3486 GdkPixbufAnimation *annipixbuf = NULL; | |
3487 GtkWidget *icon = NULL; | |
3488 GtkTextChildAnchor *anchor; | |
8505 | 3489 char *unescaped = gaim_unescape_html(smiley); |
8061 | 3490 |
8505 | 3491 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); |
8061 | 3492 if(annipixbuf) { |
3493 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
3494 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); | |
3495 if(pixbuf) | |
3496 icon = gtk_image_new_from_pixbuf(pixbuf); | |
3497 } else { | |
3498 icon = gtk_image_new_from_animation(annipixbuf); | |
3499 } | |
3500 } | |
3501 | |
3502 if (icon) { | |
8890 | 3503 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
3504 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); | |
3505 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); | |
3506 | |
8061 | 3507 gtk_widget_show(icon); |
3508 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | |
8890 | 3509 } else { |
3510 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); | |
8061 | 3511 } |
8890 | 3512 |
3513 g_free(unescaped); | |
8061 | 3514 } |
3515 | |
8677 | 3516 static const gchar *tag_to_html_start(GtkTextTag *tag) |
8061 | 3517 { |
8677 | 3518 const gchar *name; |
3519 static gchar buf[1024]; | |
3520 | |
3521 name = tag->name; | |
3522 g_return_val_if_fail(name != NULL, ""); | |
3523 | |
3524 if (strcmp(name, "BOLD") == 0) { | |
3525 return "<b>"; | |
3526 } else if (strcmp(name, "ITALICS") == 0) { | |
3527 return "<i>"; | |
3528 } else if (strcmp(name, "UNDERLINE") == 0) { | |
3529 return "<u>"; | |
3530 } else if (strncmp(name, "LINK ", 5) == 0) { | |
3531 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); | |
3532 if (tmp) { | |
3533 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); | |
3534 buf[sizeof(buf)-1] = '\0'; | |
3535 return buf; | |
3536 } else { | |
3537 return ""; | |
3538 } | |
3539 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3540 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); | |
3541 return buf; | |
3542 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3543 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); | |
3544 return buf; | |
3545 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3546 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); | |
3547 return buf; | |
3548 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3549 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); | |
3550 return buf; | |
3551 } else { | |
3552 return ""; | |
3553 } | |
8061 | 3554 } |
3555 | |
8677 | 3556 static const gchar *tag_to_html_end(GtkTextTag *tag) |
8061 | 3557 { |
8677 | 3558 const gchar *name; |
3559 | |
3560 name = tag->name; | |
3561 g_return_val_if_fail(name != NULL, ""); | |
3562 | |
3563 if (strcmp(name, "BOLD") == 0) { | |
3564 return "</b>"; | |
3565 } else if (strcmp(name, "ITALICS") == 0) { | |
3566 return "</i>"; | |
3567 } else if (strcmp(name, "UNDERLINE") == 0) { | |
3568 return "</u>"; | |
3569 } else if (strncmp(name, "LINK ", 5) == 0) { | |
3570 return "</a>"; | |
3571 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3572 return "</font>"; | |
3573 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3574 return "</font>"; | |
3575 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3576 return "</font>"; | |
3577 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3578 return "</font>"; | |
3579 } else { | |
3580 return ""; | |
3581 } | |
3582 } | |
3583 | |
3584 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) | |
3585 { | |
3586 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && | |
3587 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || | |
3588 gtk_text_iter_is_end(niter)); | |
8061 | 3589 } |
3590 | |
3591 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | |
3592 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | |
8677 | 3593 * check for tags that are toggled on, insert their html form, and push them on the queue. Then insert |
3594 * 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
|
3595 * Finally, replace <, >, &, and " with their HTML equivalent. |
8677 | 3596 */ |
8061 | 3597 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
3598 { | |
3599 gunichar c; | |
8677 | 3600 GtkTextIter iter, nextiter; |
8061 | 3601 GString *str = g_string_new(""); |
8677 | 3602 GSList *tags, *sl; |
3603 GQueue *q, *r; | |
3604 GtkTextTag *tag; | |
3605 | |
3606 q = g_queue_new(); | |
3607 r = g_queue_new(); | |
3608 | |
8061 | 3609 |
3610 gtk_text_iter_order(start, end); | |
8677 | 3611 nextiter = iter = *start; |
3612 gtk_text_iter_forward_char(&nextiter); | |
3613 | |
3614 /* First add the tags that are already in progress */ | |
3615 tags = gtk_text_iter_get_tags(start); | |
3616 | |
3617 for (sl = tags; sl; sl = sl->next) { | |
3618 tag = sl->data; | |
3619 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { | |
3620 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); | |
3621 g_queue_push_tail(q, tag); | |
8061 | 3622 } |
3623 } | |
8677 | 3624 g_slist_free(tags); |
8061 | 3625 |
3626 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
8677 | 3627 |
3628 tags = gtk_text_iter_get_tags(&iter); | |
3629 | |
3630 for (sl = tags; sl; sl = sl->next) { | |
3631 tag = sl->data; | |
3632 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { | |
3633 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); | |
3634 g_queue_push_tail(q, tag); | |
3635 } | |
3636 } | |
3637 | |
3638 | |
8061 | 3639 if (c == 0xFFFC) { |
3640 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | |
8698 | 3641 char *text = NULL; |
3642 if (anchor) | |
3643 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext"); | |
3644 if (text) | |
3645 str = g_string_append(str, text); | |
8677 | 3646 } else if (c == '<') { |
3647 str = g_string_append(str, "<"); | |
3648 } else if (c == '>') { | |
3649 str = g_string_append(str, ">"); | |
3650 } else if (c == '&') { | |
3651 str = g_string_append(str, "&"); | |
3652 } else if (c == '"') { | |
3653 str = g_string_append(str, """); | |
3654 } else if (c == '\n') { | |
3655 str = g_string_append(str, "<br>"); | |
8061 | 3656 } else { |
8677 | 3657 str = g_string_append_unichar(str, c); |
3658 } | |
3659 | |
3660 tags = g_slist_reverse(tags); | |
3661 for (sl = tags; sl; sl = sl->next) { | |
3662 tag = sl->data; | |
3663 if (tag_ends_here(tag, &iter, &nextiter)) { | |
3664 | |
3665 GtkTextTag *tmp; | |
3666 | |
3667 while ((tmp = g_queue_pop_tail(q)) != tag) { | |
3668 if (tmp == NULL) | |
3669 break; | |
3670 | |
3671 if (!tag_ends_here(tmp, &iter, &nextiter)) | |
3672 g_queue_push_tail(r, tmp); | |
3673 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); | |
3674 } | |
3675 | |
3676 if (tmp == NULL) | |
3677 gaim_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); | |
3678 else | |
3679 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
3680 | |
3681 while ((tmp = g_queue_pop_head(r))) { | |
3682 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); | |
3683 g_queue_push_tail(q, tmp); | |
8061 | 3684 } |
3685 } | |
3686 } | |
8677 | 3687 |
3688 g_slist_free(tags); | |
8061 | 3689 gtk_text_iter_forward_char(&iter); |
8677 | 3690 gtk_text_iter_forward_char(&nextiter); |
8061 | 3691 } |
8677 | 3692 |
3693 while ((tag = g_queue_pop_tail(q))) | |
3694 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
3695 | |
3696 g_queue_free(q); | |
3697 g_queue_free(r); | |
8061 | 3698 return g_string_free(str, FALSE); |
3699 } | |
3700 | |
8698 | 3701 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter) |
8061 | 3702 { |
3703 if (imhtml->edit.bold) | |
3704 gtk_imhtml_toggle_bold(imhtml); | |
3705 | |
3706 if (imhtml->edit.italic) | |
3707 gtk_imhtml_toggle_italic(imhtml); | |
3708 | |
3709 if (imhtml->edit.underline) | |
3710 gtk_imhtml_toggle_underline(imhtml); | |
3711 | |
3712 if (imhtml->edit.forecolor) | |
3713 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
3714 | |
3715 if (imhtml->edit.backcolor) | |
3716 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
3717 | |
3718 if (imhtml->edit.fontface) | |
3719 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
3720 | |
8677 | 3721 imhtml->edit.fontsize = 0; |
3722 | |
8719 | 3723 if (imhtml->edit.link) |
3724 gtk_imhtml_toggle_link(imhtml, NULL); | |
3725 | |
8698 | 3726 gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter); |
8061 | 3727 |
3728 } | |
3729 | |
3730 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
3731 { | |
3732 GtkTextIter start, end; | |
3733 | |
3734 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
3735 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3736 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
3737 } | |
3738 | |
8677 | 3739 char **gtk_imhtml_get_markup_lines(GtkIMHtml *imhtml) |
3740 { | |
3741 int i, j, lines; | |
3742 GtkTextIter start, end; | |
3743 char **ret; | |
3744 | |
3745 lines = gtk_text_buffer_get_line_count(imhtml->text_buffer); | |
3746 ret = g_new0(char *, lines + 1); | |
3747 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
3748 end = start; | |
3749 gtk_text_iter_forward_to_line_end(&end); | |
3750 | |
3751 for (i = 0, j = 0; i < lines; i++) { | |
3752 ret[j] = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
3753 if (ret[j] != NULL) | |
3754 j++; | |
3755 gtk_text_iter_forward_line(&start); | |
3756 end = start; | |
3757 gtk_text_iter_forward_to_line_end(&end); | |
3758 } | |
3759 | |
3760 return ret; | |
3761 } | |
3762 | |
3763 char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop) | |
8061 | 3764 { |
8519 | 3765 GString *str = g_string_new(""); |
3766 GtkTextIter iter, end; | |
3767 gunichar c; | |
3768 | |
8677 | 3769 if (start == NULL) |
3770 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
3771 else | |
3772 iter = *start; | |
3773 | |
3774 if (stop == NULL) | |
3775 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3776 else | |
3777 end = *stop; | |
3778 | |
3779 gtk_text_iter_order(&iter, &end); | |
8519 | 3780 |
3781 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { | |
3782 if (c == 0xFFFC) { | |
8677 | 3783 GtkTextChildAnchor* anchor; |
3784 char *text = NULL; | |
3785 | |
3786 anchor = gtk_text_iter_get_child_anchor(&iter); | |
3787 if (anchor) | |
8698 | 3788 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_plaintext"); |
8677 | 3789 if (text) |
3790 str = g_string_append(str, text); | |
8519 | 3791 } else { |
3792 g_string_append_unichar(str, c); | |
3793 } | |
3794 gtk_text_iter_forward_char(&iter); | |
3795 } | |
3796 | |
3797 return g_string_free(str, FALSE); | |
8061 | 3798 } |