Mercurial > pidgin.yaz
annotate src/gtkimhtml.c @ 11485:16b0da1f376f
[gaim-migrate @ 13727]
Fix the /nick weirdness bug I introduced.
Also, patch 1283539, from Peter Lawler (two changes)
1. When in a chat where Gaim can tell which users are buddies (i.e. non-Jabber chats), only the names of buddies are bolded. I'm not sure if I'll like this, but I'm committing it so we can all try it out.
2. "remove bold, underline, and italics when we're ignoring formatting, as well"
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Fri, 09 Sep 2005 20:14:32 +0000 |
parents | 78cd70f4834c |
children | b47708f46a38 |
rev | line source |
---|---|
1428 | 1 /* |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10243
diff
changeset
|
2 * @file gtkimhtml.c GTK+ IMHtml |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10243
diff
changeset
|
3 * @ingroup gtkui |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10243
diff
changeset
|
4 * |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10243
diff
changeset
|
5 * gaim |
1428 | 6 * |
8046 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
1428 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 * | |
25 */ | |
26 | |
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
27 #ifdef HAVE_CONFIG_H |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
28 #include <config.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
29 #endif |
8526 | 30 #include "debug.h" |
8091 | 31 #include "util.h" |
1428 | 32 #include "gtkimhtml.h" |
7358 | 33 #include "gtksourceiter.h" |
1428 | 34 #include <gtk/gtk.h> |
4895 | 35 #include <glib/gerror.h> |
4046 | 36 #include <gdk/gdkkeysyms.h> |
1428 | 37 #include <string.h> |
38 #include <ctype.h> | |
39 #include <stdio.h> | |
4629 | 40 #include <stdlib.h> |
1428 | 41 #include <math.h> |
2541
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
42 #ifdef HAVE_LANGINFO_CODESET |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
43 #include <langinfo.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
44 #include <locale.h> |
8229710b343b
[gaim-migrate @ 2554]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2365
diff
changeset
|
45 #endif |
8692 | 46 #ifdef _WIN32 |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
47 #include <gdk/gdkwin32.h> |
8692 | 48 #include <windows.h> |
49 #endif | |
1428 | 50 |
4417 | 51 #ifdef ENABLE_NLS |
52 # include <libintl.h> | |
53 # define _(x) gettext(x) | |
54 # ifdef gettext_noop | |
55 # define N_(String) gettext_noop (String) | |
56 # else | |
57 # define N_(String) (String) | |
58 # endif | |
59 #else | |
60 # define N_(String) (String) | |
61 # define _(x) (x) | |
62 #endif | |
63 | |
4735 | 64 #include <pango/pango-font.h> |
65 | |
10062 | 66 /* GTK+ < 2.4.x hack, see gtkgaim.h for details. */ |
67 #if (!GTK_CHECK_VERSION(2,4,0)) | |
5105 | 68 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD |
69 #endif | |
70 | |
4735 | 71 #define TOOLTIP_TIMEOUT 500 |
72 | |
8786 | 73 /* GTK+ 2.0 hack */ |
74 #if (!GTK_CHECK_VERSION(2,2,0)) | |
75 #define gtk_widget_get_clipboard(x, y) gtk_clipboard_get(y) | |
76 #endif | |
77 | |
10100 | 78 static GtkTextViewClass *parent_class = NULL; |
79 | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
80 struct scalable_data { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
81 GtkIMHtmlScalable *scalable; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
82 GtkTextMark *mark; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
83 }; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
84 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
85 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
86 struct im_image_data { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
87 int id; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
88 GtkTextMark *mark; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
89 }; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
90 |
9300 | 91 static gboolean |
92 gtk_text_view_drag_motion (GtkWidget *widget, | |
93 GdkDragContext *context, | |
94 gint x, | |
95 gint y, | |
96 guint time); | |
97 | |
8677 | 98 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
8061 | 99 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
10169 | 100 static void insert_ca_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextChildAnchor *arg2, gpointer user_data); |
101 static void gtk_imhtml_apply_tags_on_insert(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end); | |
8505 | 102 static gboolean gtk_imhtml_is_amp_escape (const gchar *string, gchar **replace, gint *length); |
8698 | 103 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter); |
9300 | 104 static void gtk_imhtml_link_drop_cb(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data); |
8091 | 105 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 | 106 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml); |
8931 | 107 static void hijack_menu_cb(GtkIMHtml *imhtml, GtkMenu *menu, gpointer data); |
108 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data); | |
109 static void paste_plaintext_received_cb (GtkClipboard *clipboard, const gchar *text, gpointer data); | |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
110 static void imhtml_paste_insert(GtkIMHtml *imhtml, const char *text, gboolean plaintext); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
111 static void imhtml_toggle_bold(GtkIMHtml *imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
112 static void imhtml_toggle_italic(GtkIMHtml *imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
113 static void imhtml_toggle_strike(GtkIMHtml *imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
114 static void imhtml_toggle_underline(GtkIMHtml *imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
115 static void imhtml_font_grow(GtkIMHtml *imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
116 static void imhtml_font_shrink(GtkIMHtml *imhtml); |
8061 | 117 |
10899 | 118 /* POINT_SIZE converts from AIM font sizes to a point size scale factor. */ |
3922 | 119 #define MAX_FONT_SIZE 7 |
10900 | 120 #define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1]) |
8380 | 121 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
|
122 |
10184 | 123 enum { |
8677 | 124 TARGET_HTML, |
8061 | 125 TARGET_UTF8_STRING, |
126 TARGET_COMPOUND_TEXT, | |
127 TARGET_STRING, | |
128 TARGET_TEXT | |
129 }; | |
130 | |
8091 | 131 enum { |
8420 | 132 URL_CLICKED, |
133 BUTTONS_UPDATE, | |
134 TOGGLE_FORMAT, | |
8427 | 135 CLEAR_FORMAT, |
8506 | 136 UPDATE_FORMAT, |
10108 | 137 MESSAGE_SEND, |
8420 | 138 LAST_SIGNAL |
139 }; | |
140 static guint signals [LAST_SIGNAL] = { 0 }; | |
141 | |
10871 | 142 static GtkTargetEntry selection_targets[] = { |
8566 | 143 { "text/html", 0, TARGET_HTML }, |
8061 | 144 { "UTF8_STRING", 0, TARGET_UTF8_STRING }, |
145 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, | |
146 { "STRING", 0, TARGET_STRING }, | |
147 { "TEXT", 0, TARGET_TEXT}}; | |
148 | |
10871 | 149 static GtkTargetEntry link_drag_drop_targets[] = { |
10145 | 150 GTK_IMHTML_DND_TARGETS |
151 }; | |
8091 | 152 |
8692 | 153 #ifdef _WIN32 |
154 /* Win32 clipboard format value, and functions to convert back and | |
155 * forth between HTML and the clipboard format. | |
156 */ | |
157 static UINT win_html_fmt; | |
158 | |
159 static gchar * | |
160 clipboard_win32_to_html(char *clipboard) { | |
9465 | 161 const char *header; |
8693 | 162 const char *begin, *end; |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
163 gint start = 0; |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
164 gint finish = 0; |
8692 | 165 gchar *html; |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
166 gchar **split; |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
167 int clipboard_length = 0; |
9465 | 168 |
169 #if 0 /* Debugging for Windows clipboard */ | |
9467 | 170 FILE *fd; |
171 | |
9465 | 172 gaim_debug_info("imhtml clipboard", "from clipboard: %s\n", clipboard); |
173 | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10574
diff
changeset
|
174 fd = g_fopen("e:\\gaimcb.txt", "wb"); |
9465 | 175 fprintf(fd, "%s", clipboard); |
176 fclose(fd); | |
177 #endif | |
178 | |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
179 clipboard_length = strlen(clipboard); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
180 |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
181 if (!(header = strstr(clipboard, "StartFragment:")) || (header - clipboard) >= clipboard_length) |
9465 | 182 return NULL; |
183 sscanf(header, "StartFragment:%d", &start); | |
184 | |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
185 if (!(header = strstr(clipboard, "EndFragment:")) || (header - clipboard) >= clipboard_length) |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
186 return NULL; |
9465 | 187 sscanf(header, "EndFragment:%d", &finish); |
188 | |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
189 if (finish > clipboard_length) |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
190 finish = clipboard_length; |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
191 |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
192 if (start > finish) |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
193 start = finish; |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
194 |
9465 | 195 begin = clipboard + start; |
196 | |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
197 end = clipboard + finish; |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
198 |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
199 html = g_strndup(begin, end - begin); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
200 |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
201 /* any newlines in the string will now be \r\n, so we need to strip out the \r */ |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
202 split = g_strsplit(html, "\r\n", 0); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
203 g_free(html); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
204 html = g_strjoinv("\n", split); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
205 g_strfreev(split); |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
206 |
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
207 html = g_strstrip(html); |
9465 | 208 |
209 #if 0 /* Debugging for Windows clipboard */ | |
10016
5b4a0af99bf7
[gaim-migrate @ 10935]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
210 gaim_debug_info("imhtml clipboard", "HTML fragment: '%s'\n", html); |
9465 | 211 #endif |
212 | |
8707 | 213 return html; |
8692 | 214 } |
215 | |
216 static gchar * | |
217 clipboard_html_to_win32(char *html) { | |
8693 | 218 int length; |
11240
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
219 GString *clipboard; |
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
220 gchar *tmp; |
8692 | 221 gchar *ret; |
222 | |
8693 | 223 if (html == NULL) |
224 return NULL; | |
8692 | 225 |
226 length = strlen(html); | |
9465 | 227 clipboard = g_string_new ("Version:1.0\r\n"); |
8692 | 228 g_string_append(clipboard, "StartHTML:0000000105\r\n"); |
11240
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
229 tmp = g_strdup_printf("EndHTML:%010d\r\n", 147 + length); |
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
230 g_string_append(clipboard, tmp); |
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
231 g_free(tmp); |
9465 | 232 g_string_append(clipboard, "StartFragment:0000000127\r\n"); |
11240
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
233 tmp = g_strdup_printf("EndFragment:%010d\r\n", 127 + length); |
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
234 g_string_append(clipboard, tmp); |
2ab2de8add8b
[gaim-migrate @ 13399]
Richard Laager <rlaager@wiktel.com>
parents:
11234
diff
changeset
|
235 g_free(tmp); |
9465 | 236 g_string_append(clipboard, "<!--StartFragment-->\r\n"); |
8692 | 237 g_string_append(clipboard, html); |
9465 | 238 g_string_append(clipboard, "\r\n<!--EndFragment-->"); |
8692 | 239 ret = clipboard->str; |
240 g_string_free(clipboard, FALSE); | |
9465 | 241 |
242 #if 0 /* Debugging for Windows clipboard */ | |
243 gaim_debug_info("imhtml clipboard", "from gaim: %s\n", ret); | |
244 #endif | |
245 | |
8692 | 246 return ret; |
247 } | |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
248 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
249 static void clipboard_copy_html_win32(GtkIMHtml *imhtml) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
250 gchar *clipboard = clipboard_html_to_win32(imhtml->clipboard_html_string); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
251 if (clipboard != NULL) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
252 HWND hwnd = GDK_WINDOW_HWND(GTK_WIDGET(imhtml)->window); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
253 if (OpenClipboard(hwnd)) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
254 if (EmptyClipboard()) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
255 gint length = strlen(clipboard); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
256 HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE, length); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
257 if (hdata != NULL) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
258 gchar *buffer = GlobalLock(hdata); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
259 memcpy(buffer, clipboard, length); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
260 GlobalUnlock(hdata); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
261 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
262 if (SetClipboardData(win_html_fmt, hdata) == NULL) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
263 gchar *err_msg = |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
264 g_win32_error_message(GetLastError()); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
265 gaim_debug_info("html clipboard", |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
266 "Unable to set clipboard data: %s\n", |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
267 err_msg ? err_msg : "Unknown Error"); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
268 g_free(err_msg); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
269 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
270 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
271 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
272 CloseClipboard(); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
273 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
274 g_free(clipboard); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
275 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
276 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
277 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
278 static gboolean clipboard_paste_html_win32(GtkIMHtml *imhtml) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
279 gboolean pasted = FALSE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
280 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
281 if (gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml)) |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
282 && IsClipboardFormatAvailable(win_html_fmt)) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
283 gboolean error_reading_clipboard = FALSE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
284 HWND hwnd = GDK_WINDOW_HWND(GTK_WIDGET(imhtml)->window); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
285 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
286 if (OpenClipboard(hwnd)) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
287 HGLOBAL hdata = GetClipboardData(win_html_fmt); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
288 if (hdata == NULL) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
289 error_reading_clipboard = TRUE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
290 } else { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
291 char *buffer = GlobalLock(hdata); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
292 if (buffer == NULL) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
293 error_reading_clipboard = TRUE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
294 } else { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
295 char *text = clipboard_win32_to_html( |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
296 buffer); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
297 imhtml_paste_insert(imhtml, text, |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
298 FALSE); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
299 g_free(text); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
300 pasted = TRUE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
301 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
302 GlobalUnlock(hdata); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
303 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
304 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
305 CloseClipboard(); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
306 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
307 } else { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
308 error_reading_clipboard = TRUE; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
309 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
310 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
311 if (error_reading_clipboard) { |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
312 gchar *err_msg = g_win32_error_message(GetLastError()); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
313 gaim_debug_info("html clipboard", |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
314 "Unable to read clipboard data: %s\n", |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
315 err_msg ? err_msg : "Unknown Error"); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
316 g_free(err_msg); |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
317 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
318 } |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
319 |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
320 return pasted; |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
321 } |
8692 | 322 #endif |
323 | |
4032 | 324 static GtkSmileyTree* |
325 gtk_smiley_tree_new () | |
326 { | |
327 return g_new0 (GtkSmileyTree, 1); | |
328 } | |
329 | |
330 static void | |
331 gtk_smiley_tree_insert (GtkSmileyTree *tree, | |
4263 | 332 GtkIMHtmlSmiley *smiley) |
4032 | 333 { |
334 GtkSmileyTree *t = tree; | |
4263 | 335 const gchar *x = smiley->smile; |
4032 | 336 |
337 if (!strlen (x)) | |
338 return; | |
339 | |
340 while (*x) { | |
341 gchar *pos; | |
342 gint index; | |
343 | |
344 if (!t->values) | |
345 t->values = g_string_new (""); | |
346 | |
347 pos = strchr (t->values->str, *x); | |
348 if (!pos) { | |
349 t->values = g_string_append_c (t->values, *x); | |
350 index = t->values->len - 1; | |
351 t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *)); | |
352 t->children [index] = g_new0 (GtkSmileyTree, 1); | |
353 } else | |
7386 | 354 index = GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str); |
8061 | 355 |
4032 | 356 t = t->children [index]; |
8061 | 357 |
4032 | 358 x++; |
359 } | |
8061 | 360 |
4263 | 361 t->image = smiley; |
4032 | 362 } |
4041 | 363 |
4263 | 364 |
4264 | 365 void gtk_smiley_tree_destroy (GtkSmileyTree *tree) |
4032 | 366 { |
367 GSList *list = g_slist_append (NULL, tree); | |
368 | |
369 while (list) { | |
370 GtkSmileyTree *t = list->data; | |
371 gint i; | |
372 list = g_slist_remove(list, t); | |
7384 | 373 if (t && t->values) { |
4032 | 374 for (i = 0; i < t->values->len; i++) |
375 list = g_slist_append (list, t->children [i]); | |
376 g_string_free (t->values, TRUE); | |
377 g_free (t->children); | |
378 } | |
379 g_free (t); | |
380 } | |
381 } | |
382 | |
5967 | 383 static gboolean gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) |
384 { | |
385 GdkRectangle rect; | |
8726 | 386 int xminus; |
5967 | 387 |
388 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); | |
389 if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ | |
390 GList *iter = GTK_IMHTML(widget)->scalables; | |
391 | |
8726 | 392 xminus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(widget)) + |
393 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(widget)); | |
394 | |
5967 | 395 while(iter){ |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
396 struct scalable_data *sd = iter->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
397 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(sd->scalable); |
8726 | 398 scale->scale(scale, rect.width - xminus, rect.height); |
5967 | 399 |
400 iter = iter->next; | |
401 } | |
402 } | |
403 | |
404 widget->old_rect = rect; | |
405 return FALSE; | |
406 } | |
407 | |
408 static gint | |
409 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) | |
410 { | |
411 PangoLayout *layout; | |
412 | |
413 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
414 | |
415 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
416 | |
8061 | 417 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, |
5967 | 418 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, |
419 "tooltip", 0, 0, -1, -1); | |
420 | |
421 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, | |
422 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); | |
423 | |
424 g_object_unref(layout); | |
425 return FALSE; | |
426 } | |
427 | |
428 static gint | |
429 gtk_imhtml_tip (gpointer data) | |
430 { | |
431 GtkIMHtml *imhtml = data; | |
8526 | 432 PangoFontMetrics *font_metrics; |
5967 | 433 PangoLayout *layout; |
8526 | 434 PangoFont *font; |
5967 | 435 |
436 gint gap, x, y, h, w, scr_w, baseline_skip; | |
437 | |
438 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); | |
439 | |
440 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { | |
441 imhtml->tip_timer = 0; | |
442 return FALSE; | |
443 } | |
8061 | 444 |
5967 | 445 if (imhtml->tip_window){ |
446 gtk_widget_destroy (imhtml->tip_window); | |
447 imhtml->tip_window = NULL; | |
448 } | |
449 | |
450 imhtml->tip_timer = 0; | |
451 imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP); | |
452 gtk_widget_set_app_paintable (imhtml->tip_window, TRUE); | |
453 gtk_window_set_resizable (GTK_WINDOW (imhtml->tip_window), FALSE); | |
454 gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); | |
455 g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", | |
456 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); | |
457 | |
458 gtk_widget_ensure_style (imhtml->tip_window); | |
459 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); | |
8526 | 460 font = pango_context_load_font(pango_layout_get_context(layout), |
461 imhtml->tip_window->style->font_desc); | |
462 | |
463 if (font == NULL) { | |
464 char *tmp = pango_font_description_to_string( | |
465 imhtml->tip_window->style->font_desc); | |
466 | |
467 gaim_debug(GAIM_DEBUG_ERROR, "gtk_imhtml_tip", | |
468 "pango_context_load_font() couldn't load font: '%s'\n", | |
469 tmp); | |
470 g_free(tmp); | |
471 | |
472 return FALSE; | |
473 } | |
474 | |
475 font_metrics = pango_font_get_metrics(font, NULL); | |
5967 | 476 |
477 pango_layout_get_pixel_size(layout, &scr_w, NULL); | |
8526 | 478 gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font_metrics) + |
479 pango_font_metrics_get_descent(font_metrics))/ 4); | |
5967 | 480 |
481 if (gap < 2) | |
482 gap = 2; | |
8526 | 483 baseline_skip = PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics) + |
484 pango_font_metrics_get_descent(font_metrics)); | |
5967 | 485 w = 8 + scr_w; |
486 h = 8 + baseline_skip; | |
487 | |
488 gdk_window_get_pointer (NULL, &x, &y, NULL); | |
489 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) | |
490 y += GTK_WIDGET(imhtml)->allocation.y; | |
491 | |
492 scr_w = gdk_screen_width(); | |
493 | |
494 x -= ((w >> 1) + 4); | |
495 | |
496 if ((x + w) > scr_w) | |
497 x -= (x + w) - scr_w; | |
498 else if (x < 0) | |
499 x = 0; | |
500 | |
8526 | 501 y = y + PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics) + |
502 pango_font_metrics_get_descent(font_metrics)); | |
5967 | 503 |
504 gtk_widget_set_size_request (imhtml->tip_window, w, h); | |
505 gtk_widget_show (imhtml->tip_window); | |
506 gtk_window_move (GTK_WINDOW(imhtml->tip_window), x, y); | |
507 | |
8526 | 508 pango_font_metrics_unref(font_metrics); |
5967 | 509 g_object_unref(layout); |
510 | |
511 return FALSE; | |
512 } | |
513 | |
514 gboolean gtk_motion_event_notify(GtkWidget *imhtml, GdkEventMotion *event, gpointer data) | |
8061 | 515 { |
5967 | 516 GtkTextIter iter; |
517 GdkWindow *win = event->window; | |
518 int x, y; | |
519 char *tip = NULL; | |
520 GSList *tags = NULL, *templist = NULL; | |
10799 | 521 GdkColor *norm, *pre; |
522 GtkTextTag *tag = NULL, *oldprelit_tag; | |
523 | |
524 oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag; | |
525 | |
5967 | 526 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); |
527 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, | |
10799 | 528 event->x, event->y, &x, &y); |
5967 | 529 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); |
530 tags = gtk_text_iter_get_tags(&iter); | |
531 | |
532 templist = tags; | |
533 while (templist) { | |
10799 | 534 tag = templist->data; |
5967 | 535 tip = g_object_get_data(G_OBJECT(tag), "link_url"); |
536 if (tip) | |
537 break; | |
538 templist = templist->next; | |
539 } | |
8061 | 540 |
10799 | 541 if (tip) { |
542 gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-prelight-color", &pre, NULL); | |
543 GTK_IMHTML(imhtml)->prelit_tag = tag; | |
544 if (tag != oldprelit_tag) { | |
545 if (pre) | |
546 g_object_set(G_OBJECT(tag), "foreground-gdk", pre, NULL); | |
547 else | |
548 g_object_set(G_OBJECT(tag), "foreground", "light blue", NULL); | |
549 } | |
550 } else { | |
551 GTK_IMHTML(imhtml)->prelit_tag = NULL; | |
552 } | |
553 | |
10834 | 554 if ((oldprelit_tag != NULL) && (GTK_IMHTML(imhtml)->prelit_tag != oldprelit_tag)) { |
10799 | 555 gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &norm, NULL); |
556 if (norm) | |
557 g_object_set(G_OBJECT(oldprelit_tag), "foreground-gdk", norm, NULL); | |
558 else | |
559 g_object_set(G_OBJECT(oldprelit_tag), "foreground", "blue", NULL); | |
560 } | |
561 | |
5967 | 562 if (GTK_IMHTML(imhtml)->tip) { |
563 if ((tip == GTK_IMHTML(imhtml)->tip)) { | |
564 return FALSE; | |
565 } | |
566 /* We've left the cell. Remove the timeout and create a new one below */ | |
567 if (GTK_IMHTML(imhtml)->tip_window) { | |
568 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
569 GTK_IMHTML(imhtml)->tip_window = NULL; | |
570 } | |
8061 | 571 if (GTK_IMHTML(imhtml)->editable) |
572 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->text_cursor); | |
573 else | |
574 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->arrow_cursor); | |
5967 | 575 if (GTK_IMHTML(imhtml)->tip_timer) |
576 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
577 GTK_IMHTML(imhtml)->tip_timer = 0; | |
578 } | |
8061 | 579 |
10799 | 580 if (tip){ |
8061 | 581 if (!GTK_IMHTML(imhtml)->editable) |
582 gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor); | |
583 GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT, | |
5967 | 584 gtk_imhtml_tip, imhtml); |
585 } | |
8061 | 586 |
5967 | 587 GTK_IMHTML(imhtml)->tip = tip; |
588 g_slist_free(tags); | |
589 return FALSE; | |
590 } | |
591 | |
10946
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
592 gboolean gtk_enter_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
593 { |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
594 if (GTK_IMHTML(imhtml)->editable) |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
595 gdk_window_set_cursor( |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
596 gtk_text_view_get_window(GTK_TEXT_VIEW(imhtml), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
597 GTK_TEXT_WINDOW_TEXT), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
598 GTK_IMHTML(imhtml)->text_cursor); |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
599 else |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
600 gdk_window_set_cursor( |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
601 gtk_text_view_get_window(GTK_TEXT_VIEW(imhtml), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
602 GTK_TEXT_WINDOW_TEXT), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
603 GTK_IMHTML(imhtml)->arrow_cursor); |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
604 |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
605 /* propagate the event normally */ |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
606 return FALSE; |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
607 } |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
608 |
5967 | 609 gboolean gtk_leave_event_notify(GtkWidget *imhtml, GdkEventCrossing *event, gpointer data) |
610 { | |
611 /* when leaving the widget, clear any current & pending tooltips and restore the cursor */ | |
10799 | 612 if (GTK_IMHTML(imhtml)->prelit_tag) { |
613 GdkColor *norm; | |
614 gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &norm, NULL); | |
615 if (norm) | |
616 g_object_set(G_OBJECT(GTK_IMHTML(imhtml)->prelit_tag), "foreground-gdk", norm, NULL); | |
617 else | |
618 g_object_set(G_OBJECT(GTK_IMHTML(imhtml)->prelit_tag), "foreground", "blue", NULL); | |
619 GTK_IMHTML(imhtml)->prelit_tag = NULL; | |
620 } | |
621 | |
5967 | 622 if (GTK_IMHTML(imhtml)->tip_window) { |
623 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
624 GTK_IMHTML(imhtml)->tip_window = NULL; | |
625 } | |
626 if (GTK_IMHTML(imhtml)->tip_timer) { | |
627 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
628 GTK_IMHTML(imhtml)->tip_timer = 0; | |
629 } | |
10946
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
630 gdk_window_set_cursor( |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
631 gtk_text_view_get_window(GTK_TEXT_VIEW(imhtml), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
632 GTK_TEXT_WINDOW_TEXT), NULL); |
5967 | 633 |
8568 | 634 /* propagate the event normally */ |
5967 | 635 return FALSE; |
636 } | |
637 | |
10844 | 638 #if (!GTK_CHECK_VERSION(2,2,0)) |
6066 | 639 /* |
640 * XXX - This should be removed eventually. | |
641 * | |
8061 | 642 * This function exists to work around a gross bug in GtkTextView. |
643 * Basically, we short circuit ctrl+a and ctrl+end because they make | |
6066 | 644 * el program go boom. |
645 * | |
8061 | 646 * It's supposed to be fixed in gtk2.2. You can view the bug report at |
6066 | 647 * http://bugzilla.gnome.org/show_bug.cgi?id=107939 |
648 */ | |
10849 | 649 static gboolean |
650 gtk_key_pressed_cb(GtkIMHtml *imhtml, GdkEventKey *event, gpointer data) | |
8677 | 651 { |
10844 | 652 if (event->state & GDK_CONTROL_MASK) { |
6066 | 653 switch (event->keyval) { |
10844 | 654 case 'a': |
655 case GDK_Home: | |
656 case GDK_End: | |
657 return TRUE; | |
6066 | 658 } |
10844 | 659 } |
6066 | 660 return FALSE; |
661 } | |
10844 | 662 #endif /* !(GTK+ >= 2.2.0) */ |
10692 | 663 |
664 static gint | |
665 gtk_imhtml_expose_event (GtkWidget *widget, | |
666 GdkEventExpose *event) | |
667 { | |
10776 | 668 GtkTextIter start, end, cur; |
669 int buf_x, buf_y; | |
670 GdkRectangle visible_rect; | |
10777 | 671 GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window)); |
672 GdkColor gcolor; | |
10844 | 673 |
10776 | 674 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect); |
675 gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), | |
676 GTK_TEXT_WINDOW_TEXT, | |
677 visible_rect.x, | |
678 visible_rect.y, | |
679 &visible_rect.x, | |
680 &visible_rect.y); | |
681 | |
682 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT, | |
683 event->area.x, event->area.y, &buf_x, &buf_y); | |
684 | |
10777 | 685 if (GTK_IMHTML(widget)->editable || GTK_IMHTML(widget)->wbfo) { |
686 | |
687 if (GTK_IMHTML(widget)->edit.background) { | |
688 gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor); | |
689 gdk_gc_set_rgb_fg_color(gc, &gcolor); | |
690 } else { | |
691 gdk_gc_set_rgb_fg_color(gc, &(widget->style->base[GTK_WIDGET_STATE(widget)])); | |
692 } | |
693 | |
694 gdk_draw_rectangle(event->window, | |
695 gc, | |
696 TRUE, | |
697 visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height); | |
698 gdk_gc_unref(gc); | |
699 | |
700 if (GTK_WIDGET_CLASS (parent_class)->expose_event) | |
701 return (* GTK_WIDGET_CLASS (parent_class)->expose_event) | |
702 (widget, event); | |
703 | |
704 return FALSE; | |
705 | |
706 } | |
707 | |
10776 | 708 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &start, buf_x, buf_y); |
709 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &end, | |
710 buf_x + event->area.width, buf_y + event->area.height); | |
711 | |
712 | |
713 | |
714 cur = start; | |
715 | |
716 while (gtk_text_iter_in_range(&cur, &start, &end)) { | |
10795 | 717 GSList *tags = gtk_text_iter_get_tags(&cur); |
718 GSList *l; | |
10776 | 719 |
720 for (l = tags; l; l = l->next) { | |
721 GtkTextTag *tag = l->data; | |
722 GdkRectangle rect; | |
723 GdkRectangle tag_area; | |
724 const char *color; | |
10777 | 725 |
10776 | 726 if (strncmp(tag->name, "BACKGROUND ", 11)) |
727 continue; | |
728 | |
729 if (gtk_text_iter_ends_tag(&cur, tag)) | |
730 continue; | |
731 | |
732 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &cur, &tag_area); | |
733 gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), | |
734 GTK_TEXT_WINDOW_TEXT, | |
735 tag_area.x, | |
736 tag_area.y, | |
737 &tag_area.x, | |
738 &tag_area.y); | |
739 rect.x = visible_rect.x; | |
740 rect.y = tag_area.y; | |
741 | |
10795 | 742 do |
10776 | 743 gtk_text_iter_forward_to_tag_toggle(&cur, tag); |
10795 | 744 while (!gtk_text_iter_is_end(&cur) && gtk_text_iter_begins_tag(&cur, tag)); |
745 | |
10776 | 746 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &cur, &tag_area); |
747 gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), | |
748 GTK_TEXT_WINDOW_TEXT, | |
749 tag_area.x, | |
750 tag_area.y, | |
751 &tag_area.x, | |
752 &tag_area.y); | |
753 | |
754 rect.width = visible_rect.width; | |
755 if (gtk_text_iter_is_end(&cur)) | |
756 rect.height = visible_rect.y + visible_rect.height - rect.y; | |
757 else | |
758 rect.height = tag_area.y + tag_area.height - rect.y | |
759 + gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget)); | |
760 | |
761 color = tag->name + 11; | |
762 | |
10857 | 763 if (!gdk_color_parse(color, &gcolor)) { |
10858 | 764 gchar tmp[8]; |
765 tmp[0] = '#'; | |
766 strncpy(&tmp[1], color, 7); | |
767 tmp[7] = '\0'; | |
10857 | 768 if (!gdk_color_parse(tmp, &gcolor)) |
769 gdk_color_parse("white", &gcolor); | |
770 } | |
10776 | 771 gdk_gc_set_rgb_fg_color(gc, &gcolor); |
772 | |
773 | |
774 gdk_draw_rectangle(event->window, | |
775 gc, | |
776 TRUE, | |
777 rect.x, rect.y, rect.width, rect.height); | |
10795 | 778 gtk_text_iter_backward_char(&cur); /* go back one, in case the end is the begining is the end |
779 * note that above, we always moved cur ahead by at least | |
780 * one character */ | |
10776 | 781 break; |
782 } | |
783 | |
784 g_slist_free(tags); | |
10795 | 785 |
786 /* loop until another tag begins, or no tag begins */ | |
787 while (gtk_text_iter_forward_to_tag_toggle(&cur, NULL) && | |
788 !gtk_text_iter_is_end(&cur) && | |
789 !gtk_text_iter_begins_tag(&cur, NULL)); | |
790 } | |
791 | |
10777 | 792 gdk_gc_unref(gc); |
793 | |
10692 | 794 if (GTK_WIDGET_CLASS (parent_class)->expose_event) |
795 return (* GTK_WIDGET_CLASS (parent_class)->expose_event) | |
796 (widget, event); | |
10776 | 797 |
10692 | 798 return FALSE; |
799 } | |
800 | |
801 | |
8931 | 802 static void paste_unformatted_cb(GtkMenuItem *menu, GtkIMHtml *imhtml) |
803 { | |
804 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); | |
805 | |
806 gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml); | |
807 | |
808 } | |
809 | |
10692 | 810 |
811 | |
8931 | 812 static void hijack_menu_cb(GtkIMHtml *imhtml, GtkMenu *menu, gpointer data) |
813 { | |
814 GtkWidget *menuitem; | |
815 | |
816 menuitem = gtk_menu_item_new_with_mnemonic(_("Pa_ste As Text")); | |
817 gtk_widget_show(menuitem); | |
818 gtk_widget_set_sensitive(menuitem, | |
819 (imhtml->editable && | |
820 gtk_clipboard_wait_is_text_available( | |
821 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD)))); | |
822 /* put it after "Paste" */ | |
823 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, 3); | |
824 | |
825 g_signal_connect(G_OBJECT(menuitem), "activate", | |
826 G_CALLBACK(paste_unformatted_cb), imhtml); | |
827 } | |
828 | |
8061 | 829 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { |
8681 | 830 char *text; |
8782
5a2b5e4abf3a
[gaim-migrate @ 9544]
Christian Hammond <chipx86@chipx86.com>
parents:
8758
diff
changeset
|
831 gboolean primary; |
8061 | 832 GtkTextIter start, end; |
833 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
834 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
10013 | 835 |
8061 | 836 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); |
837 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
|
838 primary = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY) == clipboard; |
8061 | 839 |
840 if (info == TARGET_HTML) { | |
8907 | 841 gsize len; |
8148 | 842 char *selection; |
8061 | 843 GString *str = g_string_new(NULL); |
8681 | 844 if (primary) { |
845 text = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
10013 | 846 } else |
8681 | 847 text = imhtml->clipboard_html_string; |
8061 | 848 |
849 /* Mozilla asks that we start our text/html with the Unicode byte order mark */ | |
850 str = g_string_append_unichar(str, 0xfeff); | |
851 str = g_string_append(str, text); | |
852 str = g_string_append_unichar(str, 0x0000); | |
8148 | 853 selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
11143 | 854 gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 16, (const guchar *)selection, len); |
8061 | 855 g_string_free(str, TRUE); |
856 g_free(selection); | |
857 } else { | |
8681 | 858 if (primary) { |
859 text = gtk_imhtml_get_text(imhtml, &start, &end); | |
860 } else | |
861 text = imhtml->clipboard_text_string; | |
8061 | 862 gtk_selection_data_set_text(selection_data, text, strlen(text)); |
863 } | |
8681 | 864 if (primary) /* This was allocated here */ |
865 g_free(text); | |
866 } | |
8061 | 867 |
868 static void gtk_imhtml_primary_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml) | |
7749 | 869 { |
8061 | 870 GtkTextIter insert; |
871 GtkTextIter selection_bound; | |
872 | |
873 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &insert, | |
874 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert")); | |
875 gtk_text_buffer_get_iter_at_mark (imhtml->text_buffer, &selection_bound, | |
876 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound")); | |
877 | |
878 if (!gtk_text_iter_equal (&insert, &selection_bound)) | |
879 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
880 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound"), | |
881 &insert); | |
7749 | 882 } |
7742 | 883 |
8677 | 884 static void copy_clipboard_cb(GtkIMHtml *imhtml, gpointer unused) |
7749 | 885 { |
8681 | 886 GtkTextIter start, end; |
887 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
888 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
889 | |
890 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | |
891 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
892 | |
8061 | 893 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), |
894 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
895 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
896 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | |
7346 | 897 |
8681 | 898 if (imhtml->clipboard_html_string) { |
899 g_free(imhtml->clipboard_html_string); | |
900 g_free(imhtml->clipboard_text_string); | |
901 } | |
902 | |
903 imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
904 imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); | |
905 | |
8692 | 906 #ifdef _WIN32 |
907 /* We're going to still copy plain text, but let's toss the "HTML Format" | |
908 we need into the windows clipboard now as well. */ | |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
909 clipboard_copy_html_win32(imhtml); |
8692 | 910 #endif |
911 | |
8061 | 912 g_signal_stop_emission_by_name(imhtml, "copy-clipboard"); |
913 } | |
914 | |
8698 | 915 static void cut_clipboard_cb(GtkIMHtml *imhtml, gpointer unused) |
916 { | |
917 GtkTextIter start, end; | |
918 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | |
919 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
920 | |
921 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | |
922 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | |
923 | |
924 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), | |
925 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
926 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
927 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | |
928 | |
929 if (imhtml->clipboard_html_string) { | |
930 g_free(imhtml->clipboard_html_string); | |
931 g_free(imhtml->clipboard_text_string); | |
932 } | |
933 | |
934 imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
935 imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); | |
936 | |
937 #ifdef _WIN32 | |
938 /* We're going to still copy plain text, but let's toss the "HTML Format" | |
939 we need into the windows clipboard now as well. */ | |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
940 clipboard_copy_html_win32(imhtml); |
8698 | 941 #endif |
942 | |
943 if (imhtml->editable) | |
944 gtk_text_buffer_delete_selection(imhtml->text_buffer, FALSE, FALSE); | |
945 g_signal_stop_emission_by_name(imhtml, "cut-clipboard"); | |
946 } | |
947 | |
8931 | 948 static void imhtml_paste_insert(GtkIMHtml *imhtml, const char *text, gboolean plaintext) |
949 { | |
950 GtkTextIter iter; | |
9465 | 951 GtkIMHtmlOptions flags = plaintext ? 0 : (GTK_IMHTML_NO_NEWLINE | GTK_IMHTML_NO_COMMENTS); |
8931 | 952 |
9028 | 953 if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) |
954 gtk_text_buffer_delete_selection(imhtml->text_buffer, TRUE, TRUE); | |
955 | |
8931 | 956 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, gtk_text_buffer_get_insert(imhtml->text_buffer)); |
957 if (!imhtml->wbfo && !plaintext) | |
958 gtk_imhtml_close_tags(imhtml, &iter); | |
959 | |
960 gtk_imhtml_insert_html_at_iter(imhtml, text, flags, &iter); | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
961 if (!imhtml->wbfo && !plaintext) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
962 gtk_imhtml_close_tags(imhtml, &iter); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
963 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter); |
8931 | 964 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), gtk_text_buffer_get_insert(imhtml->text_buffer), |
965 0, FALSE, 0.0, 0.0); | |
966 } | |
967 | |
968 static void paste_plaintext_received_cb (GtkClipboard *clipboard, const gchar *text, gpointer data) | |
969 { | |
970 char *tmp; | |
971 | |
972 if (text == NULL) | |
973 return; | |
974 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10699
diff
changeset
|
975 tmp = g_markup_escape_text(text, -1); |
8931 | 976 imhtml_paste_insert(data, tmp, TRUE); |
977 g_free(tmp); | |
978 } | |
979 | |
8061 | 980 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) |
981 { | |
982 char *text; | |
983 GtkIMHtml *imhtml = data; | |
7809 | 984 |
8123 | 985 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) |
8105 | 986 return; |
987 | |
8061 | 988 if (selection_data->length < 0) { |
8931 | 989 gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml); |
990 return; | |
8061 | 991 } else { |
8719 | 992 #if 0 |
993 /* Here's some debug code, for figuring out what sent to us over the clipboard. */ | |
994 { | |
995 int i; | |
996 | |
997 gaim_debug_misc("gtkimhtml", "In paste_received_cb():\n\tformat = %d, length = %d\n\t", | |
998 selection_data->format, selection_data->length); | |
999 | |
1000 for (i = 0; i < (/*(selection_data->format / 8) **/ selection_data->length); i++) { | |
1001 if ((i % 70) == 0) | |
1002 printf("\n\t"); | |
1003 if (selection_data->data[i] == '\0') | |
1004 printf("."); | |
1005 else | |
1006 printf("%c", selection_data->data[i]); | |
1007 } | |
1008 printf("\n"); | |
1009 } | |
1010 #endif | |
1011 text = g_malloc(selection_data->length); | |
1012 memcpy(text, selection_data->data, selection_data->length); | |
7766 | 1013 } |
8061 | 1014 |
8869 | 1015 if (selection_data->length >= 2 && |
1016 (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) { | |
1017 /* This is UCS-2 */ | |
8909 | 1018 char *tmp; |
8869 | 1019 char *utf8 = g_convert(text, selection_data->length, "UTF-8", "UCS-2", NULL, NULL, NULL); |
8061 | 1020 g_free(text); |
1021 text = utf8; | |
8698 | 1022 if (!text) { |
8869 | 1023 gaim_debug_warning("gtkimhtml", "g_convert from UCS-2 failed in paste_received_cb\n"); |
8698 | 1024 return; |
1025 } | |
8909 | 1026 tmp = g_utf8_next_char(text); |
1027 memmove(text, tmp, strlen(tmp) + 1); | |
8061 | 1028 } |
9621 | 1029 |
8698 | 1030 if (!(*text) || !g_utf8_validate(text, -1, NULL)) { |
1031 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in paste_received_cb\n"); | |
1032 g_free(text); | |
1033 return; | |
1034 } | |
1035 | |
8931 | 1036 imhtml_paste_insert(imhtml, text, FALSE); |
8681 | 1037 g_free(text); |
8061 | 1038 } |
1039 | |
1040 static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) | |
1041 { | |
8931 | 1042 #ifdef _WIN32 |
1043 /* If we're on windows, let's see if we can get data from the HTML Format | |
10901
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
1044 clipboard before we try to paste from the GTK buffer */ |
0711078e0e2d
[gaim-migrate @ 12622]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10900
diff
changeset
|
1045 if (!clipboard_paste_html_win32(imhtml)) { |
8931 | 1046 #endif |
8061 | 1047 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); |
1048 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
1049 paste_received_cb, imhtml); | |
8931 | 1050 #ifdef _WIN32 |
1051 } | |
1052 #endif | |
8061 | 1053 g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); |
7766 | 1054 } |
1055 | |
8677 | 1056 static void imhtml_realized_remove_primary(GtkIMHtml *imhtml, gpointer unused) |
1057 { | |
1058 gtk_text_buffer_remove_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, | |
1059 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); | |
1060 | |
1061 } | |
1062 | |
8740
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1063 static void imhtml_destroy_add_primary(GtkIMHtml *imhtml, gpointer unused) |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1064 { |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1065 gtk_text_buffer_add_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1066 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); |
61a090413b93
[gaim-migrate @ 9495]
Christian Hammond <chipx86@chipx86.com>
parents:
8735
diff
changeset
|
1067 } |
8677 | 1068 |
1069 static void mark_set_so_update_selection_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml) | |
1070 { | |
1071 if (gtk_text_buffer_get_selection_bounds(buffer, NULL, NULL)) { | |
1072 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY), | |
1073 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | |
1074 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | |
1075 (GtkClipboardClearFunc)gtk_imhtml_primary_clipboard_clear, G_OBJECT(imhtml)); | |
1076 } | |
1077 } | |
1078 | |
1079 static gboolean gtk_imhtml_button_press_event(GtkIMHtml *imhtml, GdkEventButton *event, gpointer unused) | |
7346 | 1080 { |
8677 | 1081 if (event->button == 2) { |
1082 int x, y; | |
1083 GtkTextIter iter; | |
1084 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY); | |
1085 | |
1086 if (!imhtml->editable) | |
1087 return FALSE; | |
1088 | |
1089 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), | |
1090 GTK_TEXT_WINDOW_TEXT, | |
1091 event->x, | |
1092 event->y, | |
1093 &x, | |
1094 &y); | |
1095 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
1096 gtk_text_buffer_place_cursor(imhtml->text_buffer, &iter); | |
1097 | |
1098 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
1099 paste_received_cb, imhtml); | |
1100 | |
1101 return TRUE; | |
1102 } | |
1103 | |
7346 | 1104 return FALSE; |
1105 } | |
4263 | 1106 |
10108 | 1107 static gboolean imhtml_message_send(GtkIMHtml *imhtml) |
1108 { | |
1109 return FALSE; | |
1110 } | |
1111 | |
10100 | 1112 static void imhtml_toggle_format(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) |
1113 { | |
10699 | 1114 /* since this function is the handler for the formatting keystrokes, |
1115 we need to check here that the formatting attempted is permitted */ | |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
1116 buttons &= imhtml->format_functions; |
10699 | 1117 |
10100 | 1118 switch (buttons) { |
1119 case GTK_IMHTML_BOLD: | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1120 imhtml_toggle_bold(imhtml); |
10100 | 1121 break; |
1122 case GTK_IMHTML_ITALIC: | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1123 imhtml_toggle_italic(imhtml); |
10100 | 1124 break; |
1125 case GTK_IMHTML_UNDERLINE: | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1126 imhtml_toggle_underline(imhtml); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1127 break; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1128 case GTK_IMHTML_STRIKE: |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1129 imhtml_toggle_strike(imhtml); |
10100 | 1130 break; |
1131 case GTK_IMHTML_SHRINK: | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1132 imhtml_font_shrink(imhtml); |
10100 | 1133 break; |
1134 case GTK_IMHTML_GROW: | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
1135 imhtml_font_grow(imhtml); |
10100 | 1136 break; |
1137 default: | |
1138 break; | |
1139 } | |
1140 } | |
4032 | 1141 |
1142 static void | |
1143 gtk_imhtml_finalize (GObject *object) | |
1144 { | |
1145 GtkIMHtml *imhtml = GTK_IMHTML(object); | |
4895 | 1146 GList *scalables; |
8962 | 1147 GSList *l; |
8061 | 1148 |
10798 | 1149 if (imhtml->scroll_src) |
1150 g_source_remove(imhtml->scroll_src); | |
1151 if (imhtml->scroll_time) | |
1152 g_timer_destroy(imhtml->scroll_time); | |
1153 | |
4138 | 1154 g_hash_table_destroy(imhtml->smiley_data); |
4032 | 1155 gtk_smiley_tree_destroy(imhtml->default_smilies); |
4138 | 1156 gdk_cursor_unref(imhtml->hand_cursor); |
1157 gdk_cursor_unref(imhtml->arrow_cursor); | |
8061 | 1158 gdk_cursor_unref(imhtml->text_cursor); |
8677 | 1159 |
4735 | 1160 if(imhtml->tip_window){ |
1161 gtk_widget_destroy(imhtml->tip_window); | |
1162 } | |
1163 if(imhtml->tip_timer) | |
1164 gtk_timeout_remove(imhtml->tip_timer); | |
1165 | |
4895 | 1166 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1167 struct scalable_data *sd = scalables->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1168 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(sd->scalable); |
4895 | 1169 scale->free(scale); |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1170 g_free(sd); |
4895 | 1171 } |
7991 | 1172 |
8962 | 1173 for (l = imhtml->im_images; l; l = l->next) { |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1174 struct im_image_data *img_data = l->data; |
8962 | 1175 if (imhtml->funcs->image_unref) |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1176 imhtml->funcs->image_unref(img_data->id); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
1177 g_free(img_data); |
8962 | 1178 } |
1179 | |
8681 | 1180 if (imhtml->clipboard_text_string) { |
1181 g_free(imhtml->clipboard_text_string); | |
1182 g_free(imhtml->clipboard_html_string); | |
1183 } | |
1184 | |
4895 | 1185 g_list_free(imhtml->scalables); |
8962 | 1186 g_slist_free(imhtml->im_images); |
9029 | 1187 if (imhtml->protocol_name) |
1188 g_free(imhtml->protocol_name); | |
10574 | 1189 if (imhtml->search_string) |
1190 g_free(imhtml->search_string); | |
4032 | 1191 G_OBJECT_CLASS(parent_class)->finalize (object); |
1192 } | |
1428 | 1193 |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10799
diff
changeset
|
1194 /* Boring GTK+ stuff */ |
8519 | 1195 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) |
1428 | 1196 { |
9007 | 1197 GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; |
3922 | 1198 GtkObjectClass *object_class; |
10100 | 1199 GtkBindingSet *binding_set; |
4032 | 1200 GObjectClass *gobject_class; |
8519 | 1201 object_class = (GtkObjectClass*) klass; |
1202 gobject_class = (GObjectClass*) klass; | |
4032 | 1203 parent_class = gtk_type_class(GTK_TYPE_TEXT_VIEW); |
4417 | 1204 signals[URL_CLICKED] = g_signal_new("url_clicked", |
1205 G_TYPE_FROM_CLASS(gobject_class), | |
1206 G_SIGNAL_RUN_FIRST, | |
1207 G_STRUCT_OFFSET(GtkIMHtmlClass, url_clicked), | |
1208 NULL, | |
1209 0, | |
1210 g_cclosure_marshal_VOID__POINTER, | |
1211 G_TYPE_NONE, 1, | |
1212 G_TYPE_POINTER); | |
8506 | 1213 signals[BUTTONS_UPDATE] = g_signal_new("format_buttons_update", |
8420 | 1214 G_TYPE_FROM_CLASS(gobject_class), |
1215 G_SIGNAL_RUN_FIRST, | |
1216 G_STRUCT_OFFSET(GtkIMHtmlClass, buttons_update), | |
1217 NULL, | |
1218 0, | |
10076 | 1219 g_cclosure_marshal_VOID__INT, |
8420 | 1220 G_TYPE_NONE, 1, |
1221 G_TYPE_INT); | |
1222 signals[TOGGLE_FORMAT] = g_signal_new("format_function_toggle", | |
1223 G_TYPE_FROM_CLASS(gobject_class), | |
10100 | 1224 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
8420 | 1225 G_STRUCT_OFFSET(GtkIMHtmlClass, toggle_format), |
1226 NULL, | |
1227 0, | |
10076 | 1228 g_cclosure_marshal_VOID__INT, |
1229 G_TYPE_NONE, 1, | |
8420 | 1230 G_TYPE_INT); |
8427 | 1231 signals[CLEAR_FORMAT] = g_signal_new("format_function_clear", |
1232 G_TYPE_FROM_CLASS(gobject_class), | |
11385
78cd70f4834c
[gaim-migrate @ 13612]
Luke Schierer <lschiere@pidgin.im>
parents:
11315
diff
changeset
|
1233 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, |
8427 | 1234 G_STRUCT_OFFSET(GtkIMHtmlClass, clear_format), |
1235 NULL, | |
1236 0, | |
10100 | 1237 g_cclosure_marshal_VOID__VOID, |
1238 G_TYPE_NONE, 0); | |
8506 | 1239 signals[UPDATE_FORMAT] = g_signal_new("format_function_update", |
10100 | 1240 G_TYPE_FROM_CLASS(gobject_class), |
1241 G_SIGNAL_RUN_FIRST, | |
1242 G_STRUCT_OFFSET(GtkIMHtmlClass, update_format), | |
1243 NULL, | |
1244 0, | |
1245 g_cclosure_marshal_VOID__VOID, | |
1246 G_TYPE_NONE, 0); | |
10108 | 1247 signals[MESSAGE_SEND] = g_signal_new("message_send", |
1248 G_TYPE_FROM_CLASS(gobject_class), | |
1249 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, | |
1250 G_STRUCT_OFFSET(GtkIMHtmlClass, message_send), | |
1251 NULL, | |
1252 0, g_cclosure_marshal_VOID__VOID, | |
1253 G_TYPE_NONE, 0); | |
10100 | 1254 |
1255 klass->toggle_format = imhtml_toggle_format; | |
10108 | 1256 klass->message_send = imhtml_message_send; |
10184 | 1257 |
4032 | 1258 gobject_class->finalize = gtk_imhtml_finalize; |
10184 | 1259 widget_class->drag_motion = gtk_text_view_drag_motion; |
10692 | 1260 widget_class->expose_event = gtk_imhtml_expose_event; |
9007 | 1261 gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-color", |
1262 _("Hyperlink color"), | |
1263 _("Color to draw hyperlinks."), | |
1264 GDK_TYPE_COLOR, G_PARAM_READABLE)); | |
10799 | 1265 gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-prelight-color", |
1266 _("Hyperlink prelight color"), | |
1267 _("Color to draw hyperlinks when mouse is over them."), | |
1268 GDK_TYPE_COLOR, G_PARAM_READABLE)); | |
10100 | 1269 |
1270 binding_set = gtk_binding_set_by_class (parent_class); | |
10110 | 1271 gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD); |
10100 | 1272 gtk_binding_entry_add_signal (binding_set, GDK_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC); |
1273 gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE); | |
1274 gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); | |
1275 gtk_binding_entry_add_signal (binding_set, GDK_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); | |
1276 gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK); | |
10108 | 1277 binding_set = gtk_binding_set_by_class(klass); |
11385
78cd70f4834c
[gaim-migrate @ 13612]
Luke Schierer <lschiere@pidgin.im>
parents:
11315
diff
changeset
|
1278 gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); |
10108 | 1279 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); |
1280 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); | |
1428 | 1281 } |
1282 | |
3922 | 1283 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 1284 { |
3922 | 1285 GtkTextIter iter; |
1286 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
1287 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
1288 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
5105 | 1289 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 1290 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
8677 | 1291 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); |
1292 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(imhtml), 2); | |
8061 | 1293 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
3922 | 1294 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
8061 | 1295 |
3922 | 1296 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
8932 | 1297 * other tags (color, size, face, etc.) will have to be created and applied dynamically |
9924 | 1298 * Note that even though we created SUB, SUP, and PRE tags here, we don't really |
8932 | 1299 * apply them anywhere yet. */ |
3922 | 1300 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); |
1301 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
1302 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
1303 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
1304 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
1305 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
1306 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
7295 | 1307 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
8677 | 1308 |
3922 | 1309 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
1310 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
1311 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
8061 | 1312 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
2993 | 1313 |
6124 | 1314 imhtml->show_comments = TRUE; |
4253 | 1315 |
4892 | 1316 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1317 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 1318 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 1319 |
4944 | 1320 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 1321 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 1322 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
10946
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
1323 g_signal_connect(G_OBJECT(imhtml), "enter-notify-event", G_CALLBACK(gtk_enter_event_notify), NULL); |
10844 | 1324 #if (!GTK_CHECK_VERSION(2,2,0)) |
1325 /* See the comment for gtk_key_pressed_cb */ | |
6066 | 1326 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
10844 | 1327 #endif |
8677 | 1328 g_signal_connect(G_OBJECT(imhtml), "button_press_event", G_CALLBACK(gtk_imhtml_button_press_event), NULL); |
1329 g_signal_connect(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(preinsert_cb), imhtml); | |
8061 | 1330 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
10169 | 1331 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-child-anchor", G_CALLBACK(insert_ca_cb), imhtml); |
8091 | 1332 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, |
1333 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | |
1334 GDK_ACTION_COPY); | |
1335 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | |
9300 | 1336 g_signal_connect(G_OBJECT(imhtml), "drag_drop", G_CALLBACK(gtk_imhtml_link_drop_cb), imhtml); |
8091 | 1337 |
7353 | 1338 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
8698 | 1339 g_signal_connect(G_OBJECT(imhtml), "cut-clipboard", G_CALLBACK(cut_clipboard_cb), NULL); |
8061 | 1340 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
8677 | 1341 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
|
1342 g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); |
8677 | 1343 |
1344 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
1345 G_CALLBACK(mark_set_so_update_selection_cb), imhtml); | |
1346 | |
10946
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
1347 gtk_widget_add_events(GTK_WIDGET(imhtml), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
1348 GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK); |
4735 | 1349 |
8681 | 1350 imhtml->clipboard_text_string = NULL; |
1351 imhtml->clipboard_html_string = NULL; | |
1352 | |
4735 | 1353 imhtml->tip = NULL; |
1354 imhtml->tip_timer = 0; | |
1355 imhtml->tip_window = NULL; | |
4895 | 1356 |
8677 | 1357 imhtml->edit.bold = FALSE; |
1358 imhtml->edit.italic = FALSE; | |
1359 imhtml->edit.underline = FALSE; | |
8061 | 1360 imhtml->edit.forecolor = NULL; |
1361 imhtml->edit.backcolor = NULL; | |
1362 imhtml->edit.fontface = NULL; | |
8677 | 1363 imhtml->edit.fontsize = 0; |
1364 imhtml->edit.link = NULL; | |
1365 | |
9300 | 1366 |
4895 | 1367 imhtml->scalables = NULL; |
8061 | 1368 |
1369 gtk_imhtml_set_editable(imhtml, FALSE); | |
8931 | 1370 g_signal_connect(G_OBJECT(imhtml), "populate-popup", |
1371 G_CALLBACK(hijack_menu_cb), NULL); | |
1372 | |
8692 | 1373 #ifdef _WIN32 |
1374 /* Register HTML Format as desired clipboard format */ | |
1375 win_html_fmt = RegisterClipboardFormat("HTML Format"); | |
1376 #endif | |
2993 | 1377 } |
1378 | |
3922 | 1379 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 1380 { |
4635 | 1381 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 1382 } |
1383 | |
9037 | 1384 GType gtk_imhtml_get_type() |
1428 | 1385 { |
9037 | 1386 static GType imhtml_type = 0; |
1428 | 1387 |
1388 if (!imhtml_type) { | |
9037 | 1389 static const GTypeInfo imhtml_info = { |
4635 | 1390 sizeof(GtkIMHtmlClass), |
1391 NULL, | |
1392 NULL, | |
1393 (GClassInitFunc) gtk_imhtml_class_init, | |
1394 NULL, | |
1395 NULL, | |
1428 | 1396 sizeof (GtkIMHtml), |
4635 | 1397 0, |
1398 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 1399 }; |
4635 | 1400 |
1401 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
1402 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 1403 } |
1404 | |
1405 return imhtml_type; | |
1406 } | |
1407 | |
4417 | 1408 struct url_data { |
1409 GObject *object; | |
1410 gchar *url; | |
1411 }; | |
1412 | |
8677 | 1413 static void url_data_destroy(gpointer mydata) |
1414 { | |
1415 struct url_data *data = mydata; | |
1416 g_object_unref(data->object); | |
1417 g_free(data->url); | |
1418 g_free(data); | |
1419 } | |
1420 | |
4417 | 1421 static void url_open(GtkWidget *w, struct url_data *data) { |
1422 if(!data) return; | |
8061 | 1423 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
7988 | 1424 |
4417 | 1425 } |
5582 | 1426 |
4417 | 1427 static void url_copy(GtkWidget *w, gchar *url) { |
1428 GtkClipboard *clipboard; | |
1429 | |
8931 | 1430 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY); |
4417 | 1431 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 1432 |
8931 | 1433 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_CLIPBOARD); |
5582 | 1434 gtk_clipboard_set_text(clipboard, url, -1); |
4417 | 1435 } |
1436 | |
1437 /* The callback for an event on a link tag. */ | |
10871 | 1438 static gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) { |
4417 | 1439 GdkEventButton *event_button = (GdkEventButton *) event; |
8061 | 1440 if (GTK_IMHTML(imhtml)->editable) |
1441 return FALSE; | |
3922 | 1442 if (event->type == GDK_BUTTON_RELEASE) { |
8957 | 1443 if ((event_button->button == 1) || (event_button->button == 2)) { |
4417 | 1444 GtkTextIter start, end; |
1445 /* we shouldn't open a URL if the user has selected something: */ | |
8677 | 1446 if (gtk_text_buffer_get_selection_bounds( |
1447 gtk_text_iter_get_buffer(arg2), &start, &end)) | |
4417 | 1448 return FALSE; |
1449 | |
1450 /* A link was clicked--we emit the "url_clicked" signal | |
1451 * with the URL as the argument */ | |
8677 | 1452 g_object_ref(G_OBJECT(tag)); |
1453 g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url")); | |
1454 g_object_unref(G_OBJECT(tag)); | |
4417 | 1455 return FALSE; |
1456 } else if(event_button->button == 3) { | |
4745 | 1457 GtkWidget *img, *item, *menu; |
4417 | 1458 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 1459 tempdata->object = g_object_ref(imhtml); |
8677 | 1460 tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url")); |
4745 | 1461 |
5091 | 1462 /* Don't want the tooltip around if user right-clicked on link */ |
1463 if (GTK_IMHTML(imhtml)->tip_window) { | |
1464 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
1465 GTK_IMHTML(imhtml)->tip_window = NULL; | |
1466 } | |
1467 if (GTK_IMHTML(imhtml)->tip_timer) { | |
1468 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
1469 GTK_IMHTML(imhtml)->tip_timer = 0; | |
1470 } | |
8061 | 1471 if (GTK_IMHTML(imhtml)->editable) |
1472 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | |
1473 else | |
1474 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 1475 menu = gtk_menu_new(); |
8677 | 1476 g_object_set_data_full(G_OBJECT(menu), "x-imhtml-url-data", tempdata, url_data_destroy); |
4745 | 1477 |
4417 | 1478 /* buttons and such */ |
1479 | |
8677 | 1480 if (!strncmp(tempdata->url, "mailto:", 7)) |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1481 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1482 /* Copy E-Mail Address */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1483 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1484 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1485 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1486 _("_Copy E-Mail Address")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1487 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
|
1488 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1489 G_CALLBACK(url_copy), tempdata->url + 7); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1490 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1491 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1492 else |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1493 { |
10936 | 1494 /* Open Link in Browser */ |
1495 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, | |
1496 GTK_ICON_SIZE_MENU); | |
1497 item = gtk_image_menu_item_new_with_mnemonic( | |
1498 _("_Open Link in Browser")); | |
1499 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
1500 g_signal_connect(G_OBJECT(item), "activate", | |
1501 G_CALLBACK(url_open), tempdata); | |
1502 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
1503 | |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1504 /* Copy Link Location */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1505 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1506 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1507 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1508 _("_Copy Link Location")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1509 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
|
1510 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1511 G_CALLBACK(url_copy), tempdata->url); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1512 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1513 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1514 |
4756 | 1515 |
4417 | 1516 gtk_widget_show_all(menu); |
4756 | 1517 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
1518 event_button->button, event_button->time); | |
4745 | 1519 |
4417 | 1520 return TRUE; |
1521 } | |
1428 | 1522 } |
4417 | 1523 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
1524 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1525 be caught by the regular GtkTextView menu */ | |
1526 else | |
1527 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 1528 } |
1529 | |
9300 | 1530 static gboolean |
1531 gtk_text_view_drag_motion (GtkWidget *widget, | |
1532 GdkDragContext *context, | |
1533 gint x, | |
1534 gint y, | |
1535 guint time) | |
1536 { | |
1537 GdkDragAction suggested_action = 0; | |
1538 | |
10145 | 1539 if (gtk_drag_dest_find_target (widget, context, NULL) == GDK_NONE) { |
9300 | 1540 /* can't accept any of the offered targets */ |
1541 } else { | |
1542 GtkWidget *source_widget; | |
1543 suggested_action = context->suggested_action; | |
1544 source_widget = gtk_drag_get_source_widget (context); | |
1545 if (source_widget == widget) { | |
1546 /* Default to MOVE, unless the user has | |
1547 * pressed ctrl or alt to affect available actions | |
1548 */ | |
1549 if ((context->actions & GDK_ACTION_MOVE) != 0) | |
1550 suggested_action = GDK_ACTION_MOVE; | |
1551 } | |
1552 } | |
1553 | |
10145 | 1554 gdk_drag_status (context, suggested_action, time); |
9300 | 1555 |
1556 /* TRUE return means don't propagate the drag motion to parent | |
1557 * widgets that may also be drop sites. | |
1558 */ | |
1559 return TRUE; | |
1560 } | |
1561 | |
1562 static void | |
1563 gtk_imhtml_link_drop_cb(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data) | |
1564 { | |
1565 GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL); | |
1566 | |
1567 if (target != GDK_NONE) | |
1568 gtk_drag_get_data (widget, context, target, time); | |
1569 else | |
1570 gtk_drag_finish (context, FALSE, FALSE, time); | |
1571 | |
1572 return; | |
1573 } | |
1574 | |
8091 | 1575 static void |
1576 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
11143 | 1577 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) |
8091 | 1578 { |
9300 | 1579 gchar **links; |
1580 gchar *link; | |
11143 | 1581 char *text = (char *)sd->data; |
9300 | 1582 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); |
1583 GtkTextIter iter; | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1584 gint i = 0; |
9300 | 1585 |
1586 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
1587 | |
8091 | 1588 if(gtk_imhtml_get_editable(imhtml) && sd->data){ |
9300 | 1589 switch (info) { |
10145 | 1590 case GTK_IMHTML_DRAG_URL: |
11143 | 1591 /* TODO: Is it really ok to change sd->data...? */ |
1592 gaim_str_strip_cr((char *)sd->data); | |
1593 | |
1594 links = g_strsplit((char *)sd->data, "\n", 0); | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1595 while((link = links[i]) != NULL){ |
9300 | 1596 if(gaim_str_has_prefix(link, "http://") || |
1597 gaim_str_has_prefix(link, "https://") || | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1598 gaim_str_has_prefix(link, "ftp://")) |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1599 { |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1600 gchar *label; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1601 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1602 if(links[i + 1]) |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1603 i++; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1604 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1605 label = links[i]; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1606 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1607 gtk_imhtml_insert_link(imhtml, mark, link, label); |
9300 | 1608 } else if (link=='\0') { |
1609 /* Ignore blank lines */ | |
1610 } else { | |
1611 /* Special reasons, aka images being put in via other tag, etc. */ | |
10345 | 1612 /* ... don't pretend we handled it if we didn't */ |
1613 gtk_drag_finish(dc, FALSE, FALSE, t); | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1614 g_strfreev(links); |
10345 | 1615 return; |
9300 | 1616 } |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1617 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1618 i++; |
8091 | 1619 } |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1620 g_strfreev(links); |
9300 | 1621 break; |
10145 | 1622 case GTK_IMHTML_DRAG_HTML: |
10243 | 1623 { |
1624 char *utf8 = NULL; | |
1625 /* Ewww. This is all because mozilla thinks that text/html is 'for internal use only.' | |
1626 * as explained by this comment in gtkhtml: | |
1627 * | |
1628 * FIXME This hack decides the charset of the selection. It seems that | |
1629 * mozilla/netscape alway use ucs2 for text/html | |
1630 * and openoffice.org seems to always use utf8 so we try to validate | |
1631 * the string as utf8 and if that fails we assume it is ucs2 | |
1632 * | |
1633 * See also the comment on text/html here: | |
1634 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html | |
1635 */ | |
1636 if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) { | |
1637 utf8 = g_convert(text, sd->length, "UTF-8", "UCS-2", NULL, NULL, NULL); | |
1638 | |
1639 if (!utf8) { | |
9300 | 1640 gaim_debug_warning("gtkimhtml", "g_convert from UCS-2 failed in drag_rcv_cb\n"); |
1641 return; | |
1642 } | |
10243 | 1643 |
1644 if (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe || TRUE) { | |
1645 char *tmp; | |
1646 tmp = g_utf8_next_char(utf8); | |
1647 memmove(utf8, tmp, strlen(tmp) + 1); | |
1648 } | |
1649 } else if (!(*text) || !g_utf8_validate(text, -1, NULL)) { | |
9300 | 1650 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in drag_rcv_cb\n"); |
1651 return; | |
1652 } | |
10243 | 1653 |
1654 gtk_imhtml_insert_html_at_iter(imhtml, utf8 ? utf8 : text, 0, &iter); | |
1655 g_free(utf8); | |
9300 | 1656 break; |
10243 | 1657 } |
10145 | 1658 case GTK_IMHTML_DRAG_TEXT: |
1659 if (!(*text) || !g_utf8_validate(text, -1, NULL)) { | |
1660 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in drag_rcv_cb\n"); | |
1661 return; | |
1662 } else { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10699
diff
changeset
|
1663 char *tmp = g_markup_escape_text(text, -1); |
10145 | 1664 gtk_imhtml_insert_html_at_iter(imhtml, tmp, 0, &iter); |
1665 g_free(tmp); | |
1666 } | |
1667 break; | |
9300 | 1668 default: |
10145 | 1669 gtk_drag_finish(dc, FALSE, FALSE, t); |
1670 return; | |
8091 | 1671 } |
1672 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1673 } else { | |
1674 gtk_drag_finish(dc, FALSE, FALSE, t); | |
1675 } | |
1676 } | |
1677 | |
4298 | 1678 /* this isn't used yet |
9300 | 1679 static void gtk_smiley_tree_remove (GtkSmileyTree *tree, |
4263 | 1680 GtkIMHtmlSmiley *smiley) |
4032 | 1681 { |
1682 GtkSmileyTree *t = tree; | |
4263 | 1683 const gchar *x = smiley->smile; |
4032 | 1684 gint len = 0; |
1685 | |
1686 while (*x) { | |
1687 gchar *pos; | |
1688 | |
1689 if (!t->values) | |
1690 return; | |
1691 | |
1692 pos = strchr (t->values->str, *x); | |
1693 if (pos) | |
1694 t = t->children [(int) pos - (int) t->values->str]; | |
1695 else | |
1696 return; | |
1697 | |
1698 x++; len++; | |
1699 } | |
1700 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1701 if (t->image) { |
4032 | 1702 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1703 } |
4032 | 1704 } |
4298 | 1705 */ |
1706 | |
4032 | 1707 |
1708 static gint | |
1709 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
1710 const gchar *text) | |
1711 { | |
1712 GtkSmileyTree *t = tree; | |
1713 const gchar *x = text; | |
1714 gint len = 0; | |
8505 | 1715 gchar *amp; |
1716 gint alen; | |
4032 | 1717 |
1718 while (*x) { | |
1719 gchar *pos; | |
1720 | |
1721 if (!t->values) | |
1722 break; | |
1723 | |
8505 | 1724 if(*x == '&' && gtk_imhtml_is_amp_escape(x, &, &alen)) { |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1725 gboolean matched = TRUE; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1726 /* Make sure all chars of the unescaped value match */ |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1727 while (*(amp + 1)) { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1728 pos = strchr (t->values->str, *amp); |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1729 if (pos) |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1730 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1731 else { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1732 matched = FALSE; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1733 break; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1734 } |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1735 amp++; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1736 } |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1737 if (!matched) |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1738 break; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1739 |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1740 pos = strchr (t->values->str, *amp); |
8505 | 1741 } |
9636 | 1742 else if (*x == '<') /* Because we're all WYSIWYG now, a '<' |
1743 * char should only appear as the start of a tag. Perhaps a safer (but costlier) | |
1744 * check would be to call gtk_imhtml_is_tag on it */ | |
10600 | 1745 break; |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1746 else { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1747 alen = 1; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1748 pos = strchr (t->values->str, *x); |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1749 } |
8505 | 1750 |
4032 | 1751 if (pos) |
7371 | 1752 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1753 else |
1754 break; | |
1755 | |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1756 x += alen; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1757 len += alen; |
4032 | 1758 } |
1759 | |
1760 if (t->image) | |
1761 return len; | |
1762 | |
1763 return 0; | |
1764 } | |
1765 | |
1766 void | |
4263 | 1767 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
10537 | 1768 const gchar *sml, |
4263 | 1769 GtkIMHtmlSmiley *smiley) |
4032 | 1770 { |
1771 GtkSmileyTree *tree; | |
1772 g_return_if_fail (imhtml != NULL); | |
1773 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
7371 | 1774 |
4032 | 1775 if (sml == NULL) |
1776 tree = imhtml->default_smilies; | |
1777 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
1778 } else { | |
1779 tree = gtk_smiley_tree_new(); | |
4892 | 1780 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 1781 } |
1782 | |
4263 | 1783 gtk_smiley_tree_insert (tree, smiley); |
4032 | 1784 } |
1785 | |
1786 static gboolean | |
1787 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
1788 GSList *fonts, | |
1789 const gchar *text, | |
1790 gint *len) | |
1791 { | |
1792 GtkSmileyTree *tree; | |
5967 | 1793 GtkIMHtmlFontDetail *font; |
4032 | 1794 char *sml = NULL; |
1795 | |
1796 if (fonts) { | |
1797 font = fonts->data; | |
1798 sml = font->sml; | |
1799 } | |
1800 | |
9029 | 1801 if (!sml) |
1802 sml = imhtml->protocol_name; | |
1803 | |
1804 if (!sml || !(tree = g_hash_table_lookup(imhtml->smiley_data, sml))) | |
4032 | 1805 tree = imhtml->default_smilies; |
9029 | 1806 |
4032 | 1807 if (tree == NULL) |
1808 return FALSE; | |
7371 | 1809 |
8505 | 1810 *len = gtk_smiley_tree_lookup (tree, text); |
4032 | 1811 return (*len > 0); |
1812 } | |
1813 | |
10526 | 1814 GtkIMHtmlSmiley * |
1815 gtk_imhtml_smiley_get(GtkIMHtml *imhtml, | |
1816 const gchar *sml, | |
1817 const gchar *text) | |
4032 | 1818 { |
1819 GtkSmileyTree *t; | |
1820 const gchar *x = text; | |
1821 if (sml == NULL) | |
1822 t = imhtml->default_smilies; | |
7371 | 1823 else |
4032 | 1824 t = g_hash_table_lookup(imhtml->smiley_data, sml); |
7371 | 1825 |
4032 | 1826 |
1827 if (t == NULL) | |
10526 | 1828 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1829 |
1830 while (*x) { | |
1831 gchar *pos; | |
1832 | |
1833 if (!t->values) { | |
10526 | 1834 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1835 } |
7371 | 1836 |
4032 | 1837 pos = strchr (t->values->str, *x); |
1838 if (pos) { | |
7371 | 1839 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1840 } else { |
10526 | 1841 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1842 } |
1843 x++; | |
1844 } | |
1845 | |
10526 | 1846 return t->image; |
1847 } | |
1848 | |
1849 GdkPixbufAnimation * | |
1850 gtk_smiley_tree_image (GtkIMHtml *imhtml, | |
1851 const gchar *sml, | |
1852 const gchar *text) | |
1853 { | |
1854 | |
1855 GtkIMHtmlSmiley *smiley; | |
1856 | |
1857 smiley = gtk_imhtml_smiley_get(imhtml,sml,text); | |
1858 | |
1859 if (!smiley) | |
8890 | 1860 return NULL; |
1861 | |
10526 | 1862 if (!smiley->icon && smiley->file) { |
1863 smiley->icon = gdk_pixbuf_animation_new_from_file(smiley->file, NULL); | |
1864 } else if (!smiley->icon && smiley->loader) { | |
1865 smiley->icon = gdk_pixbuf_loader_get_animation(smiley->loader); | |
1866 if (smiley->icon) | |
1867 g_object_ref(G_OBJECT(smiley->icon)); | |
1868 } | |
1869 | |
1870 return smiley->icon; | |
4032 | 1871 } |
8890 | 1872 |
4793 | 1873 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 1874 *tag = g_strndup (string, strlen (x)); \ |
1875 *len = strlen (x) + 1; \ | |
1876 return TRUE; \ | |
1877 } \ | |
1878 (*type)++ | |
1428 | 1879 |
4793 | 1880 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 1881 const gchar *c = string + strlen (x " "); \ |
1882 gchar e = '"'; \ | |
1883 gboolean quote = FALSE; \ | |
1884 while (*c) { \ | |
1885 if (*c == '"' || *c == '\'') { \ | |
1886 if (quote && (*c == e)) \ | |
1887 quote = !quote; \ | |
1888 else if (!quote) { \ | |
1889 quote = !quote; \ | |
1890 e = *c; \ | |
1891 } \ | |
1892 } else if (!quote && (*c == '>')) \ | |
1893 break; \ | |
1894 c++; \ | |
1895 } \ | |
1896 if (*c) { \ | |
1897 *tag = g_strndup (string, c - string); \ | |
1898 *len = c - string + 1; \ | |
1899 return TRUE; \ | |
1900 } \ | |
1901 } \ | |
1902 (*type)++ | |
1428 | 1903 |
1904 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1905 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1906 gtk_imhtml_is_amp_escape (const gchar *string, |
7280 | 1907 gchar **replace, |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1908 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1909 { |
7287 | 1910 static char buf[7]; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1911 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1912 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1913 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1914 |
4793 | 1915 if (!g_ascii_strncasecmp (string, "&", 5)) { |
7280 | 1916 *replace = "&"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1917 *length = 5; |
4793 | 1918 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
7280 | 1919 *replace = "<"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1920 *length = 4; |
4793 | 1921 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
7280 | 1922 *replace = ">"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1923 *length = 4; |
4793 | 1924 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
7280 | 1925 *replace = " "; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1926 *length = 6; |
4793 | 1927 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
7280 | 1928 *replace = "©"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1929 *length = 6; |
4793 | 1930 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
7280 | 1931 *replace = "\""; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1932 *length = 6; |
4793 | 1933 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
7280 | 1934 *replace = "®"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1935 *length = 5; |
5093 | 1936 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
7280 | 1937 *replace = "\'"; |
5093 | 1938 *length = 6; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1939 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
1940 guint pound = 0; |
3004 | 1941 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
7287 | 1942 int buflen; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1943 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1944 return FALSE; |
7287 | 1945 buflen = g_unichar_to_utf8((gunichar)pound, buf); |
1946 buf[buflen] = '\0'; | |
7280 | 1947 *replace = buf; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1948 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1949 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1950 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1951 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1952 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1953 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1954 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1955 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1956 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1957 |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1958 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1959 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1960 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1961 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1962 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1963 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1964 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1965 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1966 { |
8061 | 1967 char *close; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1968 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1969 |
8118 | 1970 |
8061 | 1971 if (!(close = strchr (string, '>'))) |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1972 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1973 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1974 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1975 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1976 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1977 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1978 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1979 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1980 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1981 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1982 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1983 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1984 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1985 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1986 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1987 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1988 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1989 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1990 VALID_TAG ("SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1991 VALID_TAG ("/SUB"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1992 VALID_TAG ("SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1993 VALID_TAG ("/SUP"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1994 VALID_TAG ("PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1995 VALID_TAG ("/PRE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1996 VALID_TAG ("TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1997 VALID_TAG ("/TITLE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1998 VALID_TAG ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1999 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2000 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2001 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2002 VALID_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2003 VALID_TAG ("/P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2004 VALID_TAG ("H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2005 VALID_TAG ("/H3"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2006 VALID_TAG ("HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2007 VALID_TAG ("/HTML"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2008 VALID_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2009 VALID_TAG ("/BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2010 VALID_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2011 VALID_TAG ("HEAD"); |
2993 | 2012 VALID_TAG ("/HEAD"); |
2013 VALID_TAG ("BINARY"); | |
2014 VALID_TAG ("/BINARY"); | |
5093 | 2015 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2016 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2017 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2018 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2019 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2020 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2021 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2022 VALID_OPT_TAG ("H3"); |
5093 | 2023 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2024 |
5101 | 2025 VALID_TAG ("CITE"); |
2026 VALID_TAG ("/CITE"); | |
2027 VALID_TAG ("EM"); | |
2028 VALID_TAG ("/EM"); | |
2029 VALID_TAG ("STRONG"); | |
2030 VALID_TAG ("/STRONG"); | |
2031 | |
5104 | 2032 VALID_OPT_TAG ("SPAN"); |
2033 VALID_TAG ("/SPAN"); | |
5174 | 2034 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
6982 | 2035 VALID_TAG ("IMG"); |
8026 | 2036 VALID_TAG("SPAN"); |
8061 | 2037 VALID_OPT_TAG("BR"); |
7988 | 2038 |
4793 | 2039 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
2040 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2041 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2042 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2043 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2044 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2045 } |
8118 | 2046 } |
2047 | |
8061 | 2048 *type = -1; |
2049 *len = close - string + 1; | |
2050 *tag = g_strndup(string, *len - 1); | |
2051 return TRUE; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2052 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2053 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2054 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2055 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2056 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2057 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2058 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2059 gchar *e, *a; |
5177 | 2060 gchar *val; |
2061 gint len; | |
7280 | 2062 gchar *c; |
5177 | 2063 GString *ret; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2064 |
4793 | 2065 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2066 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2067 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2068 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2069 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2070 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2071 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2072 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2073 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2074 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2075 |
4793 | 2076 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2077 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2078 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2079 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2080 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2081 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2082 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2083 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2084 while (*e && (*e != *(t - 1))) e++; |
2993 | 2085 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2086 return NULL; |
5177 | 2087 } else |
2088 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2089 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2090 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2091 while (*e && !isspace ((gint) *e)) e++; |
5177 | 2092 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2093 } |
5177 | 2094 |
2095 ret = g_string_new(""); | |
2096 e = val; | |
2097 while(*e) { | |
2098 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
7280 | 2099 ret = g_string_append(ret, c); |
5177 | 2100 e += len; |
2101 } else { | |
2102 ret = g_string_append_c(ret, *e); | |
2103 e++; | |
2104 } | |
2105 } | |
2106 | |
2107 g_free(val); | |
8568 | 2108 |
2109 return g_string_free(ret, FALSE); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2110 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2111 |
8118 | 2112 /* Inline CSS Support - Douglas Thrift */ |
2113 static gchar* | |
2114 gtk_imhtml_get_css_opt (gchar *style, | |
2115 const gchar *opt) | |
2116 { | |
2117 gchar *t = style; | |
2118 gchar *e, *a; | |
2119 gchar *val; | |
2120 gint len; | |
2121 gchar *c; | |
2122 GString *ret; | |
2123 | |
2124 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
8177 | 2125 /* gboolean quote = FALSE; */ |
8118 | 2126 if (*t == '\0') break; |
2127 while (*t && !((*t == ' ') /*&& !quote*/)) { | |
2128 /* if (*t == '\"') | |
8177 | 2129 quote = ! quote; */ |
8118 | 2130 t++; |
2131 } | |
2132 while (*t && (*t == ' ')) t++; | |
2133 } | |
2134 | |
2135 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
2136 t += strlen (opt); | |
10457 | 2137 while (*t && (*t == ' ')) t++; |
2138 if (!*t) | |
2139 return NULL; | |
8118 | 2140 } else { |
2141 return NULL; | |
2142 } | |
2143 | |
2144 /* if ((*t == '\"') || (*t == '\'')) { | |
2145 e = a = ++t; | |
2146 while (*e && (*e != *(t - 1))) e++; | |
2147 if (*e == '\0') { | |
2148 return NULL; | |
2149 } else | |
2150 val = g_strndup(a, e - a); | |
2151 } else { | |
2152 e = a = t; | |
2153 while (*e && !isspace ((gint) *e)) e++; | |
2154 val = g_strndup(a, e - a); | |
2155 }*/ | |
2156 | |
2157 e = a = t; | |
2158 while (*e && *e != ';') e++; | |
2159 val = g_strndup(a, e - a); | |
2160 | |
2161 ret = g_string_new(""); | |
2162 e = val; | |
2163 while(*e) { | |
2164 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
2165 ret = g_string_append(ret, c); | |
2166 e += len; | |
2167 } else { | |
2168 ret = g_string_append_c(ret, *e); | |
2169 e++; | |
2170 } | |
2171 } | |
2172 | |
2173 g_free(val); | |
2174 val = ret->str; | |
2175 g_string_free(ret, FALSE); | |
2176 return val; | |
2177 } | |
3922 | 2178 |
8334 | 2179 static const char *accepted_protocols[] = { |
2180 "http://", | |
2181 "https://", | |
2182 "ftp://" | |
2183 }; | |
2184 | |
2185 static const int accepted_protocols_size = 3; | |
2186 | |
2187 /* returns if the beginning of the text is a protocol. If it is the protocol, returns the length so | |
2188 the caller knows how long the protocol string is. */ | |
2189 int gtk_imhtml_is_protocol(const char *text) | |
2190 { | |
2191 gint i; | |
2192 | |
2193 for(i=0; i<accepted_protocols_size; i++){ | |
2194 if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ | |
2195 return strlen(accepted_protocols[i]); | |
2196 } | |
2197 } | |
2198 return 0; | |
2199 } | |
2200 | |
8677 | 2201 /* |
2202 <KingAnt> marv: The two IM image functions in oscar are gaim_odc_send_im and gaim_odc_incoming | |
2203 | |
2204 | |
2205 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) | |
2206 [19:59] <KingAnt> marv: I think the image tag used by the core is something like <img id="#"/> | |
2207 [19:59] Ro0tSiEgE robert42 RobFlynn Robot101 ross22 roz | |
2208 [20:00] <KingAnt> marv: Where the ID is the what is returned when you add the image to the imgstore using gaim_imgstore_add | |
2209 [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? | |
2210 [20:00] <KingAnt> marv: Right | |
2211 [20:00] <marv> alright | |
2212 | |
2213 Here's my plan with IMImages. make gtk_imhtml_[append|insert]_text_with_images instead just | |
2214 gtkimhtml_[append|insert]_text (hrm maybe it should be called html instead of text), add a | |
2215 function for gaim to register for look up images, i.e. gtk_imhtml_set_get_img_fnc, so that | |
2216 images can be looked up like that, instead of passing a GSList of them. | |
2217 */ | |
2218 | |
2219 void gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | |
2220 const gchar *text, | |
2221 GtkIMHtmlOptions options, | |
2222 GSList *unused) | |
1428 | 2223 { |
8677 | 2224 GtkTextIter iter, ins, sel; |
2225 GdkRectangle rect; | |
2226 int y, height, ins_offset = 0, sel_offset = 0; | |
2227 gboolean fixins = FALSE, fixsel = FALSE; | |
2228 | |
2229 g_return_if_fail (imhtml != NULL); | |
2230 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
2231 g_return_if_fail (text != NULL); | |
2232 | |
2233 | |
2234 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
2235 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
2236 if (gtk_text_iter_equal(&iter, &ins) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
2237 fixins = TRUE; | |
2238 ins_offset = gtk_text_iter_get_offset(&ins); | |
2239 } | |
2240 | |
2241 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &sel, gtk_text_buffer_get_selection_bound(imhtml->text_buffer)); | |
2242 if (gtk_text_iter_equal(&iter, &sel) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
2243 fixsel = TRUE; | |
2244 sel_offset = gtk_text_iter_get_offset(&sel); | |
2245 } | |
2246 | |
2247 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
2248 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
2249 | |
2250 | |
2251 if(((y + height) - (rect.y + rect.height)) > height | |
2252 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
2253 options |= GTK_IMHTML_NO_SCROLL; | |
2254 } | |
2255 | |
2256 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); | |
2257 | |
2258 if (fixins) { | |
2259 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins, ins_offset); | |
2260 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_insert(imhtml->text_buffer), &ins); | |
2261 } | |
2262 | |
2263 if (fixsel) { | |
2264 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &sel, sel_offset); | |
2265 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_selection_bound(imhtml->text_buffer), &sel); | |
2266 } | |
2267 | |
2268 if (!(options & GTK_IMHTML_NO_SCROLL)) { | |
8729 | 2269 gtk_imhtml_scroll_to_end(imhtml); |
8677 | 2270 } |
2271 } | |
2272 | |
11006 | 2273 #define MAX_SCROLL_TIME 0.4 /* seconds */ |
2274 #define SCROLL_DELAY 33 /* milliseconds */ | |
2275 | |
2276 /* | |
2277 * Smoothly scroll a GtkIMHtml. | |
2278 * | |
2279 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. | |
2280 */ | |
10871 | 2281 static gboolean scroll_cb(gpointer data) |
10798 | 2282 { |
2283 GtkIMHtml *imhtml = data; | |
2284 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; | |
11006 | 2285 gdouble max_val = adj->upper - adj->page_size; |
2286 | |
2287 g_return_val_if_fail(imhtml->scroll_time != NULL, FALSE); | |
2288 | |
2289 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME) { | |
2290 /* time's up. jump to the end and kill the timer */ | |
2291 gtk_adjustment_set_value(adj, max_val); | |
10798 | 2292 g_timer_destroy(imhtml->scroll_time); |
2293 imhtml->scroll_time = NULL; | |
2294 return FALSE; | |
11006 | 2295 } |
2296 | |
2297 /* scroll by 1/3rd the remaining distance */ | |
2298 gtk_adjustment_set_value(adj, gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3)); | |
2299 return TRUE; | |
10798 | 2300 } |
2301 | |
10871 | 2302 static gboolean scroll_idle_cb(gpointer data) |
10797 | 2303 { |
10798 | 2304 GtkIMHtml *imhtml = data; |
11006 | 2305 imhtml->scroll_src = g_timeout_add(SCROLL_DELAY, scroll_cb, imhtml); |
10797 | 2306 return FALSE; |
2307 } | |
2308 | |
8729 | 2309 void gtk_imhtml_scroll_to_end(GtkIMHtml *imhtml) |
2310 { | |
10798 | 2311 if (imhtml->scroll_time) |
2312 g_timer_destroy(imhtml->scroll_time); | |
2313 imhtml->scroll_time = g_timer_new(); | |
2314 if (imhtml->scroll_src) | |
2315 g_source_remove(imhtml->scroll_src); | |
2316 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); | |
8729 | 2317 } |
2318 | |
8677 | 2319 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, |
2320 const gchar *text, | |
2321 GtkIMHtmlOptions options, | |
2322 GtkTextIter *iter) | |
2323 { | |
8061 | 2324 GdkRectangle rect; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2325 gint pos = 0; |
3922 | 2326 gchar *ws; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2327 gchar *tag; |
3922 | 2328 gchar *bg = NULL; |
6982 | 2329 gint len; |
4032 | 2330 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2331 gint type; |
3922 | 2332 const gchar *c; |
7280 | 2333 gchar *amp; |
8334 | 2334 gint len_protocol; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2335 |
1428 | 2336 guint bold = 0, |
2337 italics = 0, | |
2338 underline = 0, | |
2339 strike = 0, | |
2340 sub = 0, | |
2341 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2342 title = 0, |
8061 | 2343 pre = 0; |
1428 | 2344 |
10217 | 2345 gboolean br = FALSE; |
2346 | |
3922 | 2347 GSList *fonts = NULL; |
8506 | 2348 GObject *object; |
8061 | 2349 GtkIMHtmlScalable *scalable = NULL; |
8677 | 2350 |
2351 g_return_if_fail (imhtml != NULL); | |
2352 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
2353 g_return_if_fail (text != NULL); | |
3922 | 2354 c = text; |
6982 | 2355 len = strlen(text); |
3922 | 2356 ws = g_malloc(len + 1); |
2357 ws[0] = 0; | |
1428 | 2358 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2359 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2360 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2361 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2362 pos++; |
8061 | 2363 ws[wpos] = '\0'; |
10217 | 2364 br = FALSE; |
8061 | 2365 switch (type) |
3922 | 2366 { |
2367 case 1: /* B */ | |
2368 case 2: /* BOLD */ | |
5101 | 2369 case 54: /* STRONG */ |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2370 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2371 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2372 |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2373 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD)) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2374 gtk_imhtml_toggle_bold(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2375 bold++; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2376 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2377 } |
3922 | 2378 break; |
2379 case 3: /* /B */ | |
2380 case 4: /* /BOLD */ | |
5101 | 2381 case 55: /* /STRONG */ |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2382 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2383 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2384 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2385 |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2386 if (bold) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2387 bold--; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2388 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD) && !imhtml->wbfo) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2389 gtk_imhtml_toggle_bold(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2390 } |
3922 | 2391 break; |
2392 case 5: /* I */ | |
2393 case 6: /* ITALIC */ | |
5101 | 2394 case 52: /* EM */ |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2395 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2396 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2397 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2398 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC)) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2399 gtk_imhtml_toggle_italic(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2400 italics++; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2401 } |
3922 | 2402 break; |
2403 case 7: /* /I */ | |
2404 case 8: /* /ITALIC */ | |
5101 | 2405 case 53: /* /EM */ |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2406 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2407 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2408 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2409 if (italics) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2410 italics--; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2411 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC) && !imhtml->wbfo) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2412 gtk_imhtml_toggle_italic(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2413 } |
3922 | 2414 break; |
2415 case 9: /* U */ | |
2416 case 10: /* UNDERLINE */ | |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2417 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2418 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2419 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2420 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2421 gtk_imhtml_toggle_underline(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2422 underline++; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2423 } |
3922 | 2424 break; |
2425 case 11: /* /U */ | |
2426 case 12: /* /UNDERLINE */ | |
11485
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2427 if (!(options & GTK_IMHTML_NO_FORMATTING)) { |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2428 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2429 ws[0] = '\0'; wpos = 0; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2430 if (underline) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2431 underline--; |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2432 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE) && !imhtml->wbfo) |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2433 gtk_imhtml_toggle_underline(imhtml); |
16b0da1f376f
[gaim-migrate @ 13727]
Richard Laager <rlaager@wiktel.com>
parents:
11385
diff
changeset
|
2434 } |
3922 | 2435 break; |
2436 case 13: /* S */ | |
2437 case 14: /* STRIKE */ | |
9924 | 2438 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2439 ws[0] = '\0'; wpos = 0; | |
2440 if ((strike == 0) && (imhtml->format_functions & GTK_IMHTML_STRIKE)) | |
2441 gtk_imhtml_toggle_strike(imhtml); | |
3922 | 2442 strike++; |
2443 break; | |
2444 case 15: /* /S */ | |
2445 case 16: /* /STRIKE */ | |
9924 | 2446 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2447 ws[0] = '\0'; wpos = 0; | |
3922 | 2448 if (strike) |
2449 strike--; | |
9924 | 2450 if ((strike == 0) && (imhtml->format_functions & GTK_IMHTML_STRIKE) && !imhtml->wbfo) |
2451 gtk_imhtml_toggle_strike(imhtml); | |
3922 | 2452 break; |
2453 case 17: /* SUB */ | |
8677 | 2454 /* FIXME: reimpliment this */ |
3922 | 2455 sub++; |
2456 break; | |
2457 case 18: /* /SUB */ | |
8677 | 2458 /* FIXME: reimpliment this */ |
3922 | 2459 if (sub) |
2460 sub--; | |
2461 break; | |
2462 case 19: /* SUP */ | |
8677 | 2463 /* FIXME: reimplement this */ |
3922 | 2464 sup++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2465 break; |
3922 | 2466 case 20: /* /SUP */ |
8677 | 2467 /* FIXME: reimplement this */ |
3922 | 2468 if (sup) |
2469 sup--; | |
2470 break; | |
2471 case 21: /* PRE */ | |
8677 | 2472 /* FIXME: reimplement this */ |
3922 | 2473 pre++; |
2474 break; | |
2475 case 22: /* /PRE */ | |
8677 | 2476 /* FIXME: reimplement this */ |
3922 | 2477 if (pre) |
2478 pre--; | |
2479 break; | |
2480 case 23: /* TITLE */ | |
8677 | 2481 /* FIXME: what was this supposed to do anyway? */ |
3922 | 2482 title++; |
2483 break; | |
2484 case 24: /* /TITLE */ | |
8677 | 2485 /* FIXME: make this undo whatever 23 was supposed to do */ |
3922 | 2486 if (title) { |
2487 if (options & GTK_IMHTML_NO_TITLE) { | |
2488 wpos = 0; | |
2489 ws [wpos] = '\0'; | |
2490 } | |
2491 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2492 } |
3922 | 2493 break; |
2494 case 25: /* BR */ | |
5174 | 2495 case 58: /* BR/ */ |
8061 | 2496 case 61: /* BR (opt) */ |
3922 | 2497 ws[wpos] = '\n'; |
2498 wpos++; | |
10217 | 2499 br = TRUE; |
6982 | 2500 break; |
3922 | 2501 case 26: /* HR */ |
2502 case 42: /* HR (opt) */ | |
8726 | 2503 { |
2504 int minus; | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2505 struct scalable_data *sd = g_new(struct scalable_data, 1); |
8726 | 2506 |
3922 | 2507 ws[wpos++] = '\n'; |
8677 | 2508 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2509 | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2510 sd->scalable = scalable = gtk_imhtml_hr_new(); |
11233
f08d22130bb2
[gaim-migrate @ 13373]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11224
diff
changeset
|
2511 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); |
8061 | 2512 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
8677 | 2513 scalable->add_to(scalable, imhtml, iter); |
8726 | 2514 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + |
2515 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
2516 scalable->scale(scalable, rect.width - minus, rect.height); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2517 imhtml->scalables = g_list_append(imhtml->scalables, sd); |
8061 | 2518 ws[0] = '\0'; wpos = 0; |
7942 | 2519 ws[wpos++] = '\n'; |
8061 | 2520 |
3922 | 2521 break; |
8726 | 2522 } |
3922 | 2523 case 27: /* /FONT */ |
8677 | 2524 if (fonts && !imhtml->wbfo) { |
5967 | 2525 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2526 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2527 ws[0] = '\0'; wpos = 0; |
8177 | 2528 /* NEW_BIT (NEW_TEXT_BIT); */ |
8677 | 2529 |
8698 | 2530 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) { |
8061 | 2531 gtk_imhtml_toggle_fontface(imhtml, NULL); |
3922 | 2532 g_free (font->face); |
8061 | 2533 } |
8698 | 2534 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
8061 | 2535 gtk_imhtml_toggle_forecolor(imhtml, NULL); |
3922 | 2536 g_free (font->fore); |
8061 | 2537 } |
8698 | 2538 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
8061 | 2539 gtk_imhtml_toggle_backcolor(imhtml, NULL); |
3922 | 2540 g_free (font->back); |
8061 | 2541 } |
4032 | 2542 if (font->sml) |
2543 g_free (font->sml); | |
8309 | 2544 |
8698 | 2545 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2546 gtk_imhtml_font_set_size(imhtml, 3); |
2547 | |
10761 | 2548 |
2549 fonts = g_slist_remove (fonts, font); | |
9245 | 2550 g_free(font); |
2551 | |
8309 | 2552 if (fonts) { |
2553 GtkIMHtmlFontDetail *font = fonts->data; | |
8677 | 2554 |
8698 | 2555 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8309 | 2556 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8698 | 2557 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8309 | 2558 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8698 | 2559 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
8309 | 2560 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8698 | 2561 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2562 gtk_imhtml_font_set_size(imhtml, font->size); |
2563 } | |
3922 | 2564 } |
8309 | 2565 break; |
3922 | 2566 case 28: /* /A */ |
8677 | 2567 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2568 gtk_imhtml_toggle_link(imhtml, NULL); | |
2569 ws[0] = '\0'; wpos = 0; | |
8061 | 2570 break; |
8118 | 2571 |
3922 | 2572 case 29: /* P */ |
2573 case 30: /* /P */ | |
2574 case 31: /* H3 */ | |
2575 case 32: /* /H3 */ | |
2576 case 33: /* HTML */ | |
2577 case 34: /* /HTML */ | |
2578 case 35: /* BODY */ | |
10776 | 2579 break; |
3922 | 2580 case 36: /* /BODY */ |
10786 | 2581 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2582 ws[0] = '\0'; wpos = 0; | |
10776 | 2583 gtk_imhtml_toggle_background(imhtml, NULL); |
2584 break; | |
3922 | 2585 case 37: /* FONT */ |
2586 case 38: /* HEAD */ | |
2587 case 39: /* /HEAD */ | |
6982 | 2588 case 40: /* BINARY */ |
2589 case 41: /* /BINARY */ | |
3922 | 2590 break; |
2591 case 43: /* FONT (opt) */ | |
2592 { | |
4032 | 2593 gchar *color, *back, *face, *size, *sml; |
5967 | 2594 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 2595 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
2596 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
2597 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
2598 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 2599 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
2600 if (!(color || back || face || size || sml)) | |
3922 | 2601 break; |
8061 | 2602 |
8677 | 2603 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2604 ws[0] = '\0'; wpos = 0; |
2605 | |
5967 | 2606 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 2607 if (fonts) |
2608 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2609 |
8677 | 2610 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
3922 | 2611 font->fore = color; |
8061 | 2612 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8677 | 2613 } |
8309 | 2614 //else if (oldfont && oldfont->fore) |
2615 // font->fore = g_strdup(oldfont->fore); | |
8677 | 2616 |
2617 if (back && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { | |
3922 | 2618 font->back = back; |
8061 | 2619 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8309 | 2620 } |
2621 //else if (oldfont && oldfont->back) | |
2622 // font->back = g_strdup(oldfont->back); | |
8677 | 2623 |
2624 if (face && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) { | |
3922 | 2625 font->face = face; |
8061 | 2626 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8309 | 2627 } |
2628 //else if (oldfont && oldfont->face) | |
2629 // font->face = g_strdup(oldfont->face); | |
4032 | 2630 |
2631 if (sml) | |
2632 font->sml = sml; | |
2633 else if (oldfont && oldfont->sml) | |
2634 font->sml = g_strdup(oldfont->sml); | |
2635 | |
8677 | 2636 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) { |
3922 | 2637 if (*size == '+') { |
2638 sscanf (size + 1, "%hd", &font->size); | |
2639 font->size += 3; | |
2640 } else if (*size == '-') { | |
2641 sscanf (size + 1, "%hd", &font->size); | |
2642 font->size = MAX (0, 3 - font->size); | |
2643 } else if (isdigit (*size)) { | |
2644 sscanf (size, "%hd", &font->size); | |
8061 | 2645 } |
6042 | 2646 if (font->size > 100) |
2647 font->size = 100; | |
3922 | 2648 } else if (oldfont) |
2649 font->size = oldfont->size; | |
8309 | 2650 else |
2651 font->size = 3; | |
8698 | 2652 if ((imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
2653 gtk_imhtml_font_set_size(imhtml, font->size); | |
3922 | 2654 g_free(size); |
2655 fonts = g_slist_prepend (fonts, font); | |
2656 } | |
2657 break; | |
2658 case 44: /* BODY (opt) */ | |
2659 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
2660 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
8677 | 2661 if (bgcolor && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
2662 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2663 ws[0] = '\0'; wpos = 0; |
8177 | 2664 /* NEW_BIT(NEW_TEXT_BIT); */ |
3922 | 2665 if (bg) |
2666 g_free(bg); | |
2667 bg = bgcolor; | |
10776 | 2668 gtk_imhtml_toggle_background(imhtml, bg); |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
2669 } |
1428 | 2670 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2671 break; |
3922 | 2672 case 45: /* A (opt) */ |
2673 { | |
2674 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
8677 | 2675 if (href && (imhtml->format_functions & GTK_IMHTML_LINK)) { |
2676 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2677 ws[0] = '\0'; wpos = 0; |
8677 | 2678 gtk_imhtml_toggle_link(imhtml, href); |
3922 | 2679 } |
10504 | 2680 if (href) |
2681 g_free(href); | |
2993 | 2682 } |
3922 | 2683 break; |
4895 | 2684 case 46: /* IMG (opt) */ |
6982 | 2685 case 59: /* IMG */ |
4895 | 2686 { |
8962 | 2687 const char *id; |
2688 | |
2689 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
2690 ws[0] = '\0'; wpos = 0; | |
4895 | 2691 |
8677 | 2692 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) |
2693 break; | |
2694 | |
8962 | 2695 id = gtk_imhtml_get_html_opt(tag, "ID="); |
9186 | 2696 if (!id) |
2697 break; | |
8962 | 2698 gtk_imhtml_insert_image_at_iter(imhtml, atoi(id), iter); |
2699 break; | |
4895 | 2700 } |
3922 | 2701 case 47: /* P (opt) */ |
2702 case 48: /* H3 (opt) */ | |
5093 | 2703 case 49: /* HTML (opt) */ |
5101 | 2704 case 50: /* CITE */ |
2705 case 51: /* /CITE */ | |
8026 | 2706 case 56: /* SPAN (opt) */ |
8118 | 2707 /* Inline CSS Support - Douglas Thrift |
2708 * | |
2709 * color | |
8686 | 2710 * background |
8118 | 2711 * font-family |
2712 * font-size | |
8686 | 2713 * text-decoration: underline |
10483 | 2714 * |
2715 * TODO: | |
2716 * background-color | |
2717 * font-style | |
2718 * font-weight | |
8118 | 2719 */ |
2720 { | |
8686 | 2721 gchar *style, *color, *background, *family, *size; |
2722 gchar *textdec; | |
8118 | 2723 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
2724 style = gtk_imhtml_get_html_opt (tag, "style="); | |
2725 | |
2726 if (!style) break; | |
2727 | |
10457 | 2728 color = gtk_imhtml_get_css_opt (style, "color:"); |
2729 background = gtk_imhtml_get_css_opt (style, "background:"); | |
8118 | 2730 family = gtk_imhtml_get_css_opt (style, |
10457 | 2731 "font-family:"); |
2732 size = gtk_imhtml_get_css_opt (style, "font-size:"); | |
2733 textdec = gtk_imhtml_get_css_opt (style, "text-decoration:"); | |
8686 | 2734 |
2735 if (!(color || family || size || background || textdec)) { | |
8120 | 2736 g_free(style); |
2737 break; | |
2738 } | |
8118 | 2739 |
8677 | 2740 |
2741 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8118 | 2742 ws[0] = '\0'; wpos = 0; |
8177 | 2743 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2744 |
2745 font = g_new0 (GtkIMHtmlFontDetail, 1); | |
2746 if (fonts) | |
2747 oldfont = fonts->data; | |
2748 | |
8677 | 2749 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8686 | 2750 { |
8118 | 2751 font->fore = color; |
8686 | 2752 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
2753 } | |
8118 | 2754 else if (oldfont && oldfont->fore) |
2755 font->fore = g_strdup(oldfont->fore); | |
2756 | |
8686 | 2757 if (background && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
2758 { | |
2759 font->back = background; | |
2760 gtk_imhtml_toggle_backcolor(imhtml, font->back); | |
2761 } | |
2762 else if (oldfont && oldfont->back) | |
8118 | 2763 font->back = g_strdup(oldfont->back); |
2764 | |
8677 | 2765 if (family && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8686 | 2766 { |
8118 | 2767 font->face = family; |
8686 | 2768 gtk_imhtml_toggle_fontface(imhtml, font->face); |
2769 } | |
8118 | 2770 else if (oldfont && oldfont->face) |
2771 font->face = g_strdup(oldfont->face); | |
2772 if (font->face && (atoi(font->face) > 100)) { | |
8677 | 2773 /* WTF is this? */ |
9696 | 2774 /* Maybe it sets a max size on the font face? I seem to |
2775 * remember bad things happening if the font size was | |
2776 * 2 billion */ | |
8118 | 2777 g_free(font->face); |
2778 font->face = g_strdup("100"); | |
2779 } | |
2780 | |
2781 if (oldfont && oldfont->sml) | |
2782 font->sml = g_strdup(oldfont->sml); | |
2783 | |
8677 | 2784 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_SHRINK|GTK_IMHTML_GROW))) { |
8686 | 2785 if (g_ascii_strcasecmp(size, "xx-small") == 0) |
2786 font->size = 1; | |
2787 else if (g_ascii_strcasecmp(size, "smaller") == 0 | |
2788 || g_ascii_strcasecmp(size, "x-small") == 0) | |
8118 | 2789 font->size = 2; |
8686 | 2790 else if (g_ascii_strcasecmp(size, "larger") == 0 |
2791 || g_ascii_strcasecmp(size, "medium") == 0) | |
8118 | 2792 font->size = 4; |
8686 | 2793 else if (g_ascii_strcasecmp(size, "large") == 0) |
2794 font->size = 5; | |
2795 else if (g_ascii_strcasecmp(size, "x-large") == 0) | |
2796 font->size = 6; | |
2797 else if (g_ascii_strcasecmp(size, "xx-large") == 0) | |
2798 font->size = 7; | |
8118 | 2799 else |
2800 font->size = 3; | |
8686 | 2801 gtk_imhtml_font_set_size(imhtml, font->size); |
2802 } | |
2803 else if (oldfont) | |
2804 { | |
2805 font->size = oldfont->size; | |
2806 } | |
2807 | |
2808 if (oldfont) | |
2809 { | |
2810 font->underline = oldfont->underline; | |
2811 } | |
2812 if (textdec && font->underline != 1 | |
9025 | 2813 && g_ascii_strcasecmp(textdec, "underline") == 0 |
8686 | 2814 && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
2815 { | |
2816 gtk_imhtml_toggle_underline(imhtml); | |
2817 font->underline = 1; | |
2818 } | |
8118 | 2819 |
2820 g_free(style); | |
2821 g_free(size); | |
2822 fonts = g_slist_prepend (fonts, font); | |
2823 } | |
2824 break; | |
5104 | 2825 case 57: /* /SPAN */ |
8118 | 2826 /* Inline CSS Support - Douglas Thrift */ |
8677 | 2827 if (fonts && !imhtml->wbfo) { |
8686 | 2828 GtkIMHtmlFontDetail *oldfont = NULL; |
8118 | 2829 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2830 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8118 | 2831 ws[0] = '\0'; wpos = 0; |
8177 | 2832 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2833 fonts = g_slist_remove (fonts, font); |
8692 | 2834 if (fonts) |
2835 oldfont = fonts->data; | |
2836 | |
2837 if (!oldfont) { | |
2838 gtk_imhtml_font_set_size(imhtml, 3); | |
2839 if (font->underline) | |
2840 gtk_imhtml_toggle_underline(imhtml); | |
2841 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
2842 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
2843 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
8686 | 2844 } |
8692 | 2845 else |
8686 | 2846 { |
8692 | 2847 |
2848 if (font->size != oldfont->size) | |
2849 gtk_imhtml_font_set_size(imhtml, oldfont->size); | |
2850 | |
2851 if (font->underline != oldfont->underline) | |
2852 gtk_imhtml_toggle_underline(imhtml); | |
2853 | |
9286 | 2854 if (font->face && (!oldfont->face || strcmp(font->face, oldfont->face) != 0)) |
8692 | 2855 gtk_imhtml_toggle_fontface(imhtml, oldfont->face); |
2856 | |
9286 | 2857 if (font->fore && (!oldfont->fore || strcmp(font->fore, oldfont->fore) != 0)) |
8692 | 2858 gtk_imhtml_toggle_forecolor(imhtml, oldfont->fore); |
2859 | |
9286 | 2860 if (font->back && (!oldfont->back || strcmp(font->back, oldfont->back) != 0)) |
8692 | 2861 gtk_imhtml_toggle_backcolor(imhtml, oldfont->back); |
8686 | 2862 } |
8692 | 2863 |
2864 g_free (font->face); | |
2865 g_free (font->fore); | |
2866 g_free (font->back); | |
2867 g_free (font->sml); | |
2868 | |
8118 | 2869 g_free (font); |
2870 } | |
2871 break; | |
8026 | 2872 case 60: /* SPAN */ |
2993 | 2873 break; |
8061 | 2874 case 62: /* comment */ |
8177 | 2875 /* NEW_BIT (NEW_TEXT_BIT); */ |
8317 | 2876 ws[wpos] = '\0'; |
9465 | 2877 |
8677 | 2878 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2879 | |
10815 | 2880 if (imhtml->show_comments && !(options & GTK_IMHTML_NO_COMMENTS)) { |
6124 | 2881 wpos = g_snprintf (ws, len, "%s", tag); |
10815 | 2882 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2883 } | |
2884 ws[0] = '\0'; wpos = 0; | |
2885 | |
8177 | 2886 /* NEW_BIT (NEW_COMMENT_BIT); */ |
3922 | 2887 break; |
2888 default: | |
6882 | 2889 break; |
2993 | 2890 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2891 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2892 pos += tlen; |
4138 | 2893 if(tag) |
2894 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
9029 | 2895 } else if (gtk_imhtml_is_smiley(imhtml, fonts, c, &smilelen)) { |
8473 | 2896 GtkIMHtmlFontDetail *fd; |
2897 | |
2898 gchar *sml = NULL; | |
2899 if (fonts) { | |
2900 fd = fonts->data; | |
2901 sml = fd->sml; | |
2902 } | |
9029 | 2903 if (!sml) |
2904 sml = imhtml->protocol_name; | |
2905 | |
8677 | 2906 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8505 | 2907 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
8473 | 2908 |
8677 | 2909 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, ws, iter); |
8473 | 2910 |
8505 | 2911 c += smilelen; |
2912 pos += smilelen; | |
8473 | 2913 wpos = 0; |
2914 ws[0] = 0; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2915 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
7280 | 2916 while(*amp) { |
2917 ws [wpos++] = *amp++; | |
2918 } | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2919 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2920 pos += tlen; |
1428 | 2921 } else if (*c == '\n') { |
2922 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 2923 ws[wpos] = '\n'; |
2924 wpos++; | |
8677 | 2925 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2926 ws[0] = '\0'; |
2927 wpos = 0; | |
8177 | 2928 /* NEW_BIT (NEW_TEXT_BIT); */ |
10217 | 2929 } else if (!br) { /* Don't insert a space immediately after an HTML break */ |
9621 | 2930 /* A newline is defined by HTML as whitespace, which means we have to replace it with a word boundary. |
2931 * word breaks vary depending on the language used, so the correct thing to do is to use Pango to determine | |
2932 * what language this is, determine the proper word boundary to use, and insert that. I'm just going to insert | |
2933 * a space instead. What are the non-English speakers going to do? Complain in a language I'll understand? | |
2934 * Bu-wahaha! */ | |
2935 ws[wpos] = ' '; | |
2936 wpos++; | |
2937 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
2938 ws[0] = '\0'; | |
2939 wpos = 0; | |
1428 | 2940 } |
2941 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2942 pos++; |
8334 | 2943 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
2944 while(len_protocol--){ | |
8677 | 2945 /* Skip the next len_protocol characters, but make sure they're |
8334 | 2946 copied into the ws array. |
2947 */ | |
2948 ws [wpos++] = *c++; | |
2949 pos++; | |
2950 } | |
8061 | 2951 } else if (*c) { |
1428 | 2952 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2953 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2954 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2955 break; |
1428 | 2956 } |
2957 } | |
8677 | 2958 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2959 ws[0] = '\0'; wpos = 0; |
2960 | |
8177 | 2961 /* NEW_BIT(NEW_TEXT_BIT); */ |
8061 | 2962 |
4032 | 2963 while (fonts) { |
5967 | 2964 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 2965 fonts = g_slist_remove (fonts, font); |
2966 if (font->face) | |
2967 g_free (font->face); | |
2968 if (font->fore) | |
2969 g_free (font->fore); | |
2970 if (font->back) | |
2971 g_free (font->back); | |
2972 if (font->sml) | |
2973 g_free (font->sml); | |
2974 g_free (font); | |
2975 } | |
8932 | 2976 |
2977 g_free(ws); | |
2978 if (bg) | |
4630 | 2979 g_free(bg); |
8677 | 2980 |
2981 if (!imhtml->wbfo) | |
8698 | 2982 gtk_imhtml_close_tags(imhtml, iter); |
8506 | 2983 |
2984 object = g_object_ref(G_OBJECT(imhtml)); | |
2985 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | |
2986 g_object_unref(object); | |
2987 | |
3922 | 2988 } |
2989 | |
4892 | 2990 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
2991 { | |
4288 | 2992 g_hash_table_destroy(imhtml->smiley_data); |
2993 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 2994 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 2995 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 2996 imhtml->default_smilies = gtk_smiley_tree_new(); |
2997 } | |
8481 | 2998 |
3922 | 2999 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, |
4253 | 3000 gboolean show) |
3001 { | |
6124 | 3002 imhtml->show_comments = show; |
4253 | 3003 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
3004 |
8962 | 3005 void |
9029 | 3006 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, const gchar *protocol_name) { |
3007 if (imhtml->protocol_name) | |
3008 g_free(imhtml->protocol_name); | |
3009 imhtml->protocol_name = protocol_name ? g_strdup(protocol_name) : NULL; | |
8456 | 3010 } |
3011 | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
3012 void |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3013 gtk_imhtml_delete(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3014 GList *l; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3015 GSList *sl; |
11234
7d5e8bed8018
[gaim-migrate @ 13377]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11233
diff
changeset
|
3016 GtkTextIter i, i_s, i_e; |
8427 | 3017 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3018 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3019 if (start == NULL) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3020 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &i_s); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3021 start = &i_s; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3022 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3023 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3024 if (end == NULL) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3025 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &i_e); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3026 end = &i_e; |
7991 | 3027 } |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3028 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3029 l = imhtml->scalables; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3030 while (l) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3031 GList *next = l->next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3032 struct scalable_data *sd = l->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3033 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3034 &i, sd->mark); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3035 if (gtk_text_iter_in_range(&i, start, end)) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3036 GtkIMHtmlScalable *scale = sd->scalable; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3037 scale->free(scale); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3038 imhtml->scalables = g_list_remove_link(imhtml->scalables, l); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3039 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3040 l = next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3041 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3042 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3043 sl = imhtml->im_images; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3044 while (sl) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3045 GSList *next = sl->next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3046 struct im_image_data *img_data = sl->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3047 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3048 &i, img_data->mark); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3049 if (gtk_text_iter_in_range(&i, start, end)) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3050 if (imhtml->funcs->image_unref) |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3051 imhtml->funcs->image_unref(img_data->id); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3052 imhtml->im_images = g_slist_delete_link(imhtml->im_images, sl); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3053 g_free(img_data); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3054 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3055 sl = next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3056 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3057 gtk_text_buffer_delete(imhtml->text_buffer, start, end); |
8061 | 3058 |
8427 | 3059 g_object_unref(object); |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
3060 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
3061 |
4046 | 3062 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
3063 { | |
5282 | 3064 GdkRectangle rect; |
3065 GtkTextIter iter; | |
4046 | 3066 |
5282 | 3067 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
3068 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
3069 rect.y - rect.height); | |
3070 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
8061 | 3071 |
4046 | 3072 } |
5282 | 3073 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
3074 { | |
3075 GdkRectangle rect; | |
3076 GtkTextIter iter; | |
3077 | |
3078 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
3079 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
3080 rect.y + rect.height); | |
3081 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
3082 } | |
4735 | 3083 |
5967 | 3084 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
8962 | 3085 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) |
4735 | 3086 { |
5967 | 3087 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 3088 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 3089 |
5967 | 3090 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
3091 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
3092 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 3093 |
3094 im_image->pixbuf = img; | |
5012 | 3095 im_image->image = image; |
4895 | 3096 im_image->width = gdk_pixbuf_get_width(img); |
3097 im_image->height = gdk_pixbuf_get_height(img); | |
3098 im_image->mark = NULL; | |
6982 | 3099 im_image->filename = filename ? g_strdup(filename) : NULL; |
8962 | 3100 im_image->id = id; |
9573 | 3101 im_image->filesel = NULL; |
4895 | 3102 |
5046 | 3103 g_object_ref(img); |
4895 | 3104 return GTK_IMHTML_SCALABLE(im_image); |
3105 } | |
3106 | |
5967 | 3107 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 3108 { |
5967 | 3109 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 3110 |
3111 if(image->width > width || image->height > height){ | |
3112 GdkPixbuf *new_image = NULL; | |
3113 float factor; | |
3114 int new_width = image->width, new_height = image->height; | |
3115 | |
8588 | 3116 if(image->width > (width - 2)){ |
4895 | 3117 factor = (float)(width)/image->width; |
3118 new_width = width; | |
3119 new_height = image->height * factor; | |
3120 } | |
8588 | 3121 if(new_height >= (height - 2)){ |
4895 | 3122 factor = (float)(height)/new_height; |
3123 new_height = height; | |
3124 new_width = new_width * factor; | |
3125 } | |
3126 | |
5046 | 3127 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 3128 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 3129 g_object_unref(G_OBJECT(new_image)); |
3130 } | |
3131 } | |
3132 | |
9573 | 3133 static void |
3134 image_save_yes_cb(GtkIMHtmlImage *image, const char *filename) | |
5012 | 3135 { |
3136 gchar *type = NULL; | |
5019 | 3137 GError *error = NULL; |
5015 | 3138 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 3139 GSList *formats = gdk_pixbuf_get_formats(); |
6162 | 3140 #else |
3141 char *basename = g_path_get_basename(filename); | |
3142 char *ext = strrchr(basename, '.'); | |
5959 | 3143 #endif |
5012 | 3144 |
9573 | 3145 gtk_widget_destroy(image->filesel); |
3146 image->filesel = NULL; | |
5959 | 3147 |
3148 #if GTK_CHECK_VERSION(2,2,0) | |
9573 | 3149 while (formats) { |
5012 | 3150 GdkPixbufFormat *format = formats->data; |
3151 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
3152 gpointer p = extensions; | |
3153 | |
3154 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
3155 gchar *fmt_ext = extensions[0]; | |
3156 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
3157 | |
3158 if(!strcmp(fmt_ext, file_ext)){ | |
3159 type = gdk_pixbuf_format_get_name(format); | |
3160 break; | |
3161 } | |
3162 | |
3163 extensions++; | |
3164 } | |
3165 | |
3166 g_strfreev(p); | |
3167 | |
9573 | 3168 if (type) |
5012 | 3169 break; |
3170 | |
3171 formats = formats->next; | |
3172 } | |
3173 | |
5020 | 3174 g_slist_free(formats); |
3175 #else | |
3176 /* this is really ugly code, but I think it will work */ | |
9573 | 3177 if (ext) { |
5020 | 3178 ext++; |
9573 | 3179 if (!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) |
5020 | 3180 type = g_strdup("jpeg"); |
9573 | 3181 else if (!g_ascii_strcasecmp(ext, "png")) |
5020 | 3182 type = g_strdup("png"); |
3183 } | |
3184 | |
3185 g_free(basename); | |
3186 #endif | |
3187 | |
5012 | 3188 /* If I can't find a valid type, I will just tell the user about it and then assume |
3189 it's a png */ | |
9573 | 3190 if (!type){ |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3191 #if GTK_CHECK_VERSION(2,4,0) |
11019 | 3192 GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
3193 _("<span size='larger' weight='bold'>Unrecognized file type</span>\n\nDefaulting to PNG.")); | |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3194 #else |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3195 GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3196 _("Unrecognized file type\n\nDefaulting to PNG.")); |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3197 #endif |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3198 |
11019 | 3199 g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); |
3200 gtk_widget_show(dialog); | |
9717 | 3201 type = g_strdup("png"); |
5012 | 3202 } |
3203 | |
5046 | 3204 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 3205 |
9573 | 3206 if (error){ |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3207 #if GTK_CHECK_VERSION(2,4,0) |
11019 | 3208 GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
3209 _("<span size='larger' weight='bold'>Error saving image</span>\n\n%s"), error->message); | |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3210 #else |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3211 GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3212 _("Error saving image\n\n%s"), error->message); |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3213 #endif |
11019 | 3214 g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); |
3215 gtk_widget_show(dialog); | |
5012 | 3216 g_error_free(error); |
3217 } | |
3218 | |
3219 g_free(type); | |
3220 } | |
3221 | |
9573 | 3222 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
3223 static void | |
3224 image_save_check_if_exists_cb(GtkWidget *widget, gint response, GtkIMHtmlImage *image) | |
3225 { | |
3226 gchar *filename; | |
3227 | |
3228 if (response != GTK_RESPONSE_ACCEPT) { | |
3229 gtk_widget_destroy(widget); | |
3230 image->filesel = NULL; | |
3231 return; | |
3232 } | |
3233 | |
3234 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); | |
3235 #else /* FILECHOOSER */ | |
3236 static void | |
3237 image_save_check_if_exists_cb(GtkWidget *button, GtkIMHtmlImage *image) | |
5012 | 3238 { |
9573 | 3239 gchar *filename; |
3240 | |
3241 filename = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(image->filesel))); | |
3242 | |
3243 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { | |
3244 gchar *dirname; | |
3245 /* append a / is needed */ | |
3246 if (filename[strlen(filename) - 1] != G_DIR_SEPARATOR) { | |
3247 dirname = g_strconcat(filename, G_DIR_SEPARATOR_S, NULL); | |
3248 } else { | |
3249 dirname = g_strdup(filename); | |
3250 } | |
9574 | 3251 gtk_file_selection_set_filename(GTK_FILE_SELECTION(image->filesel), dirname); |
9573 | 3252 g_free(dirname); |
3253 g_free(filename); | |
3254 return; | |
3255 } | |
3256 #endif /* FILECHOOSER */ | |
3257 | |
3258 /* | |
3259 * XXX - We should probably prompt the user to determine if they really | |
3260 * want to overwrite the file or not. However, I don't feel like doing | |
3261 * that, so we're just always going to overwrite if the file exists. | |
3262 */ | |
3263 /* | |
3264 if (g_file_test(filename, G_FILE_TEST_EXISTS)) { | |
3265 } else | |
3266 image_save_yes_cb(image, filename); | |
3267 */ | |
3268 | |
3269 image_save_yes_cb(image, filename); | |
3270 | |
3271 g_free(filename); | |
3272 } | |
3273 | |
3274 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
3275 static void | |
3276 image_save_cancel_cb(GtkIMHtmlImage *image) | |
3277 { | |
3278 gtk_widget_destroy(image->filesel); | |
3279 image->filesel = NULL; | |
3280 } | |
3281 #endif /* FILECHOOSER */ | |
3282 | |
3283 static void | |
3284 gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) | |
3285 { | |
3286 if (image->filesel != NULL) { | |
3287 gtk_window_present(GTK_WINDOW(image->filesel)); | |
3288 return; | |
3289 } | |
3290 | |
3291 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
3292 image->filesel = gtk_file_chooser_dialog_new(_("Save Image"), | |
3293 NULL, | |
3294 GTK_FILE_CHOOSER_ACTION_SAVE, | |
3295 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
3296 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, | |
3297 NULL); | |
3298 gtk_dialog_set_default_response(GTK_DIALOG(image->filesel), GTK_RESPONSE_ACCEPT); | |
3299 if (image->filename != NULL) | |
3300 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(image->filesel), image->filename); | |
3301 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(image->filesel)), "response", | |
3302 G_CALLBACK(image_save_check_if_exists_cb), image); | |
3303 #else /* FILECHOOSER */ | |
3304 image->filesel = gtk_file_selection_new(_("Save Image")); | |
3305 if (image->filename != NULL) | |
3306 gtk_file_selection_set_filename(GTK_FILE_SELECTION(image->filesel), image->filename); | |
9574 | 3307 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(image->filesel)), "delete_event", |
3308 G_CALLBACK(image_save_cancel_cb), image); | |
3309 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->cancel_button), | |
3310 "clicked", G_CALLBACK(image_save_cancel_cb), image); | |
9573 | 3311 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->ok_button), "clicked", |
3312 G_CALLBACK(image_save_check_if_exists_cb), image); | |
3313 #endif /* FILECHOOSER */ | |
3314 | |
3315 gtk_widget_show(image->filesel); | |
5012 | 3316 } |
3317 | |
9815 | 3318 /* |
3319 * So, um, AIM Direct IM lets you send any file, not just images. You can | |
3320 * just insert a sound or a file or whatever in a conversation. It's | |
3321 * basically like file transfer, except there is an icon to open the file | |
3322 * embedded in the conversation. Someone should make the Gaim core handle | |
3323 * all of that. | |
3324 */ | |
5967 | 3325 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 3326 { |
3327 GdkEventButton *event_button = (GdkEventButton *) event; | |
3328 | |
3329 if (event->type == GDK_BUTTON_RELEASE) { | |
3330 if(event_button->button == 3) { | |
3331 GtkWidget *img, *item, *menu; | |
3332 gchar *text = g_strdup_printf(_("_Save Image...")); | |
3333 menu = gtk_menu_new(); | |
3334 | |
3335 /* buttons and such */ | |
3336 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
3337 item = gtk_image_menu_item_new_with_mnemonic(text); | |
3338 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 3339 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 3340 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3341 | |
3342 gtk_widget_show_all(menu); | |
3343 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
3344 event_button->button, event_button->time); | |
3345 | |
3346 g_free(text); | |
3347 return TRUE; | |
3348 } | |
3349 } | |
3350 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
3351 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
3352 be caught by the regular GtkTextView menu */ | |
3353 else | |
3354 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
3355 | |
3356 } | |
5967 | 3357 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
3358 { | |
3359 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
3360 | |
3361 g_object_unref(image->pixbuf); | |
6982 | 3362 if (image->filename) |
3363 g_free(image->filename); | |
9573 | 3364 if (image->filesel) |
3365 gtk_widget_destroy(image->filesel); | |
5967 | 3366 g_free(scale); |
3367 } | |
3368 | |
3369 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
3370 { | |
3371 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
3372 GtkWidget *box = gtk_event_box_new(); | |
8962 | 3373 char *tag; |
5967 | 3374 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
3375 | |
3376 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
9229 | 3377 |
3378 if(!gtk_check_version(2, 4, 0)) | |
3379 g_object_set(G_OBJECT(box), "visible-window", FALSE, NULL); | |
5967 | 3380 |
3381 gtk_widget_show(GTK_WIDGET(image->image)); | |
3382 gtk_widget_show(box); | |
3383 | |
8962 | 3384 tag = g_strdup_printf("<IMG ID=\"%d\">", image->id); |
3385 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free); | |
3386 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); | |
3387 | |
5967 | 3388 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); |
3389 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
3390 } | |
3391 | |
3392 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
3393 { | |
3394 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
3395 | |
3396 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
3397 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
3398 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
3399 | |
3400 hr->sep = gtk_hseparator_new(); | |
3401 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
3402 gtk_widget_show(hr->sep); | |
3403 | |
3404 return GTK_IMHTML_SCALABLE(hr); | |
3405 } | |
3406 | |
3407 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
3408 { | |
8588 | 3409 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); |
5967 | 3410 } |
3411 | |
3412 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
3413 { | |
3414 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
3415 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
8698 | 3416 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); |
3417 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); | |
5967 | 3418 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
3419 } | |
3420 | |
3421 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
3422 { | |
3423 g_free(scale); | |
3424 } | |
7295 | 3425 |
3426 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | |
3427 { | |
3428 GtkTextIter iter, start, end; | |
3429 gboolean new_search = TRUE; | |
3430 | |
3431 g_return_val_if_fail(imhtml != NULL, FALSE); | |
3432 g_return_val_if_fail(text != NULL, FALSE); | |
8061 | 3433 |
7295 | 3434 if (imhtml->search_string && !strcmp(text, imhtml->search_string)) |
3435 new_search = FALSE; | |
8061 | 3436 |
7295 | 3437 if (new_search) { |
3438 gtk_imhtml_search_clear(imhtml); | |
3439 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
3440 } else { | |
3441 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, | |
8061 | 3442 gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); |
7295 | 3443 } |
10574 | 3444 g_free(imhtml->search_string); |
7295 | 3445 imhtml->search_string = g_strdup(text); |
3446 | |
7358 | 3447 if (gtk_source_iter_forward_search(&iter, imhtml->search_string, |
3448 GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, | |
7295 | 3449 &start, &end, NULL)) { |
3450 | |
3451 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0); | |
3452 gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); | |
3453 if (new_search) { | |
3454 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); | |
8061 | 3455 do |
7295 | 3456 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); |
8061 | 3457 while (gtk_source_iter_forward_search(&end, imhtml->search_string, |
3458 GTK_SOURCE_SEARCH_VISIBLE_ONLY | | |
7358 | 3459 GTK_SOURCE_SEARCH_CASE_INSENSITIVE, |
7295 | 3460 &start, &end, NULL)); |
3461 } | |
3462 return TRUE; | |
3463 } | |
8061 | 3464 |
3465 gtk_imhtml_search_clear(imhtml); | |
3466 | |
7295 | 3467 return FALSE; |
3468 } | |
3469 | |
3470 void gtk_imhtml_search_clear(GtkIMHtml *imhtml) | |
3471 { | |
3472 GtkTextIter start, end; | |
8061 | 3473 |
7295 | 3474 g_return_if_fail(imhtml != NULL); |
8061 | 3475 |
7295 | 3476 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
3477 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3478 | |
3479 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end); | |
3480 if (imhtml->search_string) | |
3481 g_free(imhtml->search_string); | |
3482 imhtml->search_string = NULL; | |
3483 } | |
8061 | 3484 |
8677 | 3485 static GtkTextTag *find_font_forecolor_tag(GtkIMHtml *imhtml, gchar *color) |
3486 { | |
3487 gchar str[18]; | |
3488 GtkTextTag *tag; | |
3489 | |
3490 g_snprintf(str, sizeof(str), "FORECOLOR %s", color); | |
3491 | |
3492 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
10858 | 3493 if (!tag) { |
3494 GdkColor gcolor; | |
3495 if (!gdk_color_parse(color, &gcolor)) { | |
3496 gchar tmp[8]; | |
3497 tmp[0] = '#'; | |
3498 strncpy(&tmp[1], color, 7); | |
3499 tmp[7] = '\0'; | |
3500 if (!gdk_color_parse(tmp, &gcolor)) | |
3501 gdk_color_parse("black", &gcolor); | |
3502 } | |
3503 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground-gdk", &gcolor, NULL); | |
3504 } | |
8677 | 3505 |
3506 return tag; | |
3507 } | |
3508 | |
3509 static GtkTextTag *find_font_backcolor_tag(GtkIMHtml *imhtml, gchar *color) | |
3510 { | |
3511 gchar str[18]; | |
3512 GtkTextTag *tag; | |
3513 | |
3514 g_snprintf(str, sizeof(str), "BACKCOLOR %s", color); | |
3515 | |
3516 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
10858 | 3517 if (!tag) { |
3518 GdkColor gcolor; | |
3519 if (!gdk_color_parse(color, &gcolor)) { | |
3520 gchar tmp[8]; | |
3521 tmp[0] = '#'; | |
3522 strncpy(&tmp[1], color, 7); | |
3523 tmp[7] = '\0'; | |
3524 if (!gdk_color_parse(tmp, &gcolor)) | |
3525 gdk_color_parse("white", &gcolor); | |
3526 } | |
3527 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "background-gdk", &gcolor, NULL); | |
3528 } | |
8677 | 3529 |
3530 return tag; | |
3531 } | |
3532 | |
10776 | 3533 static GtkTextTag *find_font_background_tag(GtkIMHtml *imhtml, gchar *color) |
3534 { | |
3535 gchar str[19]; | |
3536 GtkTextTag *tag; | |
3537 | |
3538 g_snprintf(str, sizeof(str), "BACKGROUND %s", color); | |
3539 | |
3540 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3541 if (!tag) | |
3542 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, NULL); | |
3543 | |
3544 return tag; | |
3545 } | |
3546 | |
8677 | 3547 static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) |
8061 | 3548 { |
8677 | 3549 gchar str[256]; |
3550 GtkTextTag *tag; | |
3551 | |
3552 g_snprintf(str, sizeof(str), "FONT FACE %s", face); | |
3553 str[255] = '\0'; | |
3554 | |
3555 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3556 if (!tag) | |
3557 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "family", face, NULL); | |
3558 | |
3559 return tag; | |
3560 } | |
3561 | |
3562 static GtkTextTag *find_font_size_tag(GtkIMHtml *imhtml, int size) | |
3563 { | |
3564 gchar str[24]; | |
3565 GtkTextTag *tag; | |
3566 | |
3567 g_snprintf(str, sizeof(str), "FONT SIZE %d", size); | |
3568 str[23] = '\0'; | |
3569 | |
3570 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3571 if (!tag) { | |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3572 /* For reasons I don't understand, setting "scale" here scaled |
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3573 * based on some default size other than my theme's default |
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3574 * size. Our size 4 was actually smaller than our size 3 for |
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3575 * me. So this works around that oddity. |
8677 | 3576 */ |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3577 GtkTextAttributes *attr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(imhtml)); |
8677 | 3578 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "size", |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3579 (gint) (pango_font_description_get_size(attr->font) * |
10899 | 3580 (double) POINT_SIZE(size)), NULL); |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3581 gtk_text_attributes_unref(attr); |
8061 | 3582 } |
3583 | |
8677 | 3584 return tag; |
3585 } | |
3586 | |
3587 static void remove_tag_by_prefix(GtkIMHtml *imhtml, const GtkTextIter *i, const GtkTextIter *e, | |
3588 const char *prefix, guint len, gboolean homo) | |
3589 { | |
3590 GSList *tags, *l; | |
3591 GtkTextIter iter; | |
3592 | |
3593 tags = gtk_text_iter_get_tags(i); | |
3594 | |
3595 for (l = tags; l; l = l->next) { | |
3596 GtkTextTag *tag = l->data; | |
3597 | |
3598 if (tag->name && !strncmp(tag->name, prefix, len)) | |
3599 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); | |
8061 | 3600 } |
3601 | |
8677 | 3602 g_slist_free(tags); |
3603 | |
3604 if (homo) | |
3605 return; | |
3606 | |
3607 iter = *i; | |
3608 | |
3609 while (gtk_text_iter_forward_char(&iter) && !gtk_text_iter_equal(&iter, e)) { | |
3610 if (gtk_text_iter_begins_tag(&iter, NULL)) { | |
3611 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); | |
3612 | |
3613 for (l = tags; l; l = l->next) { | |
3614 GtkTextTag *tag = l->data; | |
3615 | |
3616 if (tag->name && !strncmp(tag->name, prefix, len)) | |
3617 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); | |
3618 } | |
3619 | |
3620 g_slist_free(tags); | |
3621 } | |
8061 | 3622 } |
8677 | 3623 } |
3624 | |
3625 static void remove_font_size(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3626 { | |
3627 remove_tag_by_prefix(imhtml, i, e, "FONT SIZE ", 10, homo); | |
3628 } | |
3629 | |
3630 static void remove_font_face(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3631 { | |
3632 remove_tag_by_prefix(imhtml, i, e, "FONT FACE ", 10, homo); | |
3633 } | |
3634 | |
3635 static void remove_font_forecolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3636 { | |
3637 remove_tag_by_prefix(imhtml, i, e, "FORECOLOR ", 10, homo); | |
3638 } | |
3639 | |
3640 static void remove_font_backcolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3641 { | |
3642 remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); | |
3643 } | |
3644 | |
10776 | 3645 static void remove_font_background(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) |
3646 { | |
3647 remove_tag_by_prefix(imhtml, i, e, "BACKGROUND ", 10, homo); | |
3648 } | |
3649 | |
8677 | 3650 static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) |
3651 { | |
3652 remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); | |
3653 } | |
3654 | |
3655 /* Editable stuff */ | |
3656 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | |
3657 { | |
3658 imhtml->insert_offset = gtk_text_iter_get_offset(iter); | |
3659 } | |
3660 | |
10169 | 3661 static void insert_ca_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextChildAnchor *arg2, gpointer user_data) |
3662 { | |
3663 GtkTextIter start; | |
3664 | |
3665 start = *arg1; | |
3666 gtk_text_iter_backward_char(&start); | |
3667 | |
3668 gtk_imhtml_apply_tags_on_insert(user_data, &start, arg1); | |
3669 } | |
3670 | |
8677 | 3671 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) |
3672 { | |
3673 GtkTextIter start; | |
3674 | |
3675 if (!len) | |
3676 return; | |
3677 | |
3678 start = *end; | |
3679 gtk_text_iter_set_offset(&start, imhtml->insert_offset); | |
3680 | |
10169 | 3681 gtk_imhtml_apply_tags_on_insert(imhtml, &start, end); |
3682 } | |
3683 | |
3684 static void gtk_imhtml_apply_tags_on_insert(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) | |
3685 { | |
8677 | 3686 if (imhtml->edit.bold) |
10169 | 3687 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", start, end); |
8677 | 3688 else |
10169 | 3689 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", start, end); |
8677 | 3690 |
3691 if (imhtml->edit.italic) | |
10169 | 3692 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", start, end); |
8677 | 3693 else |
10169 | 3694 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", start, end); |
8677 | 3695 |
3696 if (imhtml->edit.underline) | |
10169 | 3697 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", start, end); |
8677 | 3698 else |
10169 | 3699 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", start, end); |
8677 | 3700 |
9924 | 3701 if (imhtml->edit.strike) |
10169 | 3702 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", start, end); |
9924 | 3703 else |
10169 | 3704 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", start, end); |
9924 | 3705 |
8677 | 3706 if (imhtml->edit.forecolor) { |
10169 | 3707 remove_font_forecolor(imhtml, start, end, TRUE); |
8677 | 3708 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3709 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
10169 | 3710 start, end); |
8061 | 3711 } |
3712 | |
8677 | 3713 if (imhtml->edit.backcolor) { |
10169 | 3714 remove_font_backcolor(imhtml, start, end, TRUE); |
8677 | 3715 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3716 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), | |
10169 | 3717 start, end); |
8677 | 3718 } |
3719 | |
10776 | 3720 if (imhtml->edit.background) { |
3721 remove_font_background(imhtml, start, end, TRUE); | |
3722 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3723 find_font_background_tag(imhtml, imhtml->edit.background), | |
3724 start, end); | |
3725 } | |
8677 | 3726 if (imhtml->edit.fontface) { |
10169 | 3727 remove_font_face(imhtml, start, end, TRUE); |
8677 | 3728 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3729 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
10169 | 3730 start, end); |
8061 | 3731 } |
8677 | 3732 |
3733 if (imhtml->edit.fontsize) { | |
10169 | 3734 remove_font_size(imhtml, start, end, TRUE); |
8677 | 3735 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3736 find_font_size_tag(imhtml, imhtml->edit.fontsize), | |
10169 | 3737 start, end); |
8677 | 3738 } |
3739 | |
3740 if (imhtml->edit.link) { | |
10169 | 3741 remove_font_link(imhtml, start, end, TRUE); |
8677 | 3742 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3743 imhtml->edit.link, | |
10169 | 3744 start, end); |
8677 | 3745 } |
8061 | 3746 } |
3747 | |
3748 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | |
3749 { | |
3750 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | |
8177 | 3751 /* |
3752 * We need a visible caret for accessibility, so mouseless | |
3753 * people can highlight stuff. | |
3754 */ | |
3755 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | |
8061 | 3756 imhtml->editable = editable; |
8677 | 3757 imhtml->format_functions = GTK_IMHTML_ALL; |
3758 | |
3759 if (editable) | |
3760 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
3761 G_CALLBACK(mark_set_cb), imhtml); | |
3762 } | |
3763 | |
3764 void gtk_imhtml_set_whole_buffer_formatting_only(GtkIMHtml *imhtml, gboolean wbfo) | |
3765 { | |
3766 g_return_if_fail(imhtml != NULL); | |
3767 | |
3768 imhtml->wbfo = wbfo; | |
8420 | 3769 } |
3770 | |
3771 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | |
3772 { | |
3773 GObject *object = g_object_ref(G_OBJECT(imhtml)); | |
8677 | 3774 imhtml->format_functions = buttons; |
8420 | 3775 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); |
3776 g_object_unref(object); | |
8061 | 3777 } |
3778 | |
8788 | 3779 GtkIMHtmlButtons gtk_imhtml_get_format_functions(GtkIMHtml *imhtml) |
3780 { | |
3781 return imhtml->format_functions; | |
3782 } | |
8516 | 3783 |
3784 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, | |
3785 gboolean *italic, gboolean *underline) | |
8481 | 3786 { |
8677 | 3787 if (imhtml->edit.bold) |
3788 (*bold) = TRUE; | |
3789 if (imhtml->edit.italic) | |
3790 (*italic) = TRUE; | |
3791 if (imhtml->edit.underline) | |
3792 (*underline) = TRUE; | |
8481 | 3793 } |
3794 | |
9025 | 3795 char * |
3796 gtk_imhtml_get_current_fontface(GtkIMHtml *imhtml) | |
3797 { | |
3798 if (imhtml->edit.fontface) | |
3799 return g_strdup(imhtml->edit.fontface); | |
3800 else | |
3801 return NULL; | |
3802 } | |
3803 | |
3804 char * | |
3805 gtk_imhtml_get_current_forecolor(GtkIMHtml *imhtml) | |
3806 { | |
3807 if (imhtml->edit.forecolor) | |
3808 return g_strdup(imhtml->edit.forecolor); | |
3809 else | |
3810 return NULL; | |
3811 } | |
3812 | |
3813 char * | |
3814 gtk_imhtml_get_current_backcolor(GtkIMHtml *imhtml) | |
3815 { | |
3816 if (imhtml->edit.backcolor) | |
3817 return g_strdup(imhtml->edit.backcolor); | |
3818 else | |
3819 return NULL; | |
3820 } | |
3821 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3822 char * |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3823 gtk_imhtml_get_current_background(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3824 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3825 if (imhtml->edit.background) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3826 return g_strdup(imhtml->edit.background); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3827 else |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3828 return NULL; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3829 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3830 |
9025 | 3831 gint |
3832 gtk_imhtml_get_current_fontsize(GtkIMHtml *imhtml) | |
3833 { | |
3834 return imhtml->edit.fontsize; | |
3835 } | |
3836 | |
8061 | 3837 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) |
3838 { | |
3839 return imhtml->editable; | |
3840 } | |
3841 | |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3842 void |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3843 gtk_imhtml_clear_formatting(GtkIMHtml *imhtml) |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3844 { |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3845 GtkTextIter start, end; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3846 GObject *object; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3847 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3848 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3849 |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3850 /* Move the selection bounds (to select everything), so the format functions |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3851 * will know we want to manipulate the formatting on the entire buffer. */ |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3852 #if GTK_CHECK_VERSION(2,4,0) |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3853 gtk_text_buffer_select_range(imhtml->text_buffer, &end, &start); |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3854 #else |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3855 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &end); |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3856 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "selection_bound", &start); |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3857 #endif |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3858 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3859 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3860 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3861 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3862 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3863 remove_font_size(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3864 remove_font_face(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3865 remove_font_forecolor(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3866 remove_font_backcolor(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3867 remove_font_background(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3868 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3869 imhtml->edit.bold = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3870 imhtml->edit.italic = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3871 imhtml->edit.underline = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3872 imhtml->edit.strike = 0; |
11315
a74244102c0a
[gaim-migrate @ 13517]
Richard Laager <rlaager@wiktel.com>
parents:
11299
diff
changeset
|
3873 imhtml->edit.fontsize = 0; |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3874 imhtml->edit.forecolor = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3875 imhtml->edit.backcolor = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3876 imhtml->edit.background = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3877 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3878 object = g_object_ref(G_OBJECT(imhtml)); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3879 g_signal_emit(object, signals[CLEAR_FORMAT], 0); |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3880 |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3881 /* Remove the selection, placing the cursor at the end. */ |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3882 #if GTK_CHECK_VERSION(2,4,0) |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3883 gtk_text_buffer_select_range(imhtml->text_buffer, &end, &end); |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3884 #else |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3885 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &end); |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3886 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "selection_bound", &end); |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3887 #endif |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3888 |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3889 gtk_widget_grab_focus(GTK_WIDGET(imhtml)); |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3890 |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3891 g_object_unref(object); |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3892 } |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3893 |
8677 | 3894 /* |
3895 * I had this crazy idea about changing the text cursor color to reflex the foreground color | |
3896 * of the text about to be entered. This is the place you'd do it, along with the place where | |
3897 * we actually set a new foreground color. | |
3898 * I may not do this, because people will bitch about Gaim overriding their gtk theme's cursor | |
3899 * colors. | |
3900 * | |
3901 * Just in case I do do this, I asked about what to set the secondary text cursor to. | |
3902 * | |
8719 | 3903 * (12:45:27) ?? ???: secondary_cursor_color = (rgb(background) + rgb(primary_cursor_color) ) / 2 |
3904 * (12:45:55) ?? ???: understand? | |
8677 | 3905 * (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
|
3906 * (12:46:56) ?? ???: u might need to extract separate each color from RGB |
8677 | 3907 */ |
3908 | |
3909 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, | |
3910 GtkIMHtml *imhtml) | |
3911 { | |
3912 GSList *tags, *l; | |
3913 GtkTextIter iter; | |
3914 | |
3915 if (mark != gtk_text_buffer_get_insert(buffer)) | |
3916 return; | |
3917 | |
3918 if (!gtk_text_buffer_get_char_count(buffer)) | |
3919 return; | |
3920 | |
9924 | 3921 imhtml->edit.bold = imhtml->edit.italic = imhtml->edit.underline = imhtml->edit.strike = FALSE; |
8677 | 3922 if (imhtml->edit.forecolor) |
3923 g_free(imhtml->edit.forecolor); | |
3924 imhtml->edit.forecolor = NULL; | |
3925 if (imhtml->edit.backcolor) | |
3926 g_free(imhtml->edit.backcolor); | |
3927 imhtml->edit.backcolor = NULL; | |
3928 if (imhtml->edit.fontface) | |
3929 g_free(imhtml->edit.fontface); | |
3930 imhtml->edit.fontface = NULL; | |
3931 imhtml->edit.fontsize = 0; | |
3932 imhtml->edit.link = NULL; | |
3933 | |
3934 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3935 | |
3936 | |
3937 if (gtk_text_iter_is_end(&iter)) | |
3938 tags = gtk_text_iter_get_toggled_tags(&iter, FALSE); | |
3939 else | |
3940 tags = gtk_text_iter_get_tags(&iter); | |
3941 | |
3942 for (l = tags; l != NULL; l = l->next) { | |
3943 GtkTextTag *tag = GTK_TEXT_TAG(l->data); | |
3944 | |
3945 if (tag->name) { | |
3946 if (strcmp(tag->name, "BOLD") == 0) | |
3947 imhtml->edit.bold = TRUE; | |
3948 if (strcmp(tag->name, "ITALICS") == 0) | |
3949 imhtml->edit.italic = TRUE; | |
3950 if (strcmp(tag->name, "UNDERLINE") == 0) | |
3951 imhtml->edit.underline = TRUE; | |
9924 | 3952 if (strcmp(tag->name, "STRIKE") == 0) |
3953 imhtml->edit.strike = TRUE; | |
8677 | 3954 if (strncmp(tag->name, "FORECOLOR ", 10) == 0) |
3955 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); | |
3956 if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) | |
3957 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); | |
3958 if (strncmp(tag->name, "FONT FACE ", 10) == 0) | |
3959 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); | |
3960 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) | |
3961 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); | |
8719 | 3962 if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) |
8677 | 3963 imhtml->edit.link = tag; |
3964 } | |
3965 } | |
3966 | |
3967 g_slist_free(tags); | |
3968 } | |
3969 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3970 static void imhtml_toggle_bold(GtkIMHtml *imhtml) |
8061 | 3971 { |
8677 | 3972 GtkTextIter start, end; |
3973 | |
3974 imhtml->edit.bold = !imhtml->edit.bold; | |
3975 | |
3976 if (imhtml->wbfo) { | |
3977 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3978 if (imhtml->edit.bold) | |
3979 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3980 else | |
3981 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3982 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 3983 if (imhtml->edit.bold) |
3984 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3985 else | |
3986 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3987 |
8061 | 3988 } |
3989 } | |
3990 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3991 void gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) |
8061 | 3992 { |
8481 | 3993 GObject *object; |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3994 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3995 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3996 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3997 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3998 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3999 g_object_unref(object); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4000 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4001 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4002 static void imhtml_toggle_italic(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4003 { |
8677 | 4004 GtkTextIter start, end; |
4005 | |
4006 imhtml->edit.italic = !imhtml->edit.italic; | |
4007 | |
4008 if (imhtml->wbfo) { | |
4009 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4010 if (imhtml->edit.italic) | |
4011 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
4012 else | |
4013 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4014 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4015 if (imhtml->edit.italic) |
8677 | 4016 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
4017 else | |
4018 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
8061 | 4019 } |
4020 } | |
4021 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4022 void gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) |
8061 | 4023 { |
8481 | 4024 GObject *object; |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4025 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4026 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4027 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4028 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4029 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4030 g_object_unref(object);} |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4031 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4032 static void imhtml_toggle_underline(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4033 { |
8677 | 4034 GtkTextIter start, end; |
4035 | |
4036 imhtml->edit.underline = !imhtml->edit.underline; | |
4037 | |
4038 if (imhtml->wbfo) { | |
4039 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4040 if (imhtml->edit.underline) | |
4041 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
4042 else | |
4043 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4044 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4045 if (imhtml->edit.underline) |
8677 | 4046 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
4047 else | |
4048 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
8061 | 4049 } |
4050 } | |
4051 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4052 void gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) |
9924 | 4053 { |
4054 GObject *object; | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4055 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4056 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4057 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4058 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4059 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4060 g_object_unref(object); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4061 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4062 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4063 static void imhtml_toggle_strike(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4064 { |
9924 | 4065 GtkTextIter start, end; |
4066 | |
4067 imhtml->edit.strike = !imhtml->edit.strike; | |
4068 | |
4069 if (imhtml->wbfo) { | |
4070 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4071 if (imhtml->edit.strike) | |
4072 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); | |
4073 else | |
4074 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4075 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4076 if (imhtml->edit.strike) |
9924 | 4077 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); |
4078 else | |
4079 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); | |
4080 } | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4081 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4082 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4083 void gtk_imhtml_toggle_strike(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4084 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4085 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4086 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4087 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4088 |
9924 | 4089 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4090 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_STRIKE); |
9924 | 4091 g_object_unref(object); |
4092 } | |
4093 | |
8061 | 4094 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) |
4095 { | |
9025 | 4096 GObject *object; |
8677 | 4097 GtkTextIter start, end; |
8061 | 4098 |
4099 imhtml->edit.fontsize = size; | |
4100 | |
8677 | 4101 if (imhtml->wbfo) { |
4102 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4103 remove_font_size(imhtml, &start, &end, TRUE); | |
4104 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4105 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4106 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4107 remove_font_size(imhtml, &start, &end, FALSE); |
4108 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4109 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4110 } |
8677 | 4111 |
9025 | 4112 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4113 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_SHRINK | GTK_IMHTML_GROW); |
9025 | 4114 g_object_unref(object); |
8061 | 4115 } |
4116 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4117 static void imhtml_font_shrink(GtkIMHtml *imhtml) |
8061 | 4118 { |
8677 | 4119 GtkTextIter start, end; |
4120 | |
8061 | 4121 if (imhtml->edit.fontsize == 1) |
4122 return; | |
4123 | |
8677 | 4124 if (!imhtml->edit.fontsize) |
4125 imhtml->edit.fontsize = 2; | |
4126 else | |
4127 imhtml->edit.fontsize--; | |
4128 | |
4129 if (imhtml->wbfo) { | |
4130 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4131 remove_font_size(imhtml, &start, &end, TRUE); | |
4132 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4133 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4134 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4135 remove_font_size(imhtml, &start, &end, FALSE); |
4136 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4137 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4138 } |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4139 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4140 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4141 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4142 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4143 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4144 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4145 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4146 |
9025 | 4147 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4148 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_SHRINK); |
9025 | 4149 g_object_unref(object); |
8061 | 4150 } |
4151 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4152 static void imhtml_font_grow(GtkIMHtml *imhtml) |
8061 | 4153 { |
8677 | 4154 GtkTextIter start, end; |
4155 | |
8061 | 4156 if (imhtml->edit.fontsize == MAX_FONT_SIZE) |
4157 return; | |
4158 | |
8677 | 4159 if (!imhtml->edit.fontsize) |
4160 imhtml->edit.fontsize = 4; | |
4161 else | |
4162 imhtml->edit.fontsize++; | |
4163 | |
4164 if (imhtml->wbfo) { | |
4165 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4166 remove_font_size(imhtml, &start, &end, TRUE); | |
4167 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4168 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4169 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4170 remove_font_size(imhtml, &start, &end, FALSE); |
4171 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4172 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4173 } |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4174 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4175 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4176 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4177 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4178 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4179 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4180 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4181 |
9025 | 4182 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4183 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_GROW); |
9025 | 4184 g_object_unref(object); |
8061 | 4185 } |
4186 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4187 #define gtk_imhtml_toggle_str_tag(imhtml, color, edit_field, remove_func, find_func, button) { \ |
10776 | 4188 GObject *object; \ |
4189 GtkTextIter start, end; \ | |
4190 \ | |
4191 g_free(edit_field); \ | |
4192 edit_field = NULL; \ | |
4193 \ | |
4194 if (color && strcmp(color, "") != 0) { \ | |
4195 edit_field = g_strdup(color); \ | |
4196 \ | |
4197 if (imhtml->wbfo) { \ | |
4198 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ | |
4199 remove_func(imhtml, &start, &end, TRUE); \ | |
4200 gtk_text_buffer_apply_tag(imhtml->text_buffer, \ | |
4201 find_func(imhtml, edit_field), &start, &end); \ | |
4202 } else { \ | |
4203 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, \ | |
4204 gtk_text_buffer_get_mark(imhtml->text_buffer, "insert")); \ | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4205 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { \ |
10776 | 4206 remove_func(imhtml, &start, &end, FALSE); \ |
4207 gtk_text_buffer_apply_tag(imhtml->text_buffer, \ | |
4208 find_func(imhtml, \ | |
4209 edit_field), \ | |
4210 &start, &end); \ | |
4211 } \ | |
4212 } \ | |
4213 } else { \ | |
4214 if (imhtml->wbfo) { \ | |
4215 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ | |
4216 remove_func(imhtml, &start, &end, TRUE); \ | |
4217 } \ | |
4218 } \ | |
4219 \ | |
4220 object = g_object_ref(G_OBJECT(imhtml)); \ | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4221 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, button); \ |
10776 | 4222 g_object_unref(object); \ |
4223 \ | |
4224 return edit_field != NULL; \ | |
4225 } | |
4226 | |
8061 | 4227 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) |
4228 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4229 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.forecolor, remove_font_forecolor, find_font_forecolor_tag, GTK_IMHTML_FORECOLOR); |
8061 | 4230 } |
4231 | |
4232 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
4233 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4234 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.backcolor, remove_font_backcolor, find_font_backcolor_tag, GTK_IMHTML_BACKCOLOR); |
10776 | 4235 } |
4236 | |
4237 gboolean gtk_imhtml_toggle_background(GtkIMHtml *imhtml, const char *color) | |
4238 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4239 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.background, remove_font_background, find_font_background_tag, GTK_IMHTML_BACKGROUND); |
8061 | 4240 } |
4241 | |
4242 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
4243 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4244 gtk_imhtml_toggle_str_tag(imhtml, face, imhtml->edit.fontface, remove_font_face, find_font_face_tag, GTK_IMHTML_FACE); |
8061 | 4245 } |
4246 | |
8677 | 4247 void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) |
8061 | 4248 { |
9025 | 4249 GObject *object; |
8677 | 4250 GtkTextIter start, end; |
4251 GtkTextTag *linktag; | |
4252 static guint linkno = 0; | |
4253 gchar str[48]; | |
9007 | 4254 GdkColor *color = NULL; |
8677 | 4255 |
4256 imhtml->edit.link = NULL; | |
4257 | |
4258 if (url) { | |
4259 g_snprintf(str, sizeof(str), "LINK %d", linkno++); | |
4260 str[47] = '\0'; | |
4261 | |
9007 | 4262 gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &color, NULL); |
9008 | 4263 if (color) { |
9007 | 4264 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground-gdk", color, "underline", PANGO_UNDERLINE_SINGLE, NULL); |
9008 | 4265 gdk_color_free(color); |
4266 } else { | |
9007 | 4267 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); |
9008 | 4268 } |
8677 | 4269 g_object_set_data_full(G_OBJECT(linktag), "link_url", g_strdup(url), g_free); |
4270 g_signal_connect(G_OBJECT(linktag), "event", G_CALLBACK(tag_event), NULL); | |
4271 | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4272 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4273 remove_font_link(imhtml, &start, &end, FALSE); |
4274 gtk_text_buffer_apply_tag(imhtml->text_buffer, linktag, &start, &end); | |
4275 } | |
4276 } | |
9025 | 4277 |
4278 object = g_object_ref(G_OBJECT(imhtml)); | |
4279 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_LINK); | |
4280 g_object_unref(object); | |
8677 | 4281 } |
4282 | |
4283 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, GtkTextMark *mark, const char *url, const char *text) | |
4284 { | |
8061 | 4285 GtkTextIter iter; |
8677 | 4286 |
9599 | 4287 if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) |
4288 gtk_text_buffer_delete_selection(imhtml->text_buffer, TRUE, TRUE); | |
4289 | |
8677 | 4290 gtk_imhtml_toggle_link(imhtml, url); |
8061 | 4291 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
8677 | 4292 gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); |
4293 gtk_imhtml_toggle_link(imhtml, NULL); | |
8061 | 4294 } |
4295 | |
4296 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
4297 { | |
8677 | 4298 GtkTextMark *mark; |
8061 | 4299 GtkTextIter iter; |
8677 | 4300 |
4301 mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
4302 | |
4303 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
4304 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); | |
4305 } | |
4306 | |
4307 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) | |
4308 { | |
8061 | 4309 GdkPixbuf *pixbuf = NULL; |
4310 GdkPixbufAnimation *annipixbuf = NULL; | |
4311 GtkWidget *icon = NULL; | |
4312 GtkTextChildAnchor *anchor; | |
8505 | 4313 char *unescaped = gaim_unescape_html(smiley); |
8061 | 4314 |
10526 | 4315 if (imhtml->format_functions & GTK_IMHTML_SMILEY) { |
10522 | 4316 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); |
10526 | 4317 if (annipixbuf) { |
4318 if (gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
10522 | 4319 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); |
10526 | 4320 if (pixbuf) |
10522 | 4321 icon = gtk_image_new_from_pixbuf(pixbuf); |
4322 } else { | |
4323 icon = gtk_image_new_from_animation(annipixbuf); | |
4324 } | |
8061 | 4325 } |
4326 } | |
10526 | 4327 #if 0 |
4328 else { | |
4329 GtkIMHtmlSmiley *imhtml_smiley; | |
4330 | |
4331 if (imhtml_smiley->loader) { ; } | |
4332 icon = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU); | |
4333 imhtml_smiley = gtk_get_imhtml_smiley(imhtml, sml, unescaped); | |
4334 if (!imhtml_smiley) { | |
4335 gaim_debug_info("gtkimhtml", "geezz couldnt find smiley struct\n"); | |
4336 } | |
4337 imhtml_smiley->orphan = g_slist_append(imhtml_smiley->orphan, icon); | |
4338 } | |
4339 #endif | |
8061 | 4340 |
4341 if (icon) { | |
8890 | 4342 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
4343 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); | |
4344 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); | |
4345 | |
8061 | 4346 gtk_widget_show(icon); |
4347 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | |
8890 | 4348 } else { |
4349 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); | |
8061 | 4350 } |
8890 | 4351 |
4352 g_free(unescaped); | |
8061 | 4353 } |
4354 | |
8962 | 4355 void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter) |
4356 { | |
4357 GdkPixbuf *pixbuf = NULL; | |
4358 const char *filename = NULL; | |
4359 gpointer image; | |
4360 GdkRectangle rect; | |
4361 GtkIMHtmlScalable *scalable = NULL; | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4362 struct scalable_data *sd; |
8962 | 4363 int minus; |
4364 | |
4365 if (!imhtml->funcs || !imhtml->funcs->image_get || | |
4366 !imhtml->funcs->image_get_size || !imhtml->funcs->image_get_data || | |
4367 !imhtml->funcs->image_get_filename || !imhtml->funcs->image_ref || | |
4368 !imhtml->funcs->image_unref) | |
4369 return; | |
4370 | |
4371 image = imhtml->funcs->image_get(id); | |
4372 | |
4373 if (image) { | |
4374 gpointer data; | |
4375 size_t len; | |
4376 | |
4377 data = imhtml->funcs->image_get_data(image); | |
4378 len = imhtml->funcs->image_get_size(image); | |
4379 | |
4380 if (data && len) { | |
4381 GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); | |
4382 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
4383 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); | |
9337 | 4384 if (pixbuf) |
4385 g_object_ref(G_OBJECT(pixbuf)); | |
8962 | 4386 gdk_pixbuf_loader_close(loader, NULL); |
9337 | 4387 g_object_unref(G_OBJECT(loader)); |
8962 | 4388 } |
4389 | |
4390 } | |
4391 | |
4392 if (pixbuf) { | |
11299
421007f39e53
[gaim-migrate @ 13499]
Richard Laager <rlaager@wiktel.com>
parents:
11276
diff
changeset
|
4393 struct im_image_data *t = g_new(struct im_image_data, 1); |
8962 | 4394 filename = imhtml->funcs->image_get_filename(image); |
4395 imhtml->funcs->image_ref(id); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4396 t->id = id; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4397 t->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4398 imhtml->im_images = g_slist_prepend(imhtml->im_images, t); |
8962 | 4399 } else { |
4400 pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE, | |
4401 GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image"); | |
4402 } | |
4403 | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4404 sd = g_new(struct scalable_data, 1); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4405 sd->scalable = scalable = gtk_imhtml_image_new(pixbuf, filename, id); |
11233
f08d22130bb2
[gaim-migrate @ 13373]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11224
diff
changeset
|
4406 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); |
8962 | 4407 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
4408 scalable->add_to(scalable, imhtml, iter); | |
4409 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + | |
4410 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
4411 scalable->scale(scalable, rect.width - minus, rect.height); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4412 imhtml->scalables = g_list_append(imhtml->scalables, sd); |
8962 | 4413 |
4414 g_object_unref(G_OBJECT(pixbuf)); | |
4415 } | |
4416 | |
8677 | 4417 static const gchar *tag_to_html_start(GtkTextTag *tag) |
8061 | 4418 { |
8677 | 4419 const gchar *name; |
4420 static gchar buf[1024]; | |
4421 | |
4422 name = tag->name; | |
4423 g_return_val_if_fail(name != NULL, ""); | |
4424 | |
4425 if (strcmp(name, "BOLD") == 0) { | |
4426 return "<b>"; | |
4427 } else if (strcmp(name, "ITALICS") == 0) { | |
4428 return "<i>"; | |
4429 } else if (strcmp(name, "UNDERLINE") == 0) { | |
4430 return "<u>"; | |
9924 | 4431 } else if (strcmp(name, "STRIKE") == 0) { |
4432 return "<s>"; | |
8677 | 4433 } else if (strncmp(name, "LINK ", 5) == 0) { |
4434 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); | |
4435 if (tmp) { | |
4436 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); | |
4437 buf[sizeof(buf)-1] = '\0'; | |
4438 return buf; | |
4439 } else { | |
4440 return ""; | |
4441 } | |
4442 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
4443 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); | |
4444 return buf; | |
4445 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
4446 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); | |
4447 return buf; | |
10776 | 4448 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { |
4449 g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]); | |
4450 return buf; | |
8677 | 4451 } else if (strncmp(name, "FONT FACE ", 10) == 0) { |
4452 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); | |
4453 return buf; | |
4454 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
4455 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); | |
4456 return buf; | |
4457 } else { | |
4458 return ""; | |
4459 } | |
8061 | 4460 } |
4461 | |
8677 | 4462 static const gchar *tag_to_html_end(GtkTextTag *tag) |
8061 | 4463 { |
8677 | 4464 const gchar *name; |
4465 | |
4466 name = tag->name; | |
4467 g_return_val_if_fail(name != NULL, ""); | |
4468 | |
4469 if (strcmp(name, "BOLD") == 0) { | |
4470 return "</b>"; | |
4471 } else if (strcmp(name, "ITALICS") == 0) { | |
4472 return "</i>"; | |
4473 } else if (strcmp(name, "UNDERLINE") == 0) { | |
4474 return "</u>"; | |
9924 | 4475 } else if (strcmp(name, "STRIKE") == 0) { |
4476 return "</s>"; | |
8677 | 4477 } else if (strncmp(name, "LINK ", 5) == 0) { |
4478 return "</a>"; | |
4479 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
4480 return "</font>"; | |
4481 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
4482 return "</font>"; | |
10776 | 4483 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { |
4484 return "</body>"; | |
8677 | 4485 } else if (strncmp(name, "FONT FACE ", 10) == 0) { |
4486 return "</font>"; | |
4487 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
4488 return "</font>"; | |
4489 } else { | |
4490 return ""; | |
4491 } | |
4492 } | |
4493 | |
4494 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) | |
4495 { | |
4496 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && | |
4497 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || | |
4498 gtk_text_iter_is_end(niter)); | |
8061 | 4499 } |
4500 | |
4501 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | |
4502 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | |
8677 | 4503 * check for tags that are toggled on, insert their html form, and push them on the queue. Then insert |
4504 * 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
|
4505 * Finally, replace <, >, &, and " with their HTML equivalent. |
8677 | 4506 */ |
8061 | 4507 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
4508 { | |
4509 gunichar c; | |
8677 | 4510 GtkTextIter iter, nextiter; |
8061 | 4511 GString *str = g_string_new(""); |
8677 | 4512 GSList *tags, *sl; |
4513 GQueue *q, *r; | |
4514 GtkTextTag *tag; | |
4515 | |
4516 q = g_queue_new(); | |
4517 r = g_queue_new(); | |
4518 | |
8061 | 4519 |
4520 gtk_text_iter_order(start, end); | |
8677 | 4521 nextiter = iter = *start; |
4522 gtk_text_iter_forward_char(&nextiter); | |
4523 | |
9071 | 4524 /* First add the tags that are already in progress (we don't care about non-printing tags)*/ |
8677 | 4525 tags = gtk_text_iter_get_tags(start); |
4526 | |
4527 for (sl = tags; sl; sl = sl->next) { | |
4528 tag = sl->data; | |
4529 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { | |
9071 | 4530 if (strlen(tag_to_html_end(tag)) > 0) |
4531 g_string_append(str, tag_to_html_start(tag)); | |
8677 | 4532 g_queue_push_tail(q, tag); |
8061 | 4533 } |
4534 } | |
8677 | 4535 g_slist_free(tags); |
8061 | 4536 |
4537 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
8677 | 4538 |
4539 tags = gtk_text_iter_get_tags(&iter); | |
4540 | |
4541 for (sl = tags; sl; sl = sl->next) { | |
4542 tag = sl->data; | |
4543 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { | |
9071 | 4544 if (strlen(tag_to_html_end(tag)) > 0) |
4545 g_string_append(str, tag_to_html_start(tag)); | |
8677 | 4546 g_queue_push_tail(q, tag); |
4547 } | |
4548 } | |
4549 | |
4550 | |
8061 | 4551 if (c == 0xFFFC) { |
4552 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | |
9071 | 4553 if (anchor) { |
4554 char *text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext"); | |
4555 if (text) | |
4556 str = g_string_append(str, text); | |
4557 } | |
8677 | 4558 } else if (c == '<') { |
4559 str = g_string_append(str, "<"); | |
4560 } else if (c == '>') { | |
4561 str = g_string_append(str, ">"); | |
4562 } else if (c == '&') { | |
4563 str = g_string_append(str, "&"); | |
4564 } else if (c == '"') { | |
4565 str = g_string_append(str, """); | |
4566 } else if (c == '\n') { | |
4567 str = g_string_append(str, "<br>"); | |
8061 | 4568 } else { |
8677 | 4569 str = g_string_append_unichar(str, c); |
4570 } | |
4571 | |
4572 tags = g_slist_reverse(tags); | |
4573 for (sl = tags; sl; sl = sl->next) { | |
4574 tag = sl->data; | |
9071 | 4575 /** don't worry about non-printing tags ending */ |
4576 if (tag_ends_here(tag, &iter, &nextiter) && strlen(tag_to_html_end(tag)) > 0) { | |
8677 | 4577 |
4578 GtkTextTag *tmp; | |
4579 | |
4580 while ((tmp = g_queue_pop_tail(q)) != tag) { | |
4581 if (tmp == NULL) | |
4582 break; | |
4583 | |
9071 | 4584 if (!tag_ends_here(tmp, &iter, &nextiter) && strlen(tag_to_html_end(tmp)) > 0) |
8677 | 4585 g_queue_push_tail(r, tmp); |
4586 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); | |
4587 } | |
4588 | |
4589 if (tmp == NULL) | |
4590 gaim_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); | |
4591 else | |
4592 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
4593 | |
4594 while ((tmp = g_queue_pop_head(r))) { | |
4595 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); | |
4596 g_queue_push_tail(q, tmp); | |
8061 | 4597 } |
4598 } | |
4599 } | |
8677 | 4600 |
4601 g_slist_free(tags); | |
8061 | 4602 gtk_text_iter_forward_char(&iter); |
8677 | 4603 gtk_text_iter_forward_char(&nextiter); |
8061 | 4604 } |
8677 | 4605 |
4606 while ((tag = g_queue_pop_tail(q))) | |
4607 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
4608 | |
4609 g_queue_free(q); | |
4610 g_queue_free(r); | |
8061 | 4611 return g_string_free(str, FALSE); |
4612 } | |
4613 | |
8698 | 4614 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter) |
8061 | 4615 { |
4616 if (imhtml->edit.bold) | |
4617 gtk_imhtml_toggle_bold(imhtml); | |
4618 | |
4619 if (imhtml->edit.italic) | |
4620 gtk_imhtml_toggle_italic(imhtml); | |
4621 | |
4622 if (imhtml->edit.underline) | |
4623 gtk_imhtml_toggle_underline(imhtml); | |
4624 | |
9924 | 4625 if (imhtml->edit.strike) |
4626 gtk_imhtml_toggle_strike(imhtml); | |
4627 | |
8061 | 4628 if (imhtml->edit.forecolor) |
4629 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
4630 | |
4631 if (imhtml->edit.backcolor) | |
4632 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
4633 | |
4634 if (imhtml->edit.fontface) | |
4635 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
4636 | |
8677 | 4637 imhtml->edit.fontsize = 0; |
4638 | |
8719 | 4639 if (imhtml->edit.link) |
4640 gtk_imhtml_toggle_link(imhtml, NULL); | |
4641 | |
8698 | 4642 gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter); |
8061 | 4643 |
4644 } | |
4645 | |
4646 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
4647 { | |
4648 GtkTextIter start, end; | |
4649 | |
4650 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
4651 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
4652 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
4653 } | |
4654 | |
8677 | 4655 char **gtk_imhtml_get_markup_lines(GtkIMHtml *imhtml) |
4656 { | |
4657 int i, j, lines; | |
4658 GtkTextIter start, end; | |
4659 char **ret; | |
4660 | |
4661 lines = gtk_text_buffer_get_line_count(imhtml->text_buffer); | |
4662 ret = g_new0(char *, lines + 1); | |
4663 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
4664 end = start; | |
4665 gtk_text_iter_forward_to_line_end(&end); | |
4666 | |
4667 for (i = 0, j = 0; i < lines; i++) { | |
9612 | 4668 if (gtk_text_iter_get_char(&start) != '\n') { |
4669 ret[j] = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
4670 if (ret[j] != NULL) | |
4671 j++; | |
4672 } | |
4673 | |
8677 | 4674 gtk_text_iter_forward_line(&start); |
4675 end = start; | |
4676 gtk_text_iter_forward_to_line_end(&end); | |
4677 } | |
4678 | |
4679 return ret; | |
4680 } | |
4681 | |
4682 char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop) | |
8061 | 4683 { |
8519 | 4684 GString *str = g_string_new(""); |
4685 GtkTextIter iter, end; | |
4686 gunichar c; | |
4687 | |
8677 | 4688 if (start == NULL) |
4689 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
4690 else | |
4691 iter = *start; | |
4692 | |
4693 if (stop == NULL) | |
4694 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
4695 else | |
4696 end = *stop; | |
4697 | |
4698 gtk_text_iter_order(&iter, &end); | |
8519 | 4699 |
4700 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { | |
4701 if (c == 0xFFFC) { | |
8677 | 4702 GtkTextChildAnchor* anchor; |
4703 char *text = NULL; | |
4704 | |
4705 anchor = gtk_text_iter_get_child_anchor(&iter); | |
4706 if (anchor) | |
8698 | 4707 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_plaintext"); |
8677 | 4708 if (text) |
4709 str = g_string_append(str, text); | |
8519 | 4710 } else { |
4711 g_string_append_unichar(str, c); | |
4712 } | |
4713 gtk_text_iter_forward_char(&iter); | |
4714 } | |
4715 | |
4716 return g_string_free(str, FALSE); | |
8061 | 4717 } |
8962 | 4718 |
4719 void gtk_imhtml_set_funcs(GtkIMHtml *imhtml, GtkIMHtmlFuncs *f) | |
4720 { | |
4721 g_return_if_fail(imhtml != NULL); | |
4722 imhtml->funcs = f; | |
4723 } |