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