Mercurial > pidgin
annotate src/gtkimhtml.c @ 11307:e1c55e65ab8e
[gaim-migrate @ 13507]
Patch #1262343, from Levi Bard
"Allows you to specify, on a per-rule basis, whether
text replacement rules will apply to all text, or only
to entire words (the current method).
It defaults to the old method unless specified otherwise.
It reads the old-format config files ( ~/.gaim/dict ),
and saves to the new format (which is currently very
similar to the old)."
The configuration file format is compatible in both directions. Obviously, subword replacement won't happen with an old copy of this plugin, but it won't fail parsing the configuration file.
Plus, he found that my logic was backwards in the test that I used to remove the g_assert().
I made a few changes as well. A couple that I remember:
- A number of rules weren't doing anything because the plugin didn't support them. With this patch, they are functional now. I enabled all of them to use subword completion.
- Set a size group on the labels in the prefs frame. That's been driving me nuts for a while.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Fri, 19 Aug 2005 04:30:50 +0000 |
parents | 421007f39e53 |
children | a74244102c0a |
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), | |
1233 G_SIGNAL_RUN_FIRST, | |
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); |
1278 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); | |
1279 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); | |
1428 | 1280 } |
1281 | |
3922 | 1282 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1428 | 1283 { |
3922 | 1284 GtkTextIter iter; |
1285 imhtml->text_buffer = gtk_text_buffer_new(NULL); | |
1286 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | |
1287 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
5105 | 1288 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
3922 | 1289 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
8677 | 1290 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); |
1291 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(imhtml), 2); | |
8061 | 1292 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
3922 | 1293 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
8061 | 1294 |
3922 | 1295 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
8932 | 1296 * other tags (color, size, face, etc.) will have to be created and applied dynamically |
9924 | 1297 * Note that even though we created SUB, SUP, and PRE tags here, we don't really |
8932 | 1298 * apply them anywhere yet. */ |
3922 | 1299 gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL); |
1300 gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL); | |
1301 gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
1302 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | |
1303 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | |
1304 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | |
1305 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | |
7295 | 1306 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
8677 | 1307 |
3922 | 1308 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
1309 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | |
1310 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | |
8061 | 1311 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
2993 | 1312 |
6124 | 1313 imhtml->show_comments = TRUE; |
4253 | 1314 |
4892 | 1315 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 1316 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4032 | 1317 imhtml->default_smilies = gtk_smiley_tree_new(); |
4735 | 1318 |
4944 | 1319 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
4735 | 1320 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
4944 | 1321 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
|
1322 g_signal_connect(G_OBJECT(imhtml), "enter-notify-event", G_CALLBACK(gtk_enter_event_notify), NULL); |
10844 | 1323 #if (!GTK_CHECK_VERSION(2,2,0)) |
1324 /* See the comment for gtk_key_pressed_cb */ | |
6066 | 1325 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
10844 | 1326 #endif |
8677 | 1327 g_signal_connect(G_OBJECT(imhtml), "button_press_event", G_CALLBACK(gtk_imhtml_button_press_event), NULL); |
1328 g_signal_connect(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(preinsert_cb), imhtml); | |
8061 | 1329 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
10169 | 1330 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-child-anchor", G_CALLBACK(insert_ca_cb), imhtml); |
8091 | 1331 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, |
1332 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | |
1333 GDK_ACTION_COPY); | |
1334 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | |
9300 | 1335 g_signal_connect(G_OBJECT(imhtml), "drag_drop", G_CALLBACK(gtk_imhtml_link_drop_cb), imhtml); |
8091 | 1336 |
7353 | 1337 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
8698 | 1338 g_signal_connect(G_OBJECT(imhtml), "cut-clipboard", G_CALLBACK(cut_clipboard_cb), NULL); |
8061 | 1339 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
8677 | 1340 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
|
1341 g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); |
8677 | 1342 |
1343 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
1344 G_CALLBACK(mark_set_so_update_selection_cb), imhtml); | |
1345 | |
10946
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
1346 gtk_widget_add_events(GTK_WIDGET(imhtml), |
2d30f151146d
[gaim-migrate @ 12742]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10936
diff
changeset
|
1347 GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK); |
4735 | 1348 |
8681 | 1349 imhtml->clipboard_text_string = NULL; |
1350 imhtml->clipboard_html_string = NULL; | |
1351 | |
4735 | 1352 imhtml->tip = NULL; |
1353 imhtml->tip_timer = 0; | |
1354 imhtml->tip_window = NULL; | |
4895 | 1355 |
8677 | 1356 imhtml->edit.bold = FALSE; |
1357 imhtml->edit.italic = FALSE; | |
1358 imhtml->edit.underline = FALSE; | |
8061 | 1359 imhtml->edit.forecolor = NULL; |
1360 imhtml->edit.backcolor = NULL; | |
1361 imhtml->edit.fontface = NULL; | |
8677 | 1362 imhtml->edit.fontsize = 0; |
1363 imhtml->edit.link = NULL; | |
1364 | |
9300 | 1365 |
4895 | 1366 imhtml->scalables = NULL; |
8061 | 1367 |
1368 gtk_imhtml_set_editable(imhtml, FALSE); | |
8931 | 1369 g_signal_connect(G_OBJECT(imhtml), "populate-popup", |
1370 G_CALLBACK(hijack_menu_cb), NULL); | |
1371 | |
8692 | 1372 #ifdef _WIN32 |
1373 /* Register HTML Format as desired clipboard format */ | |
1374 win_html_fmt = RegisterClipboardFormat("HTML Format"); | |
1375 #endif | |
2993 | 1376 } |
1377 | |
3922 | 1378 GtkWidget *gtk_imhtml_new(void *a, void *b) |
1428 | 1379 { |
4635 | 1380 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
1428 | 1381 } |
1382 | |
9037 | 1383 GType gtk_imhtml_get_type() |
1428 | 1384 { |
9037 | 1385 static GType imhtml_type = 0; |
1428 | 1386 |
1387 if (!imhtml_type) { | |
9037 | 1388 static const GTypeInfo imhtml_info = { |
4635 | 1389 sizeof(GtkIMHtmlClass), |
1390 NULL, | |
1391 NULL, | |
1392 (GClassInitFunc) gtk_imhtml_class_init, | |
1393 NULL, | |
1394 NULL, | |
1428 | 1395 sizeof (GtkIMHtml), |
4635 | 1396 0, |
1397 (GInstanceInitFunc) gtk_imhtml_init | |
1428 | 1398 }; |
4635 | 1399 |
1400 imhtml_type = g_type_register_static(gtk_text_view_get_type(), | |
1401 "GtkIMHtml", &imhtml_info, 0); | |
1428 | 1402 } |
1403 | |
1404 return imhtml_type; | |
1405 } | |
1406 | |
4417 | 1407 struct url_data { |
1408 GObject *object; | |
1409 gchar *url; | |
1410 }; | |
1411 | |
8677 | 1412 static void url_data_destroy(gpointer mydata) |
1413 { | |
1414 struct url_data *data = mydata; | |
1415 g_object_unref(data->object); | |
1416 g_free(data->url); | |
1417 g_free(data); | |
1418 } | |
1419 | |
4417 | 1420 static void url_open(GtkWidget *w, struct url_data *data) { |
1421 if(!data) return; | |
8061 | 1422 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
7988 | 1423 |
4417 | 1424 } |
5582 | 1425 |
4417 | 1426 static void url_copy(GtkWidget *w, gchar *url) { |
1427 GtkClipboard *clipboard; | |
1428 | |
8931 | 1429 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY); |
4417 | 1430 gtk_clipboard_set_text(clipboard, url, -1); |
5582 | 1431 |
8931 | 1432 clipboard = gtk_widget_get_clipboard(w, GDK_SELECTION_CLIPBOARD); |
5582 | 1433 gtk_clipboard_set_text(clipboard, url, -1); |
4417 | 1434 } |
1435 | |
1436 /* The callback for an event on a link tag. */ | |
10871 | 1437 static gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) { |
4417 | 1438 GdkEventButton *event_button = (GdkEventButton *) event; |
8061 | 1439 if (GTK_IMHTML(imhtml)->editable) |
1440 return FALSE; | |
3922 | 1441 if (event->type == GDK_BUTTON_RELEASE) { |
8957 | 1442 if ((event_button->button == 1) || (event_button->button == 2)) { |
4417 | 1443 GtkTextIter start, end; |
1444 /* we shouldn't open a URL if the user has selected something: */ | |
8677 | 1445 if (gtk_text_buffer_get_selection_bounds( |
1446 gtk_text_iter_get_buffer(arg2), &start, &end)) | |
4417 | 1447 return FALSE; |
1448 | |
1449 /* A link was clicked--we emit the "url_clicked" signal | |
1450 * with the URL as the argument */ | |
8677 | 1451 g_object_ref(G_OBJECT(tag)); |
1452 g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url")); | |
1453 g_object_unref(G_OBJECT(tag)); | |
4417 | 1454 return FALSE; |
1455 } else if(event_button->button == 3) { | |
4745 | 1456 GtkWidget *img, *item, *menu; |
4417 | 1457 struct url_data *tempdata = g_new(struct url_data, 1); |
5091 | 1458 tempdata->object = g_object_ref(imhtml); |
8677 | 1459 tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url")); |
4745 | 1460 |
5091 | 1461 /* Don't want the tooltip around if user right-clicked on link */ |
1462 if (GTK_IMHTML(imhtml)->tip_window) { | |
1463 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | |
1464 GTK_IMHTML(imhtml)->tip_window = NULL; | |
1465 } | |
1466 if (GTK_IMHTML(imhtml)->tip_timer) { | |
1467 g_source_remove(GTK_IMHTML(imhtml)->tip_timer); | |
1468 GTK_IMHTML(imhtml)->tip_timer = 0; | |
1469 } | |
8061 | 1470 if (GTK_IMHTML(imhtml)->editable) |
1471 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | |
1472 else | |
1473 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | |
4417 | 1474 menu = gtk_menu_new(); |
8677 | 1475 g_object_set_data_full(G_OBJECT(menu), "x-imhtml-url-data", tempdata, url_data_destroy); |
4745 | 1476 |
4417 | 1477 /* buttons and such */ |
1478 | |
8677 | 1479 if (!strncmp(tempdata->url, "mailto:", 7)) |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1480 { |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1481 /* Copy E-Mail Address */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1482 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1483 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1484 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1485 _("_Copy E-Mail Address")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1486 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
|
1487 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1488 G_CALLBACK(url_copy), tempdata->url + 7); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1489 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1490 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1491 else |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1492 { |
10936 | 1493 /* Open Link in Browser */ |
1494 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, | |
1495 GTK_ICON_SIZE_MENU); | |
1496 item = gtk_image_menu_item_new_with_mnemonic( | |
1497 _("_Open Link in Browser")); | |
1498 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
1499 g_signal_connect(G_OBJECT(item), "activate", | |
1500 G_CALLBACK(url_open), tempdata); | |
1501 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
1502 | |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1503 /* Copy Link Location */ |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1504 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1505 GTK_ICON_SIZE_MENU); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1506 item = gtk_image_menu_item_new_with_mnemonic( |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1507 _("_Copy Link Location")); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1508 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
|
1509 g_signal_connect(G_OBJECT(item), "activate", |
8677 | 1510 G_CALLBACK(url_copy), tempdata->url); |
7140
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1511 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1512 } |
48cc5d5d5a6c
[gaim-migrate @ 7707]
Christian Hammond <chipx86@chipx86.com>
parents:
6982
diff
changeset
|
1513 |
4756 | 1514 |
4417 | 1515 gtk_widget_show_all(menu); |
4756 | 1516 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
1517 event_button->button, event_button->time); | |
4745 | 1518 |
4417 | 1519 return TRUE; |
1520 } | |
1428 | 1521 } |
4417 | 1522 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) |
1523 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
1524 be caught by the regular GtkTextView menu */ | |
1525 else | |
1526 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
1428 | 1527 } |
1528 | |
9300 | 1529 static gboolean |
1530 gtk_text_view_drag_motion (GtkWidget *widget, | |
1531 GdkDragContext *context, | |
1532 gint x, | |
1533 gint y, | |
1534 guint time) | |
1535 { | |
1536 GdkDragAction suggested_action = 0; | |
1537 | |
10145 | 1538 if (gtk_drag_dest_find_target (widget, context, NULL) == GDK_NONE) { |
9300 | 1539 /* can't accept any of the offered targets */ |
1540 } else { | |
1541 GtkWidget *source_widget; | |
1542 suggested_action = context->suggested_action; | |
1543 source_widget = gtk_drag_get_source_widget (context); | |
1544 if (source_widget == widget) { | |
1545 /* Default to MOVE, unless the user has | |
1546 * pressed ctrl or alt to affect available actions | |
1547 */ | |
1548 if ((context->actions & GDK_ACTION_MOVE) != 0) | |
1549 suggested_action = GDK_ACTION_MOVE; | |
1550 } | |
1551 } | |
1552 | |
10145 | 1553 gdk_drag_status (context, suggested_action, time); |
9300 | 1554 |
1555 /* TRUE return means don't propagate the drag motion to parent | |
1556 * widgets that may also be drop sites. | |
1557 */ | |
1558 return TRUE; | |
1559 } | |
1560 | |
1561 static void | |
1562 gtk_imhtml_link_drop_cb(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data) | |
1563 { | |
1564 GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL); | |
1565 | |
1566 if (target != GDK_NONE) | |
1567 gtk_drag_get_data (widget, context, target, time); | |
1568 else | |
1569 gtk_drag_finish (context, FALSE, FALSE, time); | |
1570 | |
1571 return; | |
1572 } | |
1573 | |
8091 | 1574 static void |
1575 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
11143 | 1576 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) |
8091 | 1577 { |
9300 | 1578 gchar **links; |
1579 gchar *link; | |
11143 | 1580 char *text = (char *)sd->data; |
9300 | 1581 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); |
1582 GtkTextIter iter; | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1583 gint i = 0; |
9300 | 1584 |
1585 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
1586 | |
8091 | 1587 if(gtk_imhtml_get_editable(imhtml) && sd->data){ |
9300 | 1588 switch (info) { |
10145 | 1589 case GTK_IMHTML_DRAG_URL: |
11143 | 1590 /* TODO: Is it really ok to change sd->data...? */ |
1591 gaim_str_strip_cr((char *)sd->data); | |
1592 | |
1593 links = g_strsplit((char *)sd->data, "\n", 0); | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1594 while((link = links[i]) != NULL){ |
9300 | 1595 if(gaim_str_has_prefix(link, "http://") || |
1596 gaim_str_has_prefix(link, "https://") || | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1597 gaim_str_has_prefix(link, "ftp://")) |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1598 { |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1599 gchar *label; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1600 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1601 if(links[i + 1]) |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1602 i++; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1603 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1604 label = links[i]; |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1605 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1606 gtk_imhtml_insert_link(imhtml, mark, link, label); |
9300 | 1607 } else if (link=='\0') { |
1608 /* Ignore blank lines */ | |
1609 } else { | |
1610 /* Special reasons, aka images being put in via other tag, etc. */ | |
10345 | 1611 /* ... don't pretend we handled it if we didn't */ |
1612 gtk_drag_finish(dc, FALSE, FALSE, t); | |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1613 g_strfreev(links); |
10345 | 1614 return; |
9300 | 1615 } |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1616 |
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1617 i++; |
8091 | 1618 } |
10782
93fd90cbf45c
[gaim-migrate @ 12410]
Luke Schierer <lschiere@pidgin.im>
parents:
10777
diff
changeset
|
1619 g_strfreev(links); |
9300 | 1620 break; |
10145 | 1621 case GTK_IMHTML_DRAG_HTML: |
10243 | 1622 { |
1623 char *utf8 = NULL; | |
1624 /* Ewww. This is all because mozilla thinks that text/html is 'for internal use only.' | |
1625 * as explained by this comment in gtkhtml: | |
1626 * | |
1627 * FIXME This hack decides the charset of the selection. It seems that | |
1628 * mozilla/netscape alway use ucs2 for text/html | |
1629 * and openoffice.org seems to always use utf8 so we try to validate | |
1630 * the string as utf8 and if that fails we assume it is ucs2 | |
1631 * | |
1632 * See also the comment on text/html here: | |
1633 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html | |
1634 */ | |
1635 if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) { | |
1636 utf8 = g_convert(text, sd->length, "UTF-8", "UCS-2", NULL, NULL, NULL); | |
1637 | |
1638 if (!utf8) { | |
9300 | 1639 gaim_debug_warning("gtkimhtml", "g_convert from UCS-2 failed in drag_rcv_cb\n"); |
1640 return; | |
1641 } | |
10243 | 1642 |
1643 if (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe || TRUE) { | |
1644 char *tmp; | |
1645 tmp = g_utf8_next_char(utf8); | |
1646 memmove(utf8, tmp, strlen(tmp) + 1); | |
1647 } | |
1648 } else if (!(*text) || !g_utf8_validate(text, -1, NULL)) { | |
9300 | 1649 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in drag_rcv_cb\n"); |
1650 return; | |
1651 } | |
10243 | 1652 |
1653 gtk_imhtml_insert_html_at_iter(imhtml, utf8 ? utf8 : text, 0, &iter); | |
1654 g_free(utf8); | |
9300 | 1655 break; |
10243 | 1656 } |
10145 | 1657 case GTK_IMHTML_DRAG_TEXT: |
1658 if (!(*text) || !g_utf8_validate(text, -1, NULL)) { | |
1659 gaim_debug_warning("gtkimhtml", "empty string or invalid UTF-8 in drag_rcv_cb\n"); | |
1660 return; | |
1661 } else { | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10699
diff
changeset
|
1662 char *tmp = g_markup_escape_text(text, -1); |
10145 | 1663 gtk_imhtml_insert_html_at_iter(imhtml, tmp, 0, &iter); |
1664 g_free(tmp); | |
1665 } | |
1666 break; | |
9300 | 1667 default: |
10145 | 1668 gtk_drag_finish(dc, FALSE, FALSE, t); |
1669 return; | |
8091 | 1670 } |
1671 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
1672 } else { | |
1673 gtk_drag_finish(dc, FALSE, FALSE, t); | |
1674 } | |
1675 } | |
1676 | |
4298 | 1677 /* this isn't used yet |
9300 | 1678 static void gtk_smiley_tree_remove (GtkSmileyTree *tree, |
4263 | 1679 GtkIMHtmlSmiley *smiley) |
4032 | 1680 { |
1681 GtkSmileyTree *t = tree; | |
4263 | 1682 const gchar *x = smiley->smile; |
4032 | 1683 gint len = 0; |
1684 | |
1685 while (*x) { | |
1686 gchar *pos; | |
1687 | |
1688 if (!t->values) | |
1689 return; | |
1690 | |
1691 pos = strchr (t->values->str, *x); | |
1692 if (pos) | |
1693 t = t->children [(int) pos - (int) t->values->str]; | |
1694 else | |
1695 return; | |
1696 | |
1697 x++; len++; | |
1698 } | |
1699 | |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1700 if (t->image) { |
4032 | 1701 t->image = NULL; |
4141
ccec4fde84f4
[gaim-migrate @ 4359]
Christian Hammond <chipx86@chipx86.com>
parents:
4140
diff
changeset
|
1702 } |
4032 | 1703 } |
4298 | 1704 */ |
1705 | |
4032 | 1706 |
1707 static gint | |
1708 gtk_smiley_tree_lookup (GtkSmileyTree *tree, | |
1709 const gchar *text) | |
1710 { | |
1711 GtkSmileyTree *t = tree; | |
1712 const gchar *x = text; | |
1713 gint len = 0; | |
8505 | 1714 gchar *amp; |
1715 gint alen; | |
4032 | 1716 |
1717 while (*x) { | |
1718 gchar *pos; | |
1719 | |
1720 if (!t->values) | |
1721 break; | |
1722 | |
8505 | 1723 if(*x == '&' && gtk_imhtml_is_amp_escape(x, &, &alen)) { |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1724 gboolean matched = TRUE; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1725 /* Make sure all chars of the unescaped value match */ |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1726 while (*(amp + 1)) { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1727 pos = strchr (t->values->str, *amp); |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1728 if (pos) |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1729 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
|
1730 else { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1731 matched = FALSE; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1732 break; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1733 } |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1734 amp++; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1735 } |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1736 if (!matched) |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1737 break; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1738 |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1739 pos = strchr (t->values->str, *amp); |
8505 | 1740 } |
9636 | 1741 else if (*x == '<') /* Because we're all WYSIWYG now, a '<' |
1742 * char should only appear as the start of a tag. Perhaps a safer (but costlier) | |
1743 * check would be to call gtk_imhtml_is_tag on it */ | |
10600 | 1744 break; |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1745 else { |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1746 alen = 1; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1747 pos = strchr (t->values->str, *x); |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1748 } |
8505 | 1749 |
4032 | 1750 if (pos) |
7371 | 1751 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1752 else |
1753 break; | |
1754 | |
10865
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1755 x += alen; |
c28766b87f64
[gaim-migrate @ 12549]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10858
diff
changeset
|
1756 len += alen; |
4032 | 1757 } |
1758 | |
1759 if (t->image) | |
1760 return len; | |
1761 | |
1762 return 0; | |
1763 } | |
1764 | |
1765 void | |
4263 | 1766 gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, |
10537 | 1767 const gchar *sml, |
4263 | 1768 GtkIMHtmlSmiley *smiley) |
4032 | 1769 { |
1770 GtkSmileyTree *tree; | |
1771 g_return_if_fail (imhtml != NULL); | |
1772 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
7371 | 1773 |
4032 | 1774 if (sml == NULL) |
1775 tree = imhtml->default_smilies; | |
1776 else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { | |
1777 } else { | |
1778 tree = gtk_smiley_tree_new(); | |
4892 | 1779 g_hash_table_insert(imhtml->smiley_data, g_strdup(sml), tree); |
4032 | 1780 } |
1781 | |
4263 | 1782 gtk_smiley_tree_insert (tree, smiley); |
4032 | 1783 } |
1784 | |
1785 static gboolean | |
1786 gtk_imhtml_is_smiley (GtkIMHtml *imhtml, | |
1787 GSList *fonts, | |
1788 const gchar *text, | |
1789 gint *len) | |
1790 { | |
1791 GtkSmileyTree *tree; | |
5967 | 1792 GtkIMHtmlFontDetail *font; |
4032 | 1793 char *sml = NULL; |
1794 | |
1795 if (fonts) { | |
1796 font = fonts->data; | |
1797 sml = font->sml; | |
1798 } | |
1799 | |
9029 | 1800 if (!sml) |
1801 sml = imhtml->protocol_name; | |
1802 | |
1803 if (!sml || !(tree = g_hash_table_lookup(imhtml->smiley_data, sml))) | |
4032 | 1804 tree = imhtml->default_smilies; |
9029 | 1805 |
4032 | 1806 if (tree == NULL) |
1807 return FALSE; | |
7371 | 1808 |
8505 | 1809 *len = gtk_smiley_tree_lookup (tree, text); |
4032 | 1810 return (*len > 0); |
1811 } | |
1812 | |
10526 | 1813 GtkIMHtmlSmiley * |
1814 gtk_imhtml_smiley_get(GtkIMHtml *imhtml, | |
1815 const gchar *sml, | |
1816 const gchar *text) | |
4032 | 1817 { |
1818 GtkSmileyTree *t; | |
1819 const gchar *x = text; | |
1820 if (sml == NULL) | |
1821 t = imhtml->default_smilies; | |
7371 | 1822 else |
4032 | 1823 t = g_hash_table_lookup(imhtml->smiley_data, sml); |
7371 | 1824 |
4032 | 1825 |
1826 if (t == NULL) | |
10526 | 1827 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1828 |
1829 while (*x) { | |
1830 gchar *pos; | |
1831 | |
1832 if (!t->values) { | |
10526 | 1833 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1834 } |
7371 | 1835 |
4032 | 1836 pos = strchr (t->values->str, *x); |
1837 if (pos) { | |
7371 | 1838 t = t->children [GPOINTER_TO_INT(pos) - GPOINTER_TO_INT(t->values->str)]; |
4032 | 1839 } else { |
10526 | 1840 return sml ? gtk_imhtml_smiley_get(imhtml, NULL, text) : NULL; |
4032 | 1841 } |
1842 x++; | |
1843 } | |
1844 | |
10526 | 1845 return t->image; |
1846 } | |
1847 | |
1848 GdkPixbufAnimation * | |
1849 gtk_smiley_tree_image (GtkIMHtml *imhtml, | |
1850 const gchar *sml, | |
1851 const gchar *text) | |
1852 { | |
1853 | |
1854 GtkIMHtmlSmiley *smiley; | |
1855 | |
1856 smiley = gtk_imhtml_smiley_get(imhtml,sml,text); | |
1857 | |
1858 if (!smiley) | |
8890 | 1859 return NULL; |
1860 | |
10526 | 1861 if (!smiley->icon && smiley->file) { |
1862 smiley->icon = gdk_pixbuf_animation_new_from_file(smiley->file, NULL); | |
1863 } else if (!smiley->icon && smiley->loader) { | |
1864 smiley->icon = gdk_pixbuf_loader_get_animation(smiley->loader); | |
1865 if (smiley->icon) | |
1866 g_object_ref(G_OBJECT(smiley->icon)); | |
1867 } | |
1868 | |
1869 return smiley->icon; | |
4032 | 1870 } |
8890 | 1871 |
4793 | 1872 #define VALID_TAG(x) if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ |
3922 | 1873 *tag = g_strndup (string, strlen (x)); \ |
1874 *len = strlen (x) + 1; \ | |
1875 return TRUE; \ | |
1876 } \ | |
1877 (*type)++ | |
1428 | 1878 |
4793 | 1879 #define VALID_OPT_TAG(x) if (!g_ascii_strncasecmp (string, x " ", strlen (x " "))) { \ |
3922 | 1880 const gchar *c = string + strlen (x " "); \ |
1881 gchar e = '"'; \ | |
1882 gboolean quote = FALSE; \ | |
1883 while (*c) { \ | |
1884 if (*c == '"' || *c == '\'') { \ | |
1885 if (quote && (*c == e)) \ | |
1886 quote = !quote; \ | |
1887 else if (!quote) { \ | |
1888 quote = !quote; \ | |
1889 e = *c; \ | |
1890 } \ | |
1891 } else if (!quote && (*c == '>')) \ | |
1892 break; \ | |
1893 c++; \ | |
1894 } \ | |
1895 if (*c) { \ | |
1896 *tag = g_strndup (string, c - string); \ | |
1897 *len = c - string + 1; \ | |
1898 return TRUE; \ | |
1899 } \ | |
1900 } \ | |
1901 (*type)++ | |
1428 | 1902 |
1903 | |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1904 static gboolean |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1905 gtk_imhtml_is_amp_escape (const gchar *string, |
7280 | 1906 gchar **replace, |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1907 gint *length) |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1908 { |
7287 | 1909 static char buf[7]; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1910 g_return_val_if_fail (string != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1911 g_return_val_if_fail (replace != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1912 g_return_val_if_fail (length != NULL, FALSE); |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1913 |
4793 | 1914 if (!g_ascii_strncasecmp (string, "&", 5)) { |
7280 | 1915 *replace = "&"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1916 *length = 5; |
4793 | 1917 } else if (!g_ascii_strncasecmp (string, "<", 4)) { |
7280 | 1918 *replace = "<"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1919 *length = 4; |
4793 | 1920 } else if (!g_ascii_strncasecmp (string, ">", 4)) { |
7280 | 1921 *replace = ">"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1922 *length = 4; |
4793 | 1923 } else if (!g_ascii_strncasecmp (string, " ", 6)) { |
7280 | 1924 *replace = " "; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1925 *length = 6; |
4793 | 1926 } else if (!g_ascii_strncasecmp (string, "©", 6)) { |
7280 | 1927 *replace = "©"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1928 *length = 6; |
4793 | 1929 } else if (!g_ascii_strncasecmp (string, """, 6)) { |
7280 | 1930 *replace = "\""; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1931 *length = 6; |
4793 | 1932 } else if (!g_ascii_strncasecmp (string, "®", 5)) { |
7280 | 1933 *replace = "®"; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1934 *length = 5; |
5093 | 1935 } else if (!g_ascii_strncasecmp (string, "'", 6)) { |
7280 | 1936 *replace = "\'"; |
5093 | 1937 *length = 6; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1938 } else if (*(string + 1) == '#') { |
2022
199ba82faacb
[gaim-migrate @ 2032]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2002
diff
changeset
|
1939 guint pound = 0; |
3004 | 1940 if ((sscanf (string, "&#%u;", £) == 1) && pound != 0) { |
7287 | 1941 int buflen; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1942 if (*(string + 3 + (gint)log10 (pound)) != ';') |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1943 return FALSE; |
7287 | 1944 buflen = g_unichar_to_utf8((gunichar)pound, buf); |
1945 buf[buflen] = '\0'; | |
7280 | 1946 *replace = buf; |
1472
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1947 *length = 2; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1948 while (isdigit ((gint) string [*length])) (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1949 if (string [*length] == ';') (*length)++; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1950 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1951 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1952 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1953 } else { |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1954 return FALSE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1955 } |
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 return TRUE; |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1958 } |
be620a051d6d
[gaim-migrate @ 1482]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1463
diff
changeset
|
1959 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1960 static gboolean |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1961 gtk_imhtml_is_tag (const gchar *string, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1962 gchar **tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1963 gint *len, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1964 gint *type) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1965 { |
8061 | 1966 char *close; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1967 *type = 1; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1968 |
8118 | 1969 |
8061 | 1970 if (!(close = strchr (string, '>'))) |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1971 return FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1972 |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1973 VALID_TAG ("B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1974 VALID_TAG ("BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1975 VALID_TAG ("/B"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1976 VALID_TAG ("/BOLD"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1977 VALID_TAG ("I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1978 VALID_TAG ("ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1979 VALID_TAG ("/I"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1980 VALID_TAG ("/ITALIC"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1981 VALID_TAG ("U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1982 VALID_TAG ("UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1983 VALID_TAG ("/U"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1984 VALID_TAG ("/UNDERLINE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1985 VALID_TAG ("S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1986 VALID_TAG ("STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1987 VALID_TAG ("/S"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1988 VALID_TAG ("/STRIKE"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1989 VALID_TAG ("SUB"); |
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 ("SUP"); |
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 ("PRE"); |
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 ("TITLE"); |
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 ("BR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1998 VALID_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
1999 VALID_TAG ("/FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2000 VALID_TAG ("/A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2001 VALID_TAG ("P"); |
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 ("H3"); |
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 ("HTML"); |
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 ("BODY"); |
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 ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2010 VALID_TAG ("HEAD"); |
2993 | 2011 VALID_TAG ("/HEAD"); |
2012 VALID_TAG ("BINARY"); | |
2013 VALID_TAG ("/BINARY"); | |
5093 | 2014 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2015 VALID_OPT_TAG ("HR"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2016 VALID_OPT_TAG ("FONT"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2017 VALID_OPT_TAG ("BODY"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2018 VALID_OPT_TAG ("A"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2019 VALID_OPT_TAG ("IMG"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2020 VALID_OPT_TAG ("P"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2021 VALID_OPT_TAG ("H3"); |
5093 | 2022 VALID_OPT_TAG ("HTML"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2023 |
5101 | 2024 VALID_TAG ("CITE"); |
2025 VALID_TAG ("/CITE"); | |
2026 VALID_TAG ("EM"); | |
2027 VALID_TAG ("/EM"); | |
2028 VALID_TAG ("STRONG"); | |
2029 VALID_TAG ("/STRONG"); | |
2030 | |
5104 | 2031 VALID_OPT_TAG ("SPAN"); |
2032 VALID_TAG ("/SPAN"); | |
5174 | 2033 VALID_TAG ("BR/"); /* hack until gtkimhtml handles things better */ |
6982 | 2034 VALID_TAG ("IMG"); |
8026 | 2035 VALID_TAG("SPAN"); |
8061 | 2036 VALID_OPT_TAG("BR"); |
7988 | 2037 |
4793 | 2038 if (!g_ascii_strncasecmp(string, "!--", strlen ("!--"))) { |
2954
f6c4f2187c08
[gaim-migrate @ 2967]
Christian Hammond <chipx86@chipx86.com>
parents:
2898
diff
changeset
|
2039 gchar *e = strstr (string + strlen("!--"), "-->"); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2040 if (e) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2041 *len = e - string + strlen ("-->"); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2042 *tag = g_strndup (string + strlen ("!--"), *len - strlen ("!---->")); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2043 return TRUE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2044 } |
8118 | 2045 } |
2046 | |
8061 | 2047 *type = -1; |
2048 *len = close - string + 1; | |
2049 *tag = g_strndup(string, *len - 1); | |
2050 return TRUE; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2051 } |
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 static gchar* |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2054 gtk_imhtml_get_html_opt (gchar *tag, |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2055 const gchar *opt) |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2056 { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2057 gchar *t = tag; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2058 gchar *e, *a; |
5177 | 2059 gchar *val; |
2060 gint len; | |
7280 | 2061 gchar *c; |
5177 | 2062 GString *ret; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2063 |
4793 | 2064 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2065 gboolean quote = FALSE; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2066 if (*t == '\0') break; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2067 while (*t && !((*t == ' ') && !quote)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2068 if (*t == '\"') |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2069 quote = ! quote; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2070 t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2071 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2072 while (*t && (*t == ' ')) t++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2073 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2074 |
4793 | 2075 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2076 t += strlen (opt); |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2077 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2078 return NULL; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2079 } |
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 if ((*t == '\"') || (*t == '\'')) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2082 e = a = ++t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2083 while (*e && (*e != *(t - 1))) e++; |
2993 | 2084 if (*e == '\0') { |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2085 return NULL; |
5177 | 2086 } else |
2087 val = g_strndup(a, e - a); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2088 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2089 e = a = t; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2090 while (*e && !isspace ((gint) *e)) e++; |
5177 | 2091 val = g_strndup(a, e - a); |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2092 } |
5177 | 2093 |
2094 ret = g_string_new(""); | |
2095 e = val; | |
2096 while(*e) { | |
2097 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
7280 | 2098 ret = g_string_append(ret, c); |
5177 | 2099 e += len; |
2100 } else { | |
2101 ret = g_string_append_c(ret, *e); | |
2102 e++; | |
2103 } | |
2104 } | |
2105 | |
2106 g_free(val); | |
8568 | 2107 |
2108 return g_string_free(ret, FALSE); | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2109 } |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2110 |
8118 | 2111 /* Inline CSS Support - Douglas Thrift */ |
2112 static gchar* | |
2113 gtk_imhtml_get_css_opt (gchar *style, | |
2114 const gchar *opt) | |
2115 { | |
2116 gchar *t = style; | |
2117 gchar *e, *a; | |
2118 gchar *val; | |
2119 gint len; | |
2120 gchar *c; | |
2121 GString *ret; | |
2122 | |
2123 while (g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
8177 | 2124 /* gboolean quote = FALSE; */ |
8118 | 2125 if (*t == '\0') break; |
2126 while (*t && !((*t == ' ') /*&& !quote*/)) { | |
2127 /* if (*t == '\"') | |
8177 | 2128 quote = ! quote; */ |
8118 | 2129 t++; |
2130 } | |
2131 while (*t && (*t == ' ')) t++; | |
2132 } | |
2133 | |
2134 if (!g_ascii_strncasecmp (t, opt, strlen (opt))) { | |
2135 t += strlen (opt); | |
10457 | 2136 while (*t && (*t == ' ')) t++; |
2137 if (!*t) | |
2138 return NULL; | |
8118 | 2139 } else { |
2140 return NULL; | |
2141 } | |
2142 | |
2143 /* if ((*t == '\"') || (*t == '\'')) { | |
2144 e = a = ++t; | |
2145 while (*e && (*e != *(t - 1))) e++; | |
2146 if (*e == '\0') { | |
2147 return NULL; | |
2148 } else | |
2149 val = g_strndup(a, e - a); | |
2150 } else { | |
2151 e = a = t; | |
2152 while (*e && !isspace ((gint) *e)) e++; | |
2153 val = g_strndup(a, e - a); | |
2154 }*/ | |
2155 | |
2156 e = a = t; | |
2157 while (*e && *e != ';') e++; | |
2158 val = g_strndup(a, e - a); | |
2159 | |
2160 ret = g_string_new(""); | |
2161 e = val; | |
2162 while(*e) { | |
2163 if(gtk_imhtml_is_amp_escape(e, &c, &len)) { | |
2164 ret = g_string_append(ret, c); | |
2165 e += len; | |
2166 } else { | |
2167 ret = g_string_append_c(ret, *e); | |
2168 e++; | |
2169 } | |
2170 } | |
2171 | |
2172 g_free(val); | |
2173 val = ret->str; | |
2174 g_string_free(ret, FALSE); | |
2175 return val; | |
2176 } | |
3922 | 2177 |
8334 | 2178 static const char *accepted_protocols[] = { |
2179 "http://", | |
2180 "https://", | |
2181 "ftp://" | |
2182 }; | |
2183 | |
2184 static const int accepted_protocols_size = 3; | |
2185 | |
2186 /* returns if the beginning of the text is a protocol. If it is the protocol, returns the length so | |
2187 the caller knows how long the protocol string is. */ | |
2188 int gtk_imhtml_is_protocol(const char *text) | |
2189 { | |
2190 gint i; | |
2191 | |
2192 for(i=0; i<accepted_protocols_size; i++){ | |
2193 if( strncasecmp(text, accepted_protocols[i], strlen(accepted_protocols[i])) == 0 ){ | |
2194 return strlen(accepted_protocols[i]); | |
2195 } | |
2196 } | |
2197 return 0; | |
2198 } | |
2199 | |
8677 | 2200 /* |
2201 <KingAnt> marv: The two IM image functions in oscar are gaim_odc_send_im and gaim_odc_incoming | |
2202 | |
2203 | |
2204 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) | |
2205 [19:59] <KingAnt> marv: I think the image tag used by the core is something like <img id="#"/> | |
2206 [19:59] Ro0tSiEgE robert42 RobFlynn Robot101 ross22 roz | |
2207 [20:00] <KingAnt> marv: Where the ID is the what is returned when you add the image to the imgstore using gaim_imgstore_add | |
2208 [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? | |
2209 [20:00] <KingAnt> marv: Right | |
2210 [20:00] <marv> alright | |
2211 | |
2212 Here's my plan with IMImages. make gtk_imhtml_[append|insert]_text_with_images instead just | |
2213 gtkimhtml_[append|insert]_text (hrm maybe it should be called html instead of text), add a | |
2214 function for gaim to register for look up images, i.e. gtk_imhtml_set_get_img_fnc, so that | |
2215 images can be looked up like that, instead of passing a GSList of them. | |
2216 */ | |
2217 | |
2218 void gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | |
2219 const gchar *text, | |
2220 GtkIMHtmlOptions options, | |
2221 GSList *unused) | |
1428 | 2222 { |
8677 | 2223 GtkTextIter iter, ins, sel; |
2224 GdkRectangle rect; | |
2225 int y, height, ins_offset = 0, sel_offset = 0; | |
2226 gboolean fixins = FALSE, fixsel = FALSE; | |
2227 | |
2228 g_return_if_fail (imhtml != NULL); | |
2229 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
2230 g_return_if_fail (text != NULL); | |
2231 | |
2232 | |
2233 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
2234 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
2235 if (gtk_text_iter_equal(&iter, &ins) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
2236 fixins = TRUE; | |
2237 ins_offset = gtk_text_iter_get_offset(&ins); | |
2238 } | |
2239 | |
2240 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &sel, gtk_text_buffer_get_selection_bound(imhtml->text_buffer)); | |
2241 if (gtk_text_iter_equal(&iter, &sel) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
2242 fixsel = TRUE; | |
2243 sel_offset = gtk_text_iter_get_offset(&sel); | |
2244 } | |
2245 | |
2246 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
2247 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
2248 | |
2249 | |
2250 if(((y + height) - (rect.y + rect.height)) > height | |
2251 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
2252 options |= GTK_IMHTML_NO_SCROLL; | |
2253 } | |
2254 | |
2255 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); | |
2256 | |
2257 if (fixins) { | |
2258 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins, ins_offset); | |
2259 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_insert(imhtml->text_buffer), &ins); | |
2260 } | |
2261 | |
2262 if (fixsel) { | |
2263 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &sel, sel_offset); | |
2264 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_selection_bound(imhtml->text_buffer), &sel); | |
2265 } | |
2266 | |
2267 if (!(options & GTK_IMHTML_NO_SCROLL)) { | |
8729 | 2268 gtk_imhtml_scroll_to_end(imhtml); |
8677 | 2269 } |
2270 } | |
2271 | |
11006 | 2272 #define MAX_SCROLL_TIME 0.4 /* seconds */ |
2273 #define SCROLL_DELAY 33 /* milliseconds */ | |
2274 | |
2275 /* | |
2276 * Smoothly scroll a GtkIMHtml. | |
2277 * | |
2278 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. | |
2279 */ | |
10871 | 2280 static gboolean scroll_cb(gpointer data) |
10798 | 2281 { |
2282 GtkIMHtml *imhtml = data; | |
2283 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; | |
11006 | 2284 gdouble max_val = adj->upper - adj->page_size; |
2285 | |
2286 g_return_val_if_fail(imhtml->scroll_time != NULL, FALSE); | |
2287 | |
2288 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME) { | |
2289 /* time's up. jump to the end and kill the timer */ | |
2290 gtk_adjustment_set_value(adj, max_val); | |
10798 | 2291 g_timer_destroy(imhtml->scroll_time); |
2292 imhtml->scroll_time = NULL; | |
2293 return FALSE; | |
11006 | 2294 } |
2295 | |
2296 /* scroll by 1/3rd the remaining distance */ | |
2297 gtk_adjustment_set_value(adj, gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3)); | |
2298 return TRUE; | |
10798 | 2299 } |
2300 | |
10871 | 2301 static gboolean scroll_idle_cb(gpointer data) |
10797 | 2302 { |
10798 | 2303 GtkIMHtml *imhtml = data; |
11006 | 2304 imhtml->scroll_src = g_timeout_add(SCROLL_DELAY, scroll_cb, imhtml); |
10797 | 2305 return FALSE; |
2306 } | |
2307 | |
8729 | 2308 void gtk_imhtml_scroll_to_end(GtkIMHtml *imhtml) |
2309 { | |
10798 | 2310 if (imhtml->scroll_time) |
2311 g_timer_destroy(imhtml->scroll_time); | |
2312 imhtml->scroll_time = g_timer_new(); | |
2313 if (imhtml->scroll_src) | |
2314 g_source_remove(imhtml->scroll_src); | |
2315 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); | |
8729 | 2316 } |
2317 | |
8677 | 2318 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, |
2319 const gchar *text, | |
2320 GtkIMHtmlOptions options, | |
2321 GtkTextIter *iter) | |
2322 { | |
8061 | 2323 GdkRectangle rect; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2324 gint pos = 0; |
3922 | 2325 gchar *ws; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2326 gchar *tag; |
3922 | 2327 gchar *bg = NULL; |
6982 | 2328 gint len; |
4032 | 2329 gint tlen, smilelen, wpos=0; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2330 gint type; |
3922 | 2331 const gchar *c; |
7280 | 2332 gchar *amp; |
8334 | 2333 gint len_protocol; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2334 |
1428 | 2335 guint bold = 0, |
2336 italics = 0, | |
2337 underline = 0, | |
2338 strike = 0, | |
2339 sub = 0, | |
2340 sup = 0, | |
1691
d802b115800f
[gaim-migrate @ 1701]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1647
diff
changeset
|
2341 title = 0, |
8061 | 2342 pre = 0; |
1428 | 2343 |
10217 | 2344 gboolean br = FALSE; |
2345 | |
3922 | 2346 GSList *fonts = NULL; |
8506 | 2347 GObject *object; |
8061 | 2348 GtkIMHtmlScalable *scalable = NULL; |
8677 | 2349 |
2350 g_return_if_fail (imhtml != NULL); | |
2351 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
2352 g_return_if_fail (text != NULL); | |
3922 | 2353 c = text; |
6982 | 2354 len = strlen(text); |
3922 | 2355 ws = g_malloc(len + 1); |
2356 ws[0] = 0; | |
1428 | 2357 |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2358 while (pos < len) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2359 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2360 c++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2361 pos++; |
8061 | 2362 ws[wpos] = '\0'; |
10217 | 2363 br = FALSE; |
8061 | 2364 switch (type) |
3922 | 2365 { |
2366 case 1: /* B */ | |
2367 case 2: /* BOLD */ | |
5101 | 2368 case 54: /* STRONG */ |
8677 | 2369 |
2370 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
2371 | |
2372 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD)) | |
8061 | 2373 gtk_imhtml_toggle_bold(imhtml); |
3922 | 2374 bold++; |
8061 | 2375 ws[0] = '\0'; wpos = 0; |
3922 | 2376 break; |
2377 case 3: /* /B */ | |
2378 case 4: /* /BOLD */ | |
5101 | 2379 case 55: /* /STRONG */ |
8677 | 2380 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2381 ws[0] = '\0'; wpos = 0; |
2382 | |
3922 | 2383 if (bold) |
2384 bold--; | |
8677 | 2385 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD) && !imhtml->wbfo) |
8061 | 2386 gtk_imhtml_toggle_bold(imhtml); |
3922 | 2387 break; |
2388 case 5: /* I */ | |
2389 case 6: /* ITALIC */ | |
5101 | 2390 case 52: /* EM */ |
8677 | 2391 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2392 ws[0] = '\0'; wpos = 0; |
8677 | 2393 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC)) |
8061 | 2394 gtk_imhtml_toggle_italic(imhtml); |
3922 | 2395 italics++; |
2396 break; | |
2397 case 7: /* /I */ | |
2398 case 8: /* /ITALIC */ | |
5101 | 2399 case 53: /* /EM */ |
8677 | 2400 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2401 ws[0] = '\0'; wpos = 0; |
3922 | 2402 if (italics) |
2403 italics--; | |
8677 | 2404 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC) && !imhtml->wbfo) |
8061 | 2405 gtk_imhtml_toggle_italic(imhtml); |
3922 | 2406 break; |
2407 case 9: /* U */ | |
2408 case 10: /* UNDERLINE */ | |
8677 | 2409 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2410 ws[0] = '\0'; wpos = 0; |
8677 | 2411 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
8061 | 2412 gtk_imhtml_toggle_underline(imhtml); |
3922 | 2413 underline++; |
2414 break; | |
2415 case 11: /* /U */ | |
2416 case 12: /* /UNDERLINE */ | |
8677 | 2417 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2418 ws[0] = '\0'; wpos = 0; |
3922 | 2419 if (underline) |
2420 underline--; | |
8677 | 2421 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE) && !imhtml->wbfo) |
8061 | 2422 gtk_imhtml_toggle_underline(imhtml); |
3922 | 2423 break; |
2424 case 13: /* S */ | |
2425 case 14: /* STRIKE */ | |
9924 | 2426 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2427 ws[0] = '\0'; wpos = 0; | |
2428 if ((strike == 0) && (imhtml->format_functions & GTK_IMHTML_STRIKE)) | |
2429 gtk_imhtml_toggle_strike(imhtml); | |
3922 | 2430 strike++; |
2431 break; | |
2432 case 15: /* /S */ | |
2433 case 16: /* /STRIKE */ | |
9924 | 2434 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2435 ws[0] = '\0'; wpos = 0; | |
3922 | 2436 if (strike) |
2437 strike--; | |
9924 | 2438 if ((strike == 0) && (imhtml->format_functions & GTK_IMHTML_STRIKE) && !imhtml->wbfo) |
2439 gtk_imhtml_toggle_strike(imhtml); | |
3922 | 2440 break; |
2441 case 17: /* SUB */ | |
8677 | 2442 /* FIXME: reimpliment this */ |
3922 | 2443 sub++; |
2444 break; | |
2445 case 18: /* /SUB */ | |
8677 | 2446 /* FIXME: reimpliment this */ |
3922 | 2447 if (sub) |
2448 sub--; | |
2449 break; | |
2450 case 19: /* SUP */ | |
8677 | 2451 /* FIXME: reimplement this */ |
3922 | 2452 sup++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2453 break; |
3922 | 2454 case 20: /* /SUP */ |
8677 | 2455 /* FIXME: reimplement this */ |
3922 | 2456 if (sup) |
2457 sup--; | |
2458 break; | |
2459 case 21: /* PRE */ | |
8677 | 2460 /* FIXME: reimplement this */ |
3922 | 2461 pre++; |
2462 break; | |
2463 case 22: /* /PRE */ | |
8677 | 2464 /* FIXME: reimplement this */ |
3922 | 2465 if (pre) |
2466 pre--; | |
2467 break; | |
2468 case 23: /* TITLE */ | |
8677 | 2469 /* FIXME: what was this supposed to do anyway? */ |
3922 | 2470 title++; |
2471 break; | |
2472 case 24: /* /TITLE */ | |
8677 | 2473 /* FIXME: make this undo whatever 23 was supposed to do */ |
3922 | 2474 if (title) { |
2475 if (options & GTK_IMHTML_NO_TITLE) { | |
2476 wpos = 0; | |
2477 ws [wpos] = '\0'; | |
2478 } | |
2479 title--; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2480 } |
3922 | 2481 break; |
2482 case 25: /* BR */ | |
5174 | 2483 case 58: /* BR/ */ |
8061 | 2484 case 61: /* BR (opt) */ |
3922 | 2485 ws[wpos] = '\n'; |
2486 wpos++; | |
10217 | 2487 br = TRUE; |
6982 | 2488 break; |
3922 | 2489 case 26: /* HR */ |
2490 case 42: /* HR (opt) */ | |
8726 | 2491 { |
2492 int minus; | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2493 struct scalable_data *sd = g_new(struct scalable_data, 1); |
8726 | 2494 |
3922 | 2495 ws[wpos++] = '\n'; |
8677 | 2496 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2497 | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2498 sd->scalable = scalable = gtk_imhtml_hr_new(); |
11233
f08d22130bb2
[gaim-migrate @ 13373]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11224
diff
changeset
|
2499 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); |
8061 | 2500 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
8677 | 2501 scalable->add_to(scalable, imhtml, iter); |
8726 | 2502 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + |
2503 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
2504 scalable->scale(scalable, rect.width - minus, rect.height); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
2505 imhtml->scalables = g_list_append(imhtml->scalables, sd); |
8061 | 2506 ws[0] = '\0'; wpos = 0; |
7942 | 2507 ws[wpos++] = '\n'; |
8061 | 2508 |
3922 | 2509 break; |
8726 | 2510 } |
3922 | 2511 case 27: /* /FONT */ |
8677 | 2512 if (fonts && !imhtml->wbfo) { |
5967 | 2513 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2514 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2515 ws[0] = '\0'; wpos = 0; |
8177 | 2516 /* NEW_BIT (NEW_TEXT_BIT); */ |
8677 | 2517 |
8698 | 2518 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) { |
8061 | 2519 gtk_imhtml_toggle_fontface(imhtml, NULL); |
3922 | 2520 g_free (font->face); |
8061 | 2521 } |
8698 | 2522 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
8061 | 2523 gtk_imhtml_toggle_forecolor(imhtml, NULL); |
3922 | 2524 g_free (font->fore); |
8061 | 2525 } |
8698 | 2526 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
8061 | 2527 gtk_imhtml_toggle_backcolor(imhtml, NULL); |
3922 | 2528 g_free (font->back); |
8061 | 2529 } |
4032 | 2530 if (font->sml) |
2531 g_free (font->sml); | |
8309 | 2532 |
8698 | 2533 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2534 gtk_imhtml_font_set_size(imhtml, 3); |
2535 | |
10761 | 2536 |
2537 fonts = g_slist_remove (fonts, font); | |
9245 | 2538 g_free(font); |
2539 | |
8309 | 2540 if (fonts) { |
2541 GtkIMHtmlFontDetail *font = fonts->data; | |
8677 | 2542 |
8698 | 2543 if (font->face && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8309 | 2544 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8698 | 2545 if (font->fore && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8309 | 2546 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8698 | 2547 if (font->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
8309 | 2548 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8698 | 2549 if ((font->size != 3) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
8309 | 2550 gtk_imhtml_font_set_size(imhtml, font->size); |
2551 } | |
3922 | 2552 } |
8309 | 2553 break; |
3922 | 2554 case 28: /* /A */ |
8677 | 2555 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2556 gtk_imhtml_toggle_link(imhtml, NULL); | |
2557 ws[0] = '\0'; wpos = 0; | |
8061 | 2558 break; |
8118 | 2559 |
3922 | 2560 case 29: /* P */ |
2561 case 30: /* /P */ | |
2562 case 31: /* H3 */ | |
2563 case 32: /* /H3 */ | |
2564 case 33: /* HTML */ | |
2565 case 34: /* /HTML */ | |
2566 case 35: /* BODY */ | |
10776 | 2567 break; |
3922 | 2568 case 36: /* /BODY */ |
10786 | 2569 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2570 ws[0] = '\0'; wpos = 0; | |
10776 | 2571 gtk_imhtml_toggle_background(imhtml, NULL); |
2572 break; | |
3922 | 2573 case 37: /* FONT */ |
2574 case 38: /* HEAD */ | |
2575 case 39: /* /HEAD */ | |
6982 | 2576 case 40: /* BINARY */ |
2577 case 41: /* /BINARY */ | |
3922 | 2578 break; |
2579 case 43: /* FONT (opt) */ | |
2580 { | |
4032 | 2581 gchar *color, *back, *face, *size, *sml; |
5967 | 2582 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
3922 | 2583 color = gtk_imhtml_get_html_opt (tag, "COLOR="); |
2584 back = gtk_imhtml_get_html_opt (tag, "BACK="); | |
2585 face = gtk_imhtml_get_html_opt (tag, "FACE="); | |
2586 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | |
4032 | 2587 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
2588 if (!(color || back || face || size || sml)) | |
3922 | 2589 break; |
8061 | 2590 |
8677 | 2591 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2592 ws[0] = '\0'; wpos = 0; |
2593 | |
5967 | 2594 font = g_new0 (GtkIMHtmlFontDetail, 1); |
3922 | 2595 if (fonts) |
2596 oldfont = fonts->data; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2597 |
8677 | 2598 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
3922 | 2599 font->fore = color; |
8061 | 2600 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
8677 | 2601 } |
8309 | 2602 //else if (oldfont && oldfont->fore) |
2603 // font->fore = g_strdup(oldfont->fore); | |
8677 | 2604 |
2605 if (back && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { | |
3922 | 2606 font->back = back; |
8061 | 2607 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
8309 | 2608 } |
2609 //else if (oldfont && oldfont->back) | |
2610 // font->back = g_strdup(oldfont->back); | |
8677 | 2611 |
2612 if (face && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) { | |
3922 | 2613 font->face = face; |
8061 | 2614 gtk_imhtml_toggle_fontface(imhtml, font->face); |
8309 | 2615 } |
2616 //else if (oldfont && oldfont->face) | |
2617 // font->face = g_strdup(oldfont->face); | |
4032 | 2618 |
2619 if (sml) | |
2620 font->sml = sml; | |
2621 else if (oldfont && oldfont->sml) | |
2622 font->sml = g_strdup(oldfont->sml); | |
2623 | |
8677 | 2624 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) { |
3922 | 2625 if (*size == '+') { |
2626 sscanf (size + 1, "%hd", &font->size); | |
2627 font->size += 3; | |
2628 } else if (*size == '-') { | |
2629 sscanf (size + 1, "%hd", &font->size); | |
2630 font->size = MAX (0, 3 - font->size); | |
2631 } else if (isdigit (*size)) { | |
2632 sscanf (size, "%hd", &font->size); | |
8061 | 2633 } |
6042 | 2634 if (font->size > 100) |
2635 font->size = 100; | |
3922 | 2636 } else if (oldfont) |
2637 font->size = oldfont->size; | |
8309 | 2638 else |
2639 font->size = 3; | |
8698 | 2640 if ((imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) |
2641 gtk_imhtml_font_set_size(imhtml, font->size); | |
3922 | 2642 g_free(size); |
2643 fonts = g_slist_prepend (fonts, font); | |
2644 } | |
2645 break; | |
2646 case 44: /* BODY (opt) */ | |
2647 if (!(options & GTK_IMHTML_NO_COLOURS)) { | |
2648 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | |
8677 | 2649 if (bgcolor && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
2650 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2651 ws[0] = '\0'; wpos = 0; |
8177 | 2652 /* NEW_BIT(NEW_TEXT_BIT); */ |
3922 | 2653 if (bg) |
2654 g_free(bg); | |
2655 bg = bgcolor; | |
10776 | 2656 gtk_imhtml_toggle_background(imhtml, bg); |
2885
f72efa29c109
[gaim-migrate @ 2898]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2871
diff
changeset
|
2657 } |
1428 | 2658 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2659 break; |
3922 | 2660 case 45: /* A (opt) */ |
2661 { | |
2662 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | |
8677 | 2663 if (href && (imhtml->format_functions & GTK_IMHTML_LINK)) { |
2664 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8061 | 2665 ws[0] = '\0'; wpos = 0; |
8677 | 2666 gtk_imhtml_toggle_link(imhtml, href); |
3922 | 2667 } |
10504 | 2668 if (href) |
2669 g_free(href); | |
2993 | 2670 } |
3922 | 2671 break; |
4895 | 2672 case 46: /* IMG (opt) */ |
6982 | 2673 case 59: /* IMG */ |
4895 | 2674 { |
8962 | 2675 const char *id; |
2676 | |
2677 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
2678 ws[0] = '\0'; wpos = 0; | |
4895 | 2679 |
8677 | 2680 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) |
2681 break; | |
2682 | |
8962 | 2683 id = gtk_imhtml_get_html_opt(tag, "ID="); |
9186 | 2684 if (!id) |
2685 break; | |
8962 | 2686 gtk_imhtml_insert_image_at_iter(imhtml, atoi(id), iter); |
2687 break; | |
4895 | 2688 } |
3922 | 2689 case 47: /* P (opt) */ |
2690 case 48: /* H3 (opt) */ | |
5093 | 2691 case 49: /* HTML (opt) */ |
5101 | 2692 case 50: /* CITE */ |
2693 case 51: /* /CITE */ | |
8026 | 2694 case 56: /* SPAN (opt) */ |
8118 | 2695 /* Inline CSS Support - Douglas Thrift |
2696 * | |
2697 * color | |
8686 | 2698 * background |
8118 | 2699 * font-family |
2700 * font-size | |
8686 | 2701 * text-decoration: underline |
10483 | 2702 * |
2703 * TODO: | |
2704 * background-color | |
2705 * font-style | |
2706 * font-weight | |
8118 | 2707 */ |
2708 { | |
8686 | 2709 gchar *style, *color, *background, *family, *size; |
2710 gchar *textdec; | |
8118 | 2711 GtkIMHtmlFontDetail *font, *oldfont = NULL; |
2712 style = gtk_imhtml_get_html_opt (tag, "style="); | |
2713 | |
2714 if (!style) break; | |
2715 | |
10457 | 2716 color = gtk_imhtml_get_css_opt (style, "color:"); |
2717 background = gtk_imhtml_get_css_opt (style, "background:"); | |
8118 | 2718 family = gtk_imhtml_get_css_opt (style, |
10457 | 2719 "font-family:"); |
2720 size = gtk_imhtml_get_css_opt (style, "font-size:"); | |
2721 textdec = gtk_imhtml_get_css_opt (style, "text-decoration:"); | |
8686 | 2722 |
2723 if (!(color || family || size || background || textdec)) { | |
8120 | 2724 g_free(style); |
2725 break; | |
2726 } | |
8118 | 2727 |
8677 | 2728 |
2729 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
8118 | 2730 ws[0] = '\0'; wpos = 0; |
8177 | 2731 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2732 |
2733 font = g_new0 (GtkIMHtmlFontDetail, 1); | |
2734 if (fonts) | |
2735 oldfont = fonts->data; | |
2736 | |
8677 | 2737 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
8686 | 2738 { |
8118 | 2739 font->fore = color; |
8686 | 2740 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
2741 } | |
8118 | 2742 else if (oldfont && oldfont->fore) |
2743 font->fore = g_strdup(oldfont->fore); | |
2744 | |
8686 | 2745 if (background && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
2746 { | |
2747 font->back = background; | |
2748 gtk_imhtml_toggle_backcolor(imhtml, font->back); | |
2749 } | |
2750 else if (oldfont && oldfont->back) | |
8118 | 2751 font->back = g_strdup(oldfont->back); |
2752 | |
8677 | 2753 if (family && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) |
8686 | 2754 { |
8118 | 2755 font->face = family; |
8686 | 2756 gtk_imhtml_toggle_fontface(imhtml, font->face); |
2757 } | |
8118 | 2758 else if (oldfont && oldfont->face) |
2759 font->face = g_strdup(oldfont->face); | |
2760 if (font->face && (atoi(font->face) > 100)) { | |
8677 | 2761 /* WTF is this? */ |
9696 | 2762 /* Maybe it sets a max size on the font face? I seem to |
2763 * remember bad things happening if the font size was | |
2764 * 2 billion */ | |
8118 | 2765 g_free(font->face); |
2766 font->face = g_strdup("100"); | |
2767 } | |
2768 | |
2769 if (oldfont && oldfont->sml) | |
2770 font->sml = g_strdup(oldfont->sml); | |
2771 | |
8677 | 2772 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_SHRINK|GTK_IMHTML_GROW))) { |
8686 | 2773 if (g_ascii_strcasecmp(size, "xx-small") == 0) |
2774 font->size = 1; | |
2775 else if (g_ascii_strcasecmp(size, "smaller") == 0 | |
2776 || g_ascii_strcasecmp(size, "x-small") == 0) | |
8118 | 2777 font->size = 2; |
8686 | 2778 else if (g_ascii_strcasecmp(size, "larger") == 0 |
2779 || g_ascii_strcasecmp(size, "medium") == 0) | |
8118 | 2780 font->size = 4; |
8686 | 2781 else if (g_ascii_strcasecmp(size, "large") == 0) |
2782 font->size = 5; | |
2783 else if (g_ascii_strcasecmp(size, "x-large") == 0) | |
2784 font->size = 6; | |
2785 else if (g_ascii_strcasecmp(size, "xx-large") == 0) | |
2786 font->size = 7; | |
8118 | 2787 else |
2788 font->size = 3; | |
8686 | 2789 gtk_imhtml_font_set_size(imhtml, font->size); |
2790 } | |
2791 else if (oldfont) | |
2792 { | |
2793 font->size = oldfont->size; | |
2794 } | |
2795 | |
2796 if (oldfont) | |
2797 { | |
2798 font->underline = oldfont->underline; | |
2799 } | |
2800 if (textdec && font->underline != 1 | |
9025 | 2801 && g_ascii_strcasecmp(textdec, "underline") == 0 |
8686 | 2802 && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
2803 { | |
2804 gtk_imhtml_toggle_underline(imhtml); | |
2805 font->underline = 1; | |
2806 } | |
8118 | 2807 |
2808 g_free(style); | |
2809 g_free(size); | |
2810 fonts = g_slist_prepend (fonts, font); | |
2811 } | |
2812 break; | |
5104 | 2813 case 57: /* /SPAN */ |
8118 | 2814 /* Inline CSS Support - Douglas Thrift */ |
8677 | 2815 if (fonts && !imhtml->wbfo) { |
8686 | 2816 GtkIMHtmlFontDetail *oldfont = NULL; |
8118 | 2817 GtkIMHtmlFontDetail *font = fonts->data; |
8677 | 2818 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8118 | 2819 ws[0] = '\0'; wpos = 0; |
8177 | 2820 /* NEW_BIT (NEW_TEXT_BIT); */ |
8118 | 2821 fonts = g_slist_remove (fonts, font); |
8692 | 2822 if (fonts) |
2823 oldfont = fonts->data; | |
2824 | |
2825 if (!oldfont) { | |
2826 gtk_imhtml_font_set_size(imhtml, 3); | |
2827 if (font->underline) | |
2828 gtk_imhtml_toggle_underline(imhtml); | |
2829 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
2830 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
2831 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
8686 | 2832 } |
8692 | 2833 else |
8686 | 2834 { |
8692 | 2835 |
2836 if (font->size != oldfont->size) | |
2837 gtk_imhtml_font_set_size(imhtml, oldfont->size); | |
2838 | |
2839 if (font->underline != oldfont->underline) | |
2840 gtk_imhtml_toggle_underline(imhtml); | |
2841 | |
9286 | 2842 if (font->face && (!oldfont->face || strcmp(font->face, oldfont->face) != 0)) |
8692 | 2843 gtk_imhtml_toggle_fontface(imhtml, oldfont->face); |
2844 | |
9286 | 2845 if (font->fore && (!oldfont->fore || strcmp(font->fore, oldfont->fore) != 0)) |
8692 | 2846 gtk_imhtml_toggle_forecolor(imhtml, oldfont->fore); |
2847 | |
9286 | 2848 if (font->back && (!oldfont->back || strcmp(font->back, oldfont->back) != 0)) |
8692 | 2849 gtk_imhtml_toggle_backcolor(imhtml, oldfont->back); |
8686 | 2850 } |
8692 | 2851 |
2852 g_free (font->face); | |
2853 g_free (font->fore); | |
2854 g_free (font->back); | |
2855 g_free (font->sml); | |
2856 | |
8118 | 2857 g_free (font); |
2858 } | |
2859 break; | |
8026 | 2860 case 60: /* SPAN */ |
2993 | 2861 break; |
8061 | 2862 case 62: /* comment */ |
8177 | 2863 /* NEW_BIT (NEW_TEXT_BIT); */ |
8317 | 2864 ws[wpos] = '\0'; |
9465 | 2865 |
8677 | 2866 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2867 | |
10815 | 2868 if (imhtml->show_comments && !(options & GTK_IMHTML_NO_COMMENTS)) { |
6124 | 2869 wpos = g_snprintf (ws, len, "%s", tag); |
10815 | 2870 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2871 } | |
2872 ws[0] = '\0'; wpos = 0; | |
2873 | |
8177 | 2874 /* NEW_BIT (NEW_COMMENT_BIT); */ |
3922 | 2875 break; |
2876 default: | |
6882 | 2877 break; |
2993 | 2878 } |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2879 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2880 pos += tlen; |
4138 | 2881 if(tag) |
2882 g_free(tag); /* This was allocated back in VALID_TAG() */ | |
9029 | 2883 } else if (gtk_imhtml_is_smiley(imhtml, fonts, c, &smilelen)) { |
8473 | 2884 GtkIMHtmlFontDetail *fd; |
2885 | |
2886 gchar *sml = NULL; | |
2887 if (fonts) { | |
2888 fd = fonts->data; | |
2889 sml = fd->sml; | |
2890 } | |
9029 | 2891 if (!sml) |
2892 sml = imhtml->protocol_name; | |
2893 | |
8677 | 2894 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8505 | 2895 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
8473 | 2896 |
8677 | 2897 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, ws, iter); |
8473 | 2898 |
8505 | 2899 c += smilelen; |
2900 pos += smilelen; | |
8473 | 2901 wpos = 0; |
2902 ws[0] = 0; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2903 } else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &, &tlen)) { |
7280 | 2904 while(*amp) { |
2905 ws [wpos++] = *amp++; | |
2906 } | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2907 c += tlen; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2908 pos += tlen; |
1428 | 2909 } else if (*c == '\n') { |
2910 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | |
3922 | 2911 ws[wpos] = '\n'; |
2912 wpos++; | |
8677 | 2913 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2914 ws[0] = '\0'; |
2915 wpos = 0; | |
8177 | 2916 /* NEW_BIT (NEW_TEXT_BIT); */ |
10217 | 2917 } else if (!br) { /* Don't insert a space immediately after an HTML break */ |
9621 | 2918 /* A newline is defined by HTML as whitespace, which means we have to replace it with a word boundary. |
2919 * word breaks vary depending on the language used, so the correct thing to do is to use Pango to determine | |
2920 * what language this is, determine the proper word boundary to use, and insert that. I'm just going to insert | |
2921 * a space instead. What are the non-English speakers going to do? Complain in a language I'll understand? | |
2922 * Bu-wahaha! */ | |
2923 ws[wpos] = ' '; | |
2924 wpos++; | |
2925 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); | |
2926 ws[0] = '\0'; | |
2927 wpos = 0; | |
1428 | 2928 } |
2929 c++; | |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2930 pos++; |
8334 | 2931 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
2932 while(len_protocol--){ | |
8677 | 2933 /* Skip the next len_protocol characters, but make sure they're |
8334 | 2934 copied into the ws array. |
2935 */ | |
2936 ws [wpos++] = *c++; | |
2937 pos++; | |
2938 } | |
8061 | 2939 } else if (*c) { |
1428 | 2940 ws [wpos++] = *c++; |
2856
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2941 pos++; |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2942 } else { |
b1e300a85678
[gaim-migrate @ 2869]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2826
diff
changeset
|
2943 break; |
1428 | 2944 } |
2945 } | |
8677 | 2946 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
8061 | 2947 ws[0] = '\0'; wpos = 0; |
2948 | |
8177 | 2949 /* NEW_BIT(NEW_TEXT_BIT); */ |
8061 | 2950 |
4032 | 2951 while (fonts) { |
5967 | 2952 GtkIMHtmlFontDetail *font = fonts->data; |
4032 | 2953 fonts = g_slist_remove (fonts, font); |
2954 if (font->face) | |
2955 g_free (font->face); | |
2956 if (font->fore) | |
2957 g_free (font->fore); | |
2958 if (font->back) | |
2959 g_free (font->back); | |
2960 if (font->sml) | |
2961 g_free (font->sml); | |
2962 g_free (font); | |
2963 } | |
8932 | 2964 |
2965 g_free(ws); | |
2966 if (bg) | |
4630 | 2967 g_free(bg); |
8677 | 2968 |
2969 if (!imhtml->wbfo) | |
8698 | 2970 gtk_imhtml_close_tags(imhtml, iter); |
8506 | 2971 |
2972 object = g_object_ref(G_OBJECT(imhtml)); | |
2973 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | |
2974 g_object_unref(object); | |
2975 | |
3922 | 2976 } |
2977 | |
4892 | 2978 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
2979 { | |
4288 | 2980 g_hash_table_destroy(imhtml->smiley_data); |
2981 gtk_smiley_tree_destroy(imhtml->default_smilies); | |
4892 | 2982 imhtml->smiley_data = g_hash_table_new_full(g_str_hash, g_str_equal, |
4902 | 2983 g_free, (GDestroyNotify)gtk_smiley_tree_destroy); |
4288 | 2984 imhtml->default_smilies = gtk_smiley_tree_new(); |
2985 } | |
8481 | 2986 |
3922 | 2987 void gtk_imhtml_show_comments (GtkIMHtml *imhtml, |
4253 | 2988 gboolean show) |
2989 { | |
6124 | 2990 imhtml->show_comments = show; |
4253 | 2991 } |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
2992 |
8962 | 2993 void |
9029 | 2994 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, const gchar *protocol_name) { |
2995 if (imhtml->protocol_name) | |
2996 g_free(imhtml->protocol_name); | |
2997 imhtml->protocol_name = protocol_name ? g_strdup(protocol_name) : NULL; | |
8456 | 2998 } |
2999 | |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
3000 void |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3001 gtk_imhtml_delete(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3002 GList *l; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3003 GSList *sl; |
11234
7d5e8bed8018
[gaim-migrate @ 13377]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11233
diff
changeset
|
3004 GtkTextIter i, i_s, i_e; |
8427 | 3005 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3006 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3007 if (start == NULL) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3008 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
|
3009 start = &i_s; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3010 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3011 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3012 if (end == NULL) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3013 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
|
3014 end = &i_e; |
7991 | 3015 } |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3016 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3017 l = imhtml->scalables; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3018 while (l) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3019 GList *next = l->next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3020 struct scalable_data *sd = l->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3021 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3022 &i, sd->mark); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3023 if (gtk_text_iter_in_range(&i, start, end)) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3024 GtkIMHtmlScalable *scale = sd->scalable; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3025 scale->free(scale); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3026 imhtml->scalables = g_list_remove_link(imhtml->scalables, l); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3027 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3028 l = next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3029 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3030 |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3031 sl = imhtml->im_images; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3032 while (sl) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3033 GSList *next = sl->next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3034 struct im_image_data *img_data = sl->data; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3035 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3036 &i, img_data->mark); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3037 if (gtk_text_iter_in_range(&i, start, end)) { |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3038 if (imhtml->funcs->image_unref) |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3039 imhtml->funcs->image_unref(img_data->id); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3040 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
|
3041 g_free(img_data); |
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 = next; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3044 } |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
3045 gtk_text_buffer_delete(imhtml->text_buffer, start, end); |
8061 | 3046 |
8427 | 3047 g_object_unref(object); |
1780
d7cbedd1d651
[gaim-migrate @ 1790]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1738
diff
changeset
|
3048 } |
2363
08c66712364c
[gaim-migrate @ 2376]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2349
diff
changeset
|
3049 |
4046 | 3050 void gtk_imhtml_page_up (GtkIMHtml *imhtml) |
3051 { | |
5282 | 3052 GdkRectangle rect; |
3053 GtkTextIter iter; | |
4046 | 3054 |
5282 | 3055 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
3056 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
3057 rect.y - rect.height); | |
3058 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
8061 | 3059 |
4046 | 3060 } |
5282 | 3061 void gtk_imhtml_page_down (GtkIMHtml *imhtml) |
3062 { | |
3063 GdkRectangle rect; | |
3064 GtkTextIter iter; | |
3065 | |
3066 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
3067 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, | |
3068 rect.y + rect.height); | |
3069 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | |
3070 } | |
4735 | 3071 |
5967 | 3072 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
8962 | 3073 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) |
4735 | 3074 { |
5967 | 3075 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
5012 | 3076 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
4895 | 3077 |
5967 | 3078 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
3079 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; | |
3080 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; | |
5046 | 3081 |
3082 im_image->pixbuf = img; | |
5012 | 3083 im_image->image = image; |
4895 | 3084 im_image->width = gdk_pixbuf_get_width(img); |
3085 im_image->height = gdk_pixbuf_get_height(img); | |
3086 im_image->mark = NULL; | |
6982 | 3087 im_image->filename = filename ? g_strdup(filename) : NULL; |
8962 | 3088 im_image->id = id; |
9573 | 3089 im_image->filesel = NULL; |
4895 | 3090 |
5046 | 3091 g_object_ref(img); |
4895 | 3092 return GTK_IMHTML_SCALABLE(im_image); |
3093 } | |
3094 | |
5967 | 3095 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) |
4895 | 3096 { |
5967 | 3097 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
4895 | 3098 |
3099 if(image->width > width || image->height > height){ | |
3100 GdkPixbuf *new_image = NULL; | |
3101 float factor; | |
3102 int new_width = image->width, new_height = image->height; | |
3103 | |
8588 | 3104 if(image->width > (width - 2)){ |
4895 | 3105 factor = (float)(width)/image->width; |
3106 new_width = width; | |
3107 new_height = image->height * factor; | |
3108 } | |
8588 | 3109 if(new_height >= (height - 2)){ |
4895 | 3110 factor = (float)(height)/new_height; |
3111 new_height = height; | |
3112 new_width = new_width * factor; | |
3113 } | |
3114 | |
5046 | 3115 new_image = gdk_pixbuf_scale_simple(image->pixbuf, new_width, new_height, GDK_INTERP_BILINEAR); |
5012 | 3116 gtk_image_set_from_pixbuf(image->image, new_image); |
4895 | 3117 g_object_unref(G_OBJECT(new_image)); |
3118 } | |
3119 } | |
3120 | |
9573 | 3121 static void |
3122 image_save_yes_cb(GtkIMHtmlImage *image, const char *filename) | |
5012 | 3123 { |
3124 gchar *type = NULL; | |
5019 | 3125 GError *error = NULL; |
5015 | 3126 #if GTK_CHECK_VERSION(2,2,0) |
5012 | 3127 GSList *formats = gdk_pixbuf_get_formats(); |
6162 | 3128 #else |
3129 char *basename = g_path_get_basename(filename); | |
3130 char *ext = strrchr(basename, '.'); | |
5959 | 3131 #endif |
5012 | 3132 |
9573 | 3133 gtk_widget_destroy(image->filesel); |
3134 image->filesel = NULL; | |
5959 | 3135 |
3136 #if GTK_CHECK_VERSION(2,2,0) | |
9573 | 3137 while (formats) { |
5012 | 3138 GdkPixbufFormat *format = formats->data; |
3139 gchar **extensions = gdk_pixbuf_format_get_extensions(format); | |
3140 gpointer p = extensions; | |
3141 | |
3142 while(gdk_pixbuf_format_is_writable(format) && extensions && extensions[0]){ | |
3143 gchar *fmt_ext = extensions[0]; | |
3144 const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext); | |
3145 | |
3146 if(!strcmp(fmt_ext, file_ext)){ | |
3147 type = gdk_pixbuf_format_get_name(format); | |
3148 break; | |
3149 } | |
3150 | |
3151 extensions++; | |
3152 } | |
3153 | |
3154 g_strfreev(p); | |
3155 | |
9573 | 3156 if (type) |
5012 | 3157 break; |
3158 | |
3159 formats = formats->next; | |
3160 } | |
3161 | |
5020 | 3162 g_slist_free(formats); |
3163 #else | |
3164 /* this is really ugly code, but I think it will work */ | |
9573 | 3165 if (ext) { |
5020 | 3166 ext++; |
9573 | 3167 if (!g_ascii_strcasecmp(ext, "jpeg") || !g_ascii_strcasecmp(ext, "jpg")) |
5020 | 3168 type = g_strdup("jpeg"); |
9573 | 3169 else if (!g_ascii_strcasecmp(ext, "png")) |
5020 | 3170 type = g_strdup("png"); |
3171 } | |
3172 | |
3173 g_free(basename); | |
3174 #endif | |
3175 | |
5012 | 3176 /* If I can't find a valid type, I will just tell the user about it and then assume |
3177 it's a png */ | |
9573 | 3178 if (!type){ |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3179 #if GTK_CHECK_VERSION(2,4,0) |
11019 | 3180 GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
3181 _("<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
|
3182 #else |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3183 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
|
3184 _("Unrecognized file type\n\nDefaulting to PNG.")); |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3185 #endif |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3186 |
11019 | 3187 g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); |
3188 gtk_widget_show(dialog); | |
9717 | 3189 type = g_strdup("png"); |
5012 | 3190 } |
3191 | |
5046 | 3192 gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL); |
5012 | 3193 |
9573 | 3194 if (error){ |
11069
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3195 #if GTK_CHECK_VERSION(2,4,0) |
11019 | 3196 GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
3197 _("<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
|
3198 #else |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3199 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
|
3200 _("Error saving image\n\n%s"), error->message); |
65db26d0bc90
[gaim-migrate @ 13065]
Richard Laager <rlaager@wiktel.com>
parents:
11019
diff
changeset
|
3201 #endif |
11019 | 3202 g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); |
3203 gtk_widget_show(dialog); | |
5012 | 3204 g_error_free(error); |
3205 } | |
3206 | |
3207 g_free(type); | |
3208 } | |
3209 | |
9573 | 3210 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
3211 static void | |
3212 image_save_check_if_exists_cb(GtkWidget *widget, gint response, GtkIMHtmlImage *image) | |
3213 { | |
3214 gchar *filename; | |
3215 | |
3216 if (response != GTK_RESPONSE_ACCEPT) { | |
3217 gtk_widget_destroy(widget); | |
3218 image->filesel = NULL; | |
3219 return; | |
3220 } | |
3221 | |
3222 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); | |
3223 #else /* FILECHOOSER */ | |
3224 static void | |
3225 image_save_check_if_exists_cb(GtkWidget *button, GtkIMHtmlImage *image) | |
5012 | 3226 { |
9573 | 3227 gchar *filename; |
3228 | |
3229 filename = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(image->filesel))); | |
3230 | |
3231 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { | |
3232 gchar *dirname; | |
3233 /* append a / is needed */ | |
3234 if (filename[strlen(filename) - 1] != G_DIR_SEPARATOR) { | |
3235 dirname = g_strconcat(filename, G_DIR_SEPARATOR_S, NULL); | |
3236 } else { | |
3237 dirname = g_strdup(filename); | |
3238 } | |
9574 | 3239 gtk_file_selection_set_filename(GTK_FILE_SELECTION(image->filesel), dirname); |
9573 | 3240 g_free(dirname); |
3241 g_free(filename); | |
3242 return; | |
3243 } | |
3244 #endif /* FILECHOOSER */ | |
3245 | |
3246 /* | |
3247 * XXX - We should probably prompt the user to determine if they really | |
3248 * want to overwrite the file or not. However, I don't feel like doing | |
3249 * that, so we're just always going to overwrite if the file exists. | |
3250 */ | |
3251 /* | |
3252 if (g_file_test(filename, G_FILE_TEST_EXISTS)) { | |
3253 } else | |
3254 image_save_yes_cb(image, filename); | |
3255 */ | |
3256 | |
3257 image_save_yes_cb(image, filename); | |
3258 | |
3259 g_free(filename); | |
3260 } | |
3261 | |
3262 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
3263 static void | |
3264 image_save_cancel_cb(GtkIMHtmlImage *image) | |
3265 { | |
3266 gtk_widget_destroy(image->filesel); | |
3267 image->filesel = NULL; | |
3268 } | |
3269 #endif /* FILECHOOSER */ | |
3270 | |
3271 static void | |
3272 gtk_imhtml_image_save(GtkWidget *w, GtkIMHtmlImage *image) | |
3273 { | |
3274 if (image->filesel != NULL) { | |
3275 gtk_window_present(GTK_WINDOW(image->filesel)); | |
3276 return; | |
3277 } | |
3278 | |
3279 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
3280 image->filesel = gtk_file_chooser_dialog_new(_("Save Image"), | |
3281 NULL, | |
3282 GTK_FILE_CHOOSER_ACTION_SAVE, | |
3283 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
3284 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, | |
3285 NULL); | |
3286 gtk_dialog_set_default_response(GTK_DIALOG(image->filesel), GTK_RESPONSE_ACCEPT); | |
3287 if (image->filename != NULL) | |
3288 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(image->filesel), image->filename); | |
3289 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(image->filesel)), "response", | |
3290 G_CALLBACK(image_save_check_if_exists_cb), image); | |
3291 #else /* FILECHOOSER */ | |
3292 image->filesel = gtk_file_selection_new(_("Save Image")); | |
3293 if (image->filename != NULL) | |
3294 gtk_file_selection_set_filename(GTK_FILE_SELECTION(image->filesel), image->filename); | |
9574 | 3295 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(image->filesel)), "delete_event", |
3296 G_CALLBACK(image_save_cancel_cb), image); | |
3297 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->cancel_button), | |
3298 "clicked", G_CALLBACK(image_save_cancel_cb), image); | |
9573 | 3299 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(image->filesel)->ok_button), "clicked", |
3300 G_CALLBACK(image_save_check_if_exists_cb), image); | |
3301 #endif /* FILECHOOSER */ | |
3302 | |
3303 gtk_widget_show(image->filesel); | |
5012 | 3304 } |
3305 | |
9815 | 3306 /* |
3307 * So, um, AIM Direct IM lets you send any file, not just images. You can | |
3308 * just insert a sound or a file or whatever in a conversation. It's | |
3309 * basically like file transfer, except there is an icon to open the file | |
3310 * embedded in the conversation. Someone should make the Gaim core handle | |
3311 * all of that. | |
3312 */ | |
5967 | 3313 static gboolean gtk_imhtml_image_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlImage *image) |
5012 | 3314 { |
3315 GdkEventButton *event_button = (GdkEventButton *) event; | |
3316 | |
3317 if (event->type == GDK_BUTTON_RELEASE) { | |
3318 if(event_button->button == 3) { | |
3319 GtkWidget *img, *item, *menu; | |
3320 gchar *text = g_strdup_printf(_("_Save Image...")); | |
3321 menu = gtk_menu_new(); | |
3322 | |
3323 /* buttons and such */ | |
3324 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); | |
3325 item = gtk_image_menu_item_new_with_mnemonic(text); | |
3326 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | |
5967 | 3327 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_image_save), image); |
5012 | 3328 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3329 | |
3330 gtk_widget_show_all(menu); | |
3331 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, | |
3332 event_button->button, event_button->time); | |
3333 | |
3334 g_free(text); | |
3335 return TRUE; | |
3336 } | |
3337 } | |
3338 if(event->type == GDK_BUTTON_PRESS && event_button->button == 3) | |
3339 return TRUE; /* Clicking the right mouse button on a link shouldn't | |
3340 be caught by the regular GtkTextView menu */ | |
3341 else | |
3342 return FALSE; /* Let clicks go through if we didn't catch anything */ | |
3343 | |
3344 } | |
5967 | 3345 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) |
3346 { | |
3347 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
3348 | |
3349 g_object_unref(image->pixbuf); | |
6982 | 3350 if (image->filename) |
3351 g_free(image->filename); | |
9573 | 3352 if (image->filesel) |
3353 gtk_widget_destroy(image->filesel); | |
5967 | 3354 g_free(scale); |
3355 } | |
3356 | |
3357 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
3358 { | |
3359 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | |
3360 GtkWidget *box = gtk_event_box_new(); | |
8962 | 3361 char *tag; |
5967 | 3362 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
3363 | |
3364 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | |
9229 | 3365 |
3366 if(!gtk_check_version(2, 4, 0)) | |
3367 g_object_set(G_OBJECT(box), "visible-window", FALSE, NULL); | |
5967 | 3368 |
3369 gtk_widget_show(GTK_WIDGET(image->image)); | |
3370 gtk_widget_show(box); | |
3371 | |
8962 | 3372 tag = g_strdup_printf("<IMG ID=\"%d\">", image->id); |
3373 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free); | |
3374 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); | |
3375 | |
5967 | 3376 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); |
3377 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | |
3378 } | |
3379 | |
3380 GtkIMHtmlScalable *gtk_imhtml_hr_new() | |
3381 { | |
3382 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); | |
3383 | |
3384 GTK_IMHTML_SCALABLE(hr)->scale = gtk_imhtml_hr_scale; | |
3385 GTK_IMHTML_SCALABLE(hr)->add_to = gtk_imhtml_hr_add_to; | |
3386 GTK_IMHTML_SCALABLE(hr)->free = gtk_imhtml_hr_free; | |
3387 | |
3388 hr->sep = gtk_hseparator_new(); | |
3389 gtk_widget_set_size_request(hr->sep, 5000, 2); | |
3390 gtk_widget_show(hr->sep); | |
3391 | |
3392 return GTK_IMHTML_SCALABLE(hr); | |
3393 } | |
3394 | |
3395 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *scale, int width, int height) | |
3396 { | |
8588 | 3397 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); |
5967 | 3398 } |
3399 | |
3400 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | |
3401 { | |
3402 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | |
3403 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | |
8698 | 3404 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); |
3405 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); | |
5967 | 3406 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
3407 } | |
3408 | |
3409 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | |
3410 { | |
3411 g_free(scale); | |
3412 } | |
7295 | 3413 |
3414 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | |
3415 { | |
3416 GtkTextIter iter, start, end; | |
3417 gboolean new_search = TRUE; | |
3418 | |
3419 g_return_val_if_fail(imhtml != NULL, FALSE); | |
3420 g_return_val_if_fail(text != NULL, FALSE); | |
8061 | 3421 |
7295 | 3422 if (imhtml->search_string && !strcmp(text, imhtml->search_string)) |
3423 new_search = FALSE; | |
8061 | 3424 |
7295 | 3425 if (new_search) { |
3426 gtk_imhtml_search_clear(imhtml); | |
3427 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
3428 } else { | |
3429 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, | |
8061 | 3430 gtk_text_buffer_get_mark(imhtml->text_buffer, "search")); |
7295 | 3431 } |
10574 | 3432 g_free(imhtml->search_string); |
7295 | 3433 imhtml->search_string = g_strdup(text); |
3434 | |
7358 | 3435 if (gtk_source_iter_forward_search(&iter, imhtml->search_string, |
3436 GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_CASE_INSENSITIVE, | |
7295 | 3437 &start, &end, NULL)) { |
3438 | |
3439 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0); | |
3440 gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE); | |
3441 if (new_search) { | |
3442 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end); | |
8061 | 3443 do |
7295 | 3444 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end); |
8061 | 3445 while (gtk_source_iter_forward_search(&end, imhtml->search_string, |
3446 GTK_SOURCE_SEARCH_VISIBLE_ONLY | | |
7358 | 3447 GTK_SOURCE_SEARCH_CASE_INSENSITIVE, |
7295 | 3448 &start, &end, NULL)); |
3449 } | |
3450 return TRUE; | |
3451 } | |
8061 | 3452 |
3453 gtk_imhtml_search_clear(imhtml); | |
3454 | |
7295 | 3455 return FALSE; |
3456 } | |
3457 | |
3458 void gtk_imhtml_search_clear(GtkIMHtml *imhtml) | |
3459 { | |
3460 GtkTextIter start, end; | |
8061 | 3461 |
7295 | 3462 g_return_if_fail(imhtml != NULL); |
8061 | 3463 |
7295 | 3464 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
3465 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3466 | |
3467 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end); | |
3468 if (imhtml->search_string) | |
3469 g_free(imhtml->search_string); | |
3470 imhtml->search_string = NULL; | |
3471 } | |
8061 | 3472 |
8677 | 3473 static GtkTextTag *find_font_forecolor_tag(GtkIMHtml *imhtml, gchar *color) |
3474 { | |
3475 gchar str[18]; | |
3476 GtkTextTag *tag; | |
3477 | |
3478 g_snprintf(str, sizeof(str), "FORECOLOR %s", color); | |
3479 | |
3480 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
10858 | 3481 if (!tag) { |
3482 GdkColor gcolor; | |
3483 if (!gdk_color_parse(color, &gcolor)) { | |
3484 gchar tmp[8]; | |
3485 tmp[0] = '#'; | |
3486 strncpy(&tmp[1], color, 7); | |
3487 tmp[7] = '\0'; | |
3488 if (!gdk_color_parse(tmp, &gcolor)) | |
3489 gdk_color_parse("black", &gcolor); | |
3490 } | |
3491 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground-gdk", &gcolor, NULL); | |
3492 } | |
8677 | 3493 |
3494 return tag; | |
3495 } | |
3496 | |
3497 static GtkTextTag *find_font_backcolor_tag(GtkIMHtml *imhtml, gchar *color) | |
3498 { | |
3499 gchar str[18]; | |
3500 GtkTextTag *tag; | |
3501 | |
3502 g_snprintf(str, sizeof(str), "BACKCOLOR %s", color); | |
3503 | |
3504 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
10858 | 3505 if (!tag) { |
3506 GdkColor gcolor; | |
3507 if (!gdk_color_parse(color, &gcolor)) { | |
3508 gchar tmp[8]; | |
3509 tmp[0] = '#'; | |
3510 strncpy(&tmp[1], color, 7); | |
3511 tmp[7] = '\0'; | |
3512 if (!gdk_color_parse(tmp, &gcolor)) | |
3513 gdk_color_parse("white", &gcolor); | |
3514 } | |
3515 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "background-gdk", &gcolor, NULL); | |
3516 } | |
8677 | 3517 |
3518 return tag; | |
3519 } | |
3520 | |
10776 | 3521 static GtkTextTag *find_font_background_tag(GtkIMHtml *imhtml, gchar *color) |
3522 { | |
3523 gchar str[19]; | |
3524 GtkTextTag *tag; | |
3525 | |
3526 g_snprintf(str, sizeof(str), "BACKGROUND %s", color); | |
3527 | |
3528 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3529 if (!tag) | |
3530 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, NULL); | |
3531 | |
3532 return tag; | |
3533 } | |
3534 | |
8677 | 3535 static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) |
8061 | 3536 { |
8677 | 3537 gchar str[256]; |
3538 GtkTextTag *tag; | |
3539 | |
3540 g_snprintf(str, sizeof(str), "FONT FACE %s", face); | |
3541 str[255] = '\0'; | |
3542 | |
3543 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3544 if (!tag) | |
3545 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "family", face, NULL); | |
3546 | |
3547 return tag; | |
3548 } | |
3549 | |
3550 static GtkTextTag *find_font_size_tag(GtkIMHtml *imhtml, int size) | |
3551 { | |
3552 gchar str[24]; | |
3553 GtkTextTag *tag; | |
3554 | |
3555 g_snprintf(str, sizeof(str), "FONT SIZE %d", size); | |
3556 str[23] = '\0'; | |
3557 | |
3558 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
3559 if (!tag) { | |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3560 /* For reasons I don't understand, setting "scale" here scaled |
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3561 * based on some default size other than my theme's default |
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3562 * 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
|
3563 * me. So this works around that oddity. |
8677 | 3564 */ |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3565 GtkTextAttributes *attr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(imhtml)); |
8677 | 3566 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
|
3567 (gint) (pango_font_description_get_size(attr->font) * |
10899 | 3568 (double) POINT_SIZE(size)), NULL); |
10525
ddea15f4cbc2
[gaim-migrate @ 11842]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10524
diff
changeset
|
3569 gtk_text_attributes_unref(attr); |
8061 | 3570 } |
3571 | |
8677 | 3572 return tag; |
3573 } | |
3574 | |
3575 static void remove_tag_by_prefix(GtkIMHtml *imhtml, const GtkTextIter *i, const GtkTextIter *e, | |
3576 const char *prefix, guint len, gboolean homo) | |
3577 { | |
3578 GSList *tags, *l; | |
3579 GtkTextIter iter; | |
3580 | |
3581 tags = gtk_text_iter_get_tags(i); | |
3582 | |
3583 for (l = tags; l; l = l->next) { | |
3584 GtkTextTag *tag = l->data; | |
3585 | |
3586 if (tag->name && !strncmp(tag->name, prefix, len)) | |
3587 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); | |
8061 | 3588 } |
3589 | |
8677 | 3590 g_slist_free(tags); |
3591 | |
3592 if (homo) | |
3593 return; | |
3594 | |
3595 iter = *i; | |
3596 | |
3597 while (gtk_text_iter_forward_char(&iter) && !gtk_text_iter_equal(&iter, e)) { | |
3598 if (gtk_text_iter_begins_tag(&iter, NULL)) { | |
3599 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); | |
3600 | |
3601 for (l = tags; l; l = l->next) { | |
3602 GtkTextTag *tag = l->data; | |
3603 | |
3604 if (tag->name && !strncmp(tag->name, prefix, len)) | |
3605 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); | |
3606 } | |
3607 | |
3608 g_slist_free(tags); | |
3609 } | |
8061 | 3610 } |
8677 | 3611 } |
3612 | |
3613 static void remove_font_size(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3614 { | |
3615 remove_tag_by_prefix(imhtml, i, e, "FONT SIZE ", 10, homo); | |
3616 } | |
3617 | |
3618 static void remove_font_face(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3619 { | |
3620 remove_tag_by_prefix(imhtml, i, e, "FONT FACE ", 10, homo); | |
3621 } | |
3622 | |
3623 static void remove_font_forecolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3624 { | |
3625 remove_tag_by_prefix(imhtml, i, e, "FORECOLOR ", 10, homo); | |
3626 } | |
3627 | |
3628 static void remove_font_backcolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
3629 { | |
3630 remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); | |
3631 } | |
3632 | |
10776 | 3633 static void remove_font_background(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) |
3634 { | |
3635 remove_tag_by_prefix(imhtml, i, e, "BACKGROUND ", 10, homo); | |
3636 } | |
3637 | |
8677 | 3638 static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) |
3639 { | |
3640 remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); | |
3641 } | |
3642 | |
3643 /* Editable stuff */ | |
3644 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | |
3645 { | |
3646 imhtml->insert_offset = gtk_text_iter_get_offset(iter); | |
3647 } | |
3648 | |
10169 | 3649 static void insert_ca_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextChildAnchor *arg2, gpointer user_data) |
3650 { | |
3651 GtkTextIter start; | |
3652 | |
3653 start = *arg1; | |
3654 gtk_text_iter_backward_char(&start); | |
3655 | |
3656 gtk_imhtml_apply_tags_on_insert(user_data, &start, arg1); | |
3657 } | |
3658 | |
8677 | 3659 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) |
3660 { | |
3661 GtkTextIter start; | |
3662 | |
3663 if (!len) | |
3664 return; | |
3665 | |
3666 start = *end; | |
3667 gtk_text_iter_set_offset(&start, imhtml->insert_offset); | |
3668 | |
10169 | 3669 gtk_imhtml_apply_tags_on_insert(imhtml, &start, end); |
3670 } | |
3671 | |
3672 static void gtk_imhtml_apply_tags_on_insert(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) | |
3673 { | |
8677 | 3674 if (imhtml->edit.bold) |
10169 | 3675 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", start, end); |
8677 | 3676 else |
10169 | 3677 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", start, end); |
8677 | 3678 |
3679 if (imhtml->edit.italic) | |
10169 | 3680 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", start, end); |
8677 | 3681 else |
10169 | 3682 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", start, end); |
8677 | 3683 |
3684 if (imhtml->edit.underline) | |
10169 | 3685 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", start, end); |
8677 | 3686 else |
10169 | 3687 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", start, end); |
8677 | 3688 |
9924 | 3689 if (imhtml->edit.strike) |
10169 | 3690 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", start, end); |
9924 | 3691 else |
10169 | 3692 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", start, end); |
9924 | 3693 |
8677 | 3694 if (imhtml->edit.forecolor) { |
10169 | 3695 remove_font_forecolor(imhtml, start, end, TRUE); |
8677 | 3696 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3697 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
10169 | 3698 start, end); |
8061 | 3699 } |
3700 | |
8677 | 3701 if (imhtml->edit.backcolor) { |
10169 | 3702 remove_font_backcolor(imhtml, start, end, TRUE); |
8677 | 3703 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3704 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), | |
10169 | 3705 start, end); |
8677 | 3706 } |
3707 | |
10776 | 3708 if (imhtml->edit.background) { |
3709 remove_font_background(imhtml, start, end, TRUE); | |
3710 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3711 find_font_background_tag(imhtml, imhtml->edit.background), | |
3712 start, end); | |
3713 } | |
8677 | 3714 if (imhtml->edit.fontface) { |
10169 | 3715 remove_font_face(imhtml, start, end, TRUE); |
8677 | 3716 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3717 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
10169 | 3718 start, end); |
8061 | 3719 } |
8677 | 3720 |
3721 if (imhtml->edit.fontsize) { | |
10169 | 3722 remove_font_size(imhtml, start, end, TRUE); |
8677 | 3723 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3724 find_font_size_tag(imhtml, imhtml->edit.fontsize), | |
10169 | 3725 start, end); |
8677 | 3726 } |
3727 | |
3728 if (imhtml->edit.link) { | |
10169 | 3729 remove_font_link(imhtml, start, end, TRUE); |
8677 | 3730 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
3731 imhtml->edit.link, | |
10169 | 3732 start, end); |
8677 | 3733 } |
8061 | 3734 } |
3735 | |
3736 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | |
3737 { | |
3738 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | |
8177 | 3739 /* |
3740 * We need a visible caret for accessibility, so mouseless | |
3741 * people can highlight stuff. | |
3742 */ | |
3743 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | |
8061 | 3744 imhtml->editable = editable; |
8677 | 3745 imhtml->format_functions = GTK_IMHTML_ALL; |
3746 | |
3747 if (editable) | |
3748 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
3749 G_CALLBACK(mark_set_cb), imhtml); | |
3750 } | |
3751 | |
3752 void gtk_imhtml_set_whole_buffer_formatting_only(GtkIMHtml *imhtml, gboolean wbfo) | |
3753 { | |
3754 g_return_if_fail(imhtml != NULL); | |
3755 | |
3756 imhtml->wbfo = wbfo; | |
8420 | 3757 } |
3758 | |
3759 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | |
3760 { | |
3761 GObject *object = g_object_ref(G_OBJECT(imhtml)); | |
8677 | 3762 imhtml->format_functions = buttons; |
8420 | 3763 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); |
3764 g_object_unref(object); | |
8061 | 3765 } |
3766 | |
8788 | 3767 GtkIMHtmlButtons gtk_imhtml_get_format_functions(GtkIMHtml *imhtml) |
3768 { | |
3769 return imhtml->format_functions; | |
3770 } | |
8516 | 3771 |
3772 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, | |
3773 gboolean *italic, gboolean *underline) | |
8481 | 3774 { |
8677 | 3775 if (imhtml->edit.bold) |
3776 (*bold) = TRUE; | |
3777 if (imhtml->edit.italic) | |
3778 (*italic) = TRUE; | |
3779 if (imhtml->edit.underline) | |
3780 (*underline) = TRUE; | |
8481 | 3781 } |
3782 | |
9025 | 3783 char * |
3784 gtk_imhtml_get_current_fontface(GtkIMHtml *imhtml) | |
3785 { | |
3786 if (imhtml->edit.fontface) | |
3787 return g_strdup(imhtml->edit.fontface); | |
3788 else | |
3789 return NULL; | |
3790 } | |
3791 | |
3792 char * | |
3793 gtk_imhtml_get_current_forecolor(GtkIMHtml *imhtml) | |
3794 { | |
3795 if (imhtml->edit.forecolor) | |
3796 return g_strdup(imhtml->edit.forecolor); | |
3797 else | |
3798 return NULL; | |
3799 } | |
3800 | |
3801 char * | |
3802 gtk_imhtml_get_current_backcolor(GtkIMHtml *imhtml) | |
3803 { | |
3804 if (imhtml->edit.backcolor) | |
3805 return g_strdup(imhtml->edit.backcolor); | |
3806 else | |
3807 return NULL; | |
3808 } | |
3809 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3810 char * |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3811 gtk_imhtml_get_current_background(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3812 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3813 if (imhtml->edit.background) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3814 return g_strdup(imhtml->edit.background); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3815 else |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3816 return NULL; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3817 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3818 |
9025 | 3819 gint |
3820 gtk_imhtml_get_current_fontsize(GtkIMHtml *imhtml) | |
3821 { | |
3822 return imhtml->edit.fontsize; | |
3823 } | |
3824 | |
8061 | 3825 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) |
3826 { | |
3827 return imhtml->editable; | |
3828 } | |
3829 | |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3830 void |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3831 gtk_imhtml_clear_formatting(GtkIMHtml *imhtml) |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3832 { |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3833 GtkTextIter start, end; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3834 GObject *object; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3835 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3836 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3837 |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3838 /* Move the selection bounds (to select everything), so the format functions |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3839 * 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
|
3840 #if GTK_CHECK_VERSION(2,4,0) |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3841 gtk_text_buffer_select_range(imhtml->text_buffer, &end, &start); |
11275
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3842 #else |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3843 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
|
3844 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
|
3845 #endif |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3846 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3847 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
|
3848 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
|
3849 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
|
3850 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
|
3851 remove_font_size(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3852 remove_font_face(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3853 remove_font_forecolor(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3854 remove_font_backcolor(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3855 remove_font_background(imhtml, &start, &end, TRUE); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3856 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3857 imhtml->edit.bold = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3858 imhtml->edit.italic = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3859 imhtml->edit.underline = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3860 imhtml->edit.strike = 0; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3861 imhtml->edit.fontsize = 3; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3862 imhtml->edit.forecolor = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3863 imhtml->edit.backcolor = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3864 imhtml->edit.background = NULL; |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3865 |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3866 object = g_object_ref(G_OBJECT(imhtml)); |
ffc86d9ad8b7
[gaim-migrate @ 13461]
Richard Laager <rlaager@wiktel.com>
parents:
11269
diff
changeset
|
3867 g_signal_emit(object, signals[CLEAR_FORMAT], 0); |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3868 |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3869 /* Remove the selection, placing the cursor at the end. */ |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3870 #if GTK_CHECK_VERSION(2,4,0) |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3871 gtk_text_buffer_select_range(imhtml->text_buffer, &end, &end); |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3872 #else |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3873 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
|
3874 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
|
3875 #endif |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3876 |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3877 gtk_widget_grab_focus(GTK_WIDGET(imhtml)); |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3878 |
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
3879 g_object_unref(object); |
11269
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3880 } |
1cbe76d30e81
[gaim-migrate @ 13451]
Richard Laager <rlaager@wiktel.com>
parents:
11267
diff
changeset
|
3881 |
8677 | 3882 /* |
3883 * I had this crazy idea about changing the text cursor color to reflex the foreground color | |
3884 * of the text about to be entered. This is the place you'd do it, along with the place where | |
3885 * we actually set a new foreground color. | |
3886 * I may not do this, because people will bitch about Gaim overriding their gtk theme's cursor | |
3887 * colors. | |
3888 * | |
3889 * Just in case I do do this, I asked about what to set the secondary text cursor to. | |
3890 * | |
8719 | 3891 * (12:45:27) ?? ???: secondary_cursor_color = (rgb(background) + rgb(primary_cursor_color) ) / 2 |
3892 * (12:45:55) ?? ???: understand? | |
8677 | 3893 * (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
|
3894 * (12:46:56) ?? ???: u might need to extract separate each color from RGB |
8677 | 3895 */ |
3896 | |
3897 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, | |
3898 GtkIMHtml *imhtml) | |
3899 { | |
3900 GSList *tags, *l; | |
3901 GtkTextIter iter; | |
3902 | |
3903 if (mark != gtk_text_buffer_get_insert(buffer)) | |
3904 return; | |
3905 | |
3906 if (!gtk_text_buffer_get_char_count(buffer)) | |
3907 return; | |
3908 | |
9924 | 3909 imhtml->edit.bold = imhtml->edit.italic = imhtml->edit.underline = imhtml->edit.strike = FALSE; |
8677 | 3910 if (imhtml->edit.forecolor) |
3911 g_free(imhtml->edit.forecolor); | |
3912 imhtml->edit.forecolor = NULL; | |
3913 if (imhtml->edit.backcolor) | |
3914 g_free(imhtml->edit.backcolor); | |
3915 imhtml->edit.backcolor = NULL; | |
3916 if (imhtml->edit.fontface) | |
3917 g_free(imhtml->edit.fontface); | |
3918 imhtml->edit.fontface = NULL; | |
3919 imhtml->edit.fontsize = 0; | |
3920 imhtml->edit.link = NULL; | |
3921 | |
3922 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
3923 | |
3924 | |
3925 if (gtk_text_iter_is_end(&iter)) | |
3926 tags = gtk_text_iter_get_toggled_tags(&iter, FALSE); | |
3927 else | |
3928 tags = gtk_text_iter_get_tags(&iter); | |
3929 | |
3930 for (l = tags; l != NULL; l = l->next) { | |
3931 GtkTextTag *tag = GTK_TEXT_TAG(l->data); | |
3932 | |
3933 if (tag->name) { | |
3934 if (strcmp(tag->name, "BOLD") == 0) | |
3935 imhtml->edit.bold = TRUE; | |
3936 if (strcmp(tag->name, "ITALICS") == 0) | |
3937 imhtml->edit.italic = TRUE; | |
3938 if (strcmp(tag->name, "UNDERLINE") == 0) | |
3939 imhtml->edit.underline = TRUE; | |
9924 | 3940 if (strcmp(tag->name, "STRIKE") == 0) |
3941 imhtml->edit.strike = TRUE; | |
8677 | 3942 if (strncmp(tag->name, "FORECOLOR ", 10) == 0) |
3943 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); | |
3944 if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) | |
3945 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); | |
3946 if (strncmp(tag->name, "FONT FACE ", 10) == 0) | |
3947 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); | |
3948 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) | |
3949 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); | |
8719 | 3950 if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) |
8677 | 3951 imhtml->edit.link = tag; |
3952 } | |
3953 } | |
3954 | |
3955 g_slist_free(tags); | |
3956 } | |
3957 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3958 static void imhtml_toggle_bold(GtkIMHtml *imhtml) |
8061 | 3959 { |
8677 | 3960 GtkTextIter start, end; |
3961 | |
3962 imhtml->edit.bold = !imhtml->edit.bold; | |
3963 | |
3964 if (imhtml->wbfo) { | |
3965 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3966 if (imhtml->edit.bold) | |
3967 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3968 else | |
3969 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
|
3970 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 3971 if (imhtml->edit.bold) |
3972 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); | |
3973 else | |
3974 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
|
3975 |
8061 | 3976 } |
3977 } | |
3978 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3979 void gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) |
8061 | 3980 { |
8481 | 3981 GObject *object; |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3982 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3983 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3984 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3985 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3986 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3987 g_object_unref(object); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3988 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3989 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3990 static void imhtml_toggle_italic(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
3991 { |
8677 | 3992 GtkTextIter start, end; |
3993 | |
3994 imhtml->edit.italic = !imhtml->edit.italic; | |
3995 | |
3996 if (imhtml->wbfo) { | |
3997 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3998 if (imhtml->edit.italic) | |
3999 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
4000 else | |
4001 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
|
4002 } 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
|
4003 if (imhtml->edit.italic) |
8677 | 4004 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
4005 else | |
4006 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); | |
8061 | 4007 } |
4008 } | |
4009 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4010 void gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) |
8061 | 4011 { |
8481 | 4012 GObject *object; |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4013 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4014 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4015 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4016 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4017 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4018 g_object_unref(object);} |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4019 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4020 static void imhtml_toggle_underline(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4021 { |
8677 | 4022 GtkTextIter start, end; |
4023 | |
4024 imhtml->edit.underline = !imhtml->edit.underline; | |
4025 | |
4026 if (imhtml->wbfo) { | |
4027 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4028 if (imhtml->edit.underline) | |
4029 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
4030 else | |
4031 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
|
4032 } 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
|
4033 if (imhtml->edit.underline) |
8677 | 4034 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
4035 else | |
4036 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); | |
8061 | 4037 } |
4038 } | |
4039 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4040 void gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) |
9924 | 4041 { |
4042 GObject *object; | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4043 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4044 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4045 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4046 object = g_object_ref(G_OBJECT(imhtml)); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4047 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4048 g_object_unref(object); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4049 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4050 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4051 static void imhtml_toggle_strike(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4052 { |
9924 | 4053 GtkTextIter start, end; |
4054 | |
4055 imhtml->edit.strike = !imhtml->edit.strike; | |
4056 | |
4057 if (imhtml->wbfo) { | |
4058 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4059 if (imhtml->edit.strike) | |
4060 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); | |
4061 else | |
4062 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
|
4063 } 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
|
4064 if (imhtml->edit.strike) |
9924 | 4065 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); |
4066 else | |
4067 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "STRIKE", &start, &end); | |
4068 } | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4069 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4070 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4071 void gtk_imhtml_toggle_strike(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4072 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4073 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4074 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4075 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4076 |
9924 | 4077 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4078 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_STRIKE); |
9924 | 4079 g_object_unref(object); |
4080 } | |
4081 | |
8061 | 4082 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) |
4083 { | |
9025 | 4084 GObject *object; |
8677 | 4085 GtkTextIter start, end; |
8061 | 4086 |
4087 imhtml->edit.fontsize = size; | |
4088 | |
8677 | 4089 if (imhtml->wbfo) { |
4090 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4091 remove_font_size(imhtml, &start, &end, TRUE); | |
4092 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4093 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4094 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4095 remove_font_size(imhtml, &start, &end, FALSE); |
4096 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4097 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4098 } |
8677 | 4099 |
9025 | 4100 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4101 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_SHRINK | GTK_IMHTML_GROW); |
9025 | 4102 g_object_unref(object); |
8061 | 4103 } |
4104 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4105 static void imhtml_font_shrink(GtkIMHtml *imhtml) |
8061 | 4106 { |
8677 | 4107 GtkTextIter start, end; |
4108 | |
8061 | 4109 if (imhtml->edit.fontsize == 1) |
4110 return; | |
4111 | |
8677 | 4112 if (!imhtml->edit.fontsize) |
4113 imhtml->edit.fontsize = 2; | |
4114 else | |
4115 imhtml->edit.fontsize--; | |
4116 | |
4117 if (imhtml->wbfo) { | |
4118 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4119 remove_font_size(imhtml, &start, &end, TRUE); | |
4120 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4121 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4122 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4123 remove_font_size(imhtml, &start, &end, FALSE); |
4124 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4125 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4126 } |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4127 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4128 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4129 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4130 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4131 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4132 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4133 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4134 |
9025 | 4135 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4136 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_SHRINK); |
9025 | 4137 g_object_unref(object); |
8061 | 4138 } |
4139 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4140 static void imhtml_font_grow(GtkIMHtml *imhtml) |
8061 | 4141 { |
8677 | 4142 GtkTextIter start, end; |
4143 | |
8061 | 4144 if (imhtml->edit.fontsize == MAX_FONT_SIZE) |
4145 return; | |
4146 | |
8677 | 4147 if (!imhtml->edit.fontsize) |
4148 imhtml->edit.fontsize = 4; | |
4149 else | |
4150 imhtml->edit.fontsize++; | |
4151 | |
4152 if (imhtml->wbfo) { | |
4153 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
4154 remove_font_size(imhtml, &start, &end, TRUE); | |
4155 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4156 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4157 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4158 remove_font_size(imhtml, &start, &end, FALSE); |
4159 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
4160 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); | |
8061 | 4161 } |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4162 } |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4163 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4164 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4165 { |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4166 GObject *object; |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4167 |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4168 g_return_if_fail(imhtml != NULL); |
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4169 |
9025 | 4170 object = g_object_ref(G_OBJECT(imhtml)); |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4171 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_GROW); |
9025 | 4172 g_object_unref(object); |
8061 | 4173 } |
4174 | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4175 #define gtk_imhtml_toggle_str_tag(imhtml, color, edit_field, remove_func, find_func, button) { \ |
10776 | 4176 GObject *object; \ |
4177 GtkTextIter start, end; \ | |
4178 \ | |
4179 g_free(edit_field); \ | |
4180 edit_field = NULL; \ | |
4181 \ | |
4182 if (color && strcmp(color, "") != 0) { \ | |
4183 edit_field = g_strdup(color); \ | |
4184 \ | |
4185 if (imhtml->wbfo) { \ | |
4186 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ | |
4187 remove_func(imhtml, &start, &end, TRUE); \ | |
4188 gtk_text_buffer_apply_tag(imhtml->text_buffer, \ | |
4189 find_func(imhtml, edit_field), &start, &end); \ | |
4190 } else { \ | |
4191 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, \ | |
4192 gtk_text_buffer_get_mark(imhtml->text_buffer, "insert")); \ | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4193 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { \ |
10776 | 4194 remove_func(imhtml, &start, &end, FALSE); \ |
4195 gtk_text_buffer_apply_tag(imhtml->text_buffer, \ | |
4196 find_func(imhtml, \ | |
4197 edit_field), \ | |
4198 &start, &end); \ | |
4199 } \ | |
4200 } \ | |
4201 } else { \ | |
4202 if (imhtml->wbfo) { \ | |
4203 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); \ | |
4204 remove_func(imhtml, &start, &end, TRUE); \ | |
4205 } \ | |
4206 } \ | |
4207 \ | |
4208 object = g_object_ref(G_OBJECT(imhtml)); \ | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4209 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, button); \ |
10776 | 4210 g_object_unref(object); \ |
4211 \ | |
4212 return edit_field != NULL; \ | |
4213 } | |
4214 | |
8061 | 4215 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) |
4216 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4217 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.forecolor, remove_font_forecolor, find_font_forecolor_tag, GTK_IMHTML_FORECOLOR); |
8061 | 4218 } |
4219 | |
4220 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
4221 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4222 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.backcolor, remove_font_backcolor, find_font_backcolor_tag, GTK_IMHTML_BACKCOLOR); |
10776 | 4223 } |
4224 | |
4225 gboolean gtk_imhtml_toggle_background(GtkIMHtml *imhtml, const char *color) | |
4226 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4227 gtk_imhtml_toggle_str_tag(imhtml, color, imhtml->edit.background, remove_font_background, find_font_background_tag, GTK_IMHTML_BACKGROUND); |
8061 | 4228 } |
4229 | |
4230 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
4231 { | |
11267
477e5cca8287
[gaim-migrate @ 13449]
Richard Laager <rlaager@wiktel.com>
parents:
11240
diff
changeset
|
4232 gtk_imhtml_toggle_str_tag(imhtml, face, imhtml->edit.fontface, remove_font_face, find_font_face_tag, GTK_IMHTML_FACE); |
8061 | 4233 } |
4234 | |
8677 | 4235 void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) |
8061 | 4236 { |
9025 | 4237 GObject *object; |
8677 | 4238 GtkTextIter start, end; |
4239 GtkTextTag *linktag; | |
4240 static guint linkno = 0; | |
4241 gchar str[48]; | |
9007 | 4242 GdkColor *color = NULL; |
8677 | 4243 |
4244 imhtml->edit.link = NULL; | |
4245 | |
4246 if (url) { | |
4247 g_snprintf(str, sizeof(str), "LINK %d", linkno++); | |
4248 str[47] = '\0'; | |
4249 | |
9007 | 4250 gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &color, NULL); |
9008 | 4251 if (color) { |
9007 | 4252 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground-gdk", color, "underline", PANGO_UNDERLINE_SINGLE, NULL); |
9008 | 4253 gdk_color_free(color); |
4254 } else { | |
9007 | 4255 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); |
9008 | 4256 } |
8677 | 4257 g_object_set_data_full(G_OBJECT(linktag), "link_url", g_strdup(url), g_free); |
4258 g_signal_connect(G_OBJECT(linktag), "event", G_CALLBACK(tag_event), NULL); | |
4259 | |
11276
17ebda61c6ce
[gaim-migrate @ 13463]
Richard Laager <rlaager@wiktel.com>
parents:
11275
diff
changeset
|
4260 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
8677 | 4261 remove_font_link(imhtml, &start, &end, FALSE); |
4262 gtk_text_buffer_apply_tag(imhtml->text_buffer, linktag, &start, &end); | |
4263 } | |
4264 } | |
9025 | 4265 |
4266 object = g_object_ref(G_OBJECT(imhtml)); | |
4267 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_LINK); | |
4268 g_object_unref(object); | |
8677 | 4269 } |
4270 | |
4271 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, GtkTextMark *mark, const char *url, const char *text) | |
4272 { | |
8061 | 4273 GtkTextIter iter; |
8677 | 4274 |
9599 | 4275 if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) |
4276 gtk_text_buffer_delete_selection(imhtml->text_buffer, TRUE, TRUE); | |
4277 | |
8677 | 4278 gtk_imhtml_toggle_link(imhtml, url); |
8061 | 4279 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
8677 | 4280 gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); |
4281 gtk_imhtml_toggle_link(imhtml, NULL); | |
8061 | 4282 } |
4283 | |
4284 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
4285 { | |
8677 | 4286 GtkTextMark *mark; |
8061 | 4287 GtkTextIter iter; |
8677 | 4288 |
4289 mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
4290 | |
4291 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
4292 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); | |
4293 } | |
4294 | |
4295 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) | |
4296 { | |
8061 | 4297 GdkPixbuf *pixbuf = NULL; |
4298 GdkPixbufAnimation *annipixbuf = NULL; | |
4299 GtkWidget *icon = NULL; | |
4300 GtkTextChildAnchor *anchor; | |
8505 | 4301 char *unescaped = gaim_unescape_html(smiley); |
8061 | 4302 |
10526 | 4303 if (imhtml->format_functions & GTK_IMHTML_SMILEY) { |
10522 | 4304 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); |
10526 | 4305 if (annipixbuf) { |
4306 if (gdk_pixbuf_animation_is_static_image(annipixbuf)) { | |
10522 | 4307 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); |
10526 | 4308 if (pixbuf) |
10522 | 4309 icon = gtk_image_new_from_pixbuf(pixbuf); |
4310 } else { | |
4311 icon = gtk_image_new_from_animation(annipixbuf); | |
4312 } | |
8061 | 4313 } |
4314 } | |
10526 | 4315 #if 0 |
4316 else { | |
4317 GtkIMHtmlSmiley *imhtml_smiley; | |
4318 | |
4319 if (imhtml_smiley->loader) { ; } | |
4320 icon = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU); | |
4321 imhtml_smiley = gtk_get_imhtml_smiley(imhtml, sml, unescaped); | |
4322 if (!imhtml_smiley) { | |
4323 gaim_debug_info("gtkimhtml", "geezz couldnt find smiley struct\n"); | |
4324 } | |
4325 imhtml_smiley->orphan = g_slist_append(imhtml_smiley->orphan, icon); | |
4326 } | |
4327 #endif | |
8061 | 4328 |
4329 if (icon) { | |
8890 | 4330 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
4331 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); | |
4332 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); | |
4333 | |
8061 | 4334 gtk_widget_show(icon); |
4335 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | |
8890 | 4336 } else { |
4337 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); | |
8061 | 4338 } |
8890 | 4339 |
4340 g_free(unescaped); | |
8061 | 4341 } |
4342 | |
8962 | 4343 void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter) |
4344 { | |
4345 GdkPixbuf *pixbuf = NULL; | |
4346 const char *filename = NULL; | |
4347 gpointer image; | |
4348 GdkRectangle rect; | |
4349 GtkIMHtmlScalable *scalable = NULL; | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4350 struct scalable_data *sd; |
8962 | 4351 int minus; |
4352 | |
4353 if (!imhtml->funcs || !imhtml->funcs->image_get || | |
4354 !imhtml->funcs->image_get_size || !imhtml->funcs->image_get_data || | |
4355 !imhtml->funcs->image_get_filename || !imhtml->funcs->image_ref || | |
4356 !imhtml->funcs->image_unref) | |
4357 return; | |
4358 | |
4359 image = imhtml->funcs->image_get(id); | |
4360 | |
4361 if (image) { | |
4362 gpointer data; | |
4363 size_t len; | |
4364 | |
4365 data = imhtml->funcs->image_get_data(image); | |
4366 len = imhtml->funcs->image_get_size(image); | |
4367 | |
4368 if (data && len) { | |
4369 GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); | |
4370 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
4371 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); | |
9337 | 4372 if (pixbuf) |
4373 g_object_ref(G_OBJECT(pixbuf)); | |
8962 | 4374 gdk_pixbuf_loader_close(loader, NULL); |
9337 | 4375 g_object_unref(G_OBJECT(loader)); |
8962 | 4376 } |
4377 | |
4378 } | |
4379 | |
4380 if (pixbuf) { | |
11299
421007f39e53
[gaim-migrate @ 13499]
Richard Laager <rlaager@wiktel.com>
parents:
11276
diff
changeset
|
4381 struct im_image_data *t = g_new(struct im_image_data, 1); |
8962 | 4382 filename = imhtml->funcs->image_get_filename(image); |
4383 imhtml->funcs->image_ref(id); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4384 t->id = id; |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4385 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
|
4386 imhtml->im_images = g_slist_prepend(imhtml->im_images, t); |
8962 | 4387 } else { |
4388 pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE, | |
4389 GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image"); | |
4390 } | |
4391 | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4392 sd = g_new(struct scalable_data, 1); |
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4393 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
|
4394 sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); |
8962 | 4395 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
4396 scalable->add_to(scalable, imhtml, iter); | |
4397 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + | |
4398 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
4399 scalable->scale(scalable, rect.width - minus, rect.height); | |
11224
409d6a11da51
[gaim-migrate @ 13360]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11143
diff
changeset
|
4400 imhtml->scalables = g_list_append(imhtml->scalables, sd); |
8962 | 4401 |
4402 g_object_unref(G_OBJECT(pixbuf)); | |
4403 } | |
4404 | |
8677 | 4405 static const gchar *tag_to_html_start(GtkTextTag *tag) |
8061 | 4406 { |
8677 | 4407 const gchar *name; |
4408 static gchar buf[1024]; | |
4409 | |
4410 name = tag->name; | |
4411 g_return_val_if_fail(name != NULL, ""); | |
4412 | |
4413 if (strcmp(name, "BOLD") == 0) { | |
4414 return "<b>"; | |
4415 } else if (strcmp(name, "ITALICS") == 0) { | |
4416 return "<i>"; | |
4417 } else if (strcmp(name, "UNDERLINE") == 0) { | |
4418 return "<u>"; | |
9924 | 4419 } else if (strcmp(name, "STRIKE") == 0) { |
4420 return "<s>"; | |
8677 | 4421 } else if (strncmp(name, "LINK ", 5) == 0) { |
4422 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); | |
4423 if (tmp) { | |
4424 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); | |
4425 buf[sizeof(buf)-1] = '\0'; | |
4426 return buf; | |
4427 } else { | |
4428 return ""; | |
4429 } | |
4430 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
4431 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); | |
4432 return buf; | |
4433 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
4434 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); | |
4435 return buf; | |
10776 | 4436 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { |
4437 g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]); | |
4438 return buf; | |
8677 | 4439 } else if (strncmp(name, "FONT FACE ", 10) == 0) { |
4440 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); | |
4441 return buf; | |
4442 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
4443 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); | |
4444 return buf; | |
4445 } else { | |
4446 return ""; | |
4447 } | |
8061 | 4448 } |
4449 | |
8677 | 4450 static const gchar *tag_to_html_end(GtkTextTag *tag) |
8061 | 4451 { |
8677 | 4452 const gchar *name; |
4453 | |
4454 name = tag->name; | |
4455 g_return_val_if_fail(name != NULL, ""); | |
4456 | |
4457 if (strcmp(name, "BOLD") == 0) { | |
4458 return "</b>"; | |
4459 } else if (strcmp(name, "ITALICS") == 0) { | |
4460 return "</i>"; | |
4461 } else if (strcmp(name, "UNDERLINE") == 0) { | |
4462 return "</u>"; | |
9924 | 4463 } else if (strcmp(name, "STRIKE") == 0) { |
4464 return "</s>"; | |
8677 | 4465 } else if (strncmp(name, "LINK ", 5) == 0) { |
4466 return "</a>"; | |
4467 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
4468 return "</font>"; | |
4469 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
4470 return "</font>"; | |
10776 | 4471 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { |
4472 return "</body>"; | |
8677 | 4473 } else if (strncmp(name, "FONT FACE ", 10) == 0) { |
4474 return "</font>"; | |
4475 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
4476 return "</font>"; | |
4477 } else { | |
4478 return ""; | |
4479 } | |
4480 } | |
4481 | |
4482 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) | |
4483 { | |
4484 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && | |
4485 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || | |
4486 gtk_text_iter_is_end(niter)); | |
8061 | 4487 } |
4488 | |
4489 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | |
4490 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | |
8677 | 4491 * check for tags that are toggled on, insert their html form, and push them on the queue. Then insert |
4492 * 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
|
4493 * Finally, replace <, >, &, and " with their HTML equivalent. |
8677 | 4494 */ |
8061 | 4495 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
4496 { | |
4497 gunichar c; | |
8677 | 4498 GtkTextIter iter, nextiter; |
8061 | 4499 GString *str = g_string_new(""); |
8677 | 4500 GSList *tags, *sl; |
4501 GQueue *q, *r; | |
4502 GtkTextTag *tag; | |
4503 | |
4504 q = g_queue_new(); | |
4505 r = g_queue_new(); | |
4506 | |
8061 | 4507 |
4508 gtk_text_iter_order(start, end); | |
8677 | 4509 nextiter = iter = *start; |
4510 gtk_text_iter_forward_char(&nextiter); | |
4511 | |
9071 | 4512 /* First add the tags that are already in progress (we don't care about non-printing tags)*/ |
8677 | 4513 tags = gtk_text_iter_get_tags(start); |
4514 | |
4515 for (sl = tags; sl; sl = sl->next) { | |
4516 tag = sl->data; | |
4517 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { | |
9071 | 4518 if (strlen(tag_to_html_end(tag)) > 0) |
4519 g_string_append(str, tag_to_html_start(tag)); | |
8677 | 4520 g_queue_push_tail(q, tag); |
8061 | 4521 } |
4522 } | |
8677 | 4523 g_slist_free(tags); |
8061 | 4524 |
4525 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
8677 | 4526 |
4527 tags = gtk_text_iter_get_tags(&iter); | |
4528 | |
4529 for (sl = tags; sl; sl = sl->next) { | |
4530 tag = sl->data; | |
4531 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { | |
9071 | 4532 if (strlen(tag_to_html_end(tag)) > 0) |
4533 g_string_append(str, tag_to_html_start(tag)); | |
8677 | 4534 g_queue_push_tail(q, tag); |
4535 } | |
4536 } | |
4537 | |
4538 | |
8061 | 4539 if (c == 0xFFFC) { |
4540 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | |
9071 | 4541 if (anchor) { |
4542 char *text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext"); | |
4543 if (text) | |
4544 str = g_string_append(str, text); | |
4545 } | |
8677 | 4546 } else if (c == '<') { |
4547 str = g_string_append(str, "<"); | |
4548 } else if (c == '>') { | |
4549 str = g_string_append(str, ">"); | |
4550 } else if (c == '&') { | |
4551 str = g_string_append(str, "&"); | |
4552 } else if (c == '"') { | |
4553 str = g_string_append(str, """); | |
4554 } else if (c == '\n') { | |
4555 str = g_string_append(str, "<br>"); | |
8061 | 4556 } else { |
8677 | 4557 str = g_string_append_unichar(str, c); |
4558 } | |
4559 | |
4560 tags = g_slist_reverse(tags); | |
4561 for (sl = tags; sl; sl = sl->next) { | |
4562 tag = sl->data; | |
9071 | 4563 /** don't worry about non-printing tags ending */ |
4564 if (tag_ends_here(tag, &iter, &nextiter) && strlen(tag_to_html_end(tag)) > 0) { | |
8677 | 4565 |
4566 GtkTextTag *tmp; | |
4567 | |
4568 while ((tmp = g_queue_pop_tail(q)) != tag) { | |
4569 if (tmp == NULL) | |
4570 break; | |
4571 | |
9071 | 4572 if (!tag_ends_here(tmp, &iter, &nextiter) && strlen(tag_to_html_end(tmp)) > 0) |
8677 | 4573 g_queue_push_tail(r, tmp); |
4574 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); | |
4575 } | |
4576 | |
4577 if (tmp == NULL) | |
4578 gaim_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); | |
4579 else | |
4580 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
4581 | |
4582 while ((tmp = g_queue_pop_head(r))) { | |
4583 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); | |
4584 g_queue_push_tail(q, tmp); | |
8061 | 4585 } |
4586 } | |
4587 } | |
8677 | 4588 |
4589 g_slist_free(tags); | |
8061 | 4590 gtk_text_iter_forward_char(&iter); |
8677 | 4591 gtk_text_iter_forward_char(&nextiter); |
8061 | 4592 } |
8677 | 4593 |
4594 while ((tag = g_queue_pop_tail(q))) | |
4595 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
4596 | |
4597 g_queue_free(q); | |
4598 g_queue_free(r); | |
8061 | 4599 return g_string_free(str, FALSE); |
4600 } | |
4601 | |
8698 | 4602 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter) |
8061 | 4603 { |
4604 if (imhtml->edit.bold) | |
4605 gtk_imhtml_toggle_bold(imhtml); | |
4606 | |
4607 if (imhtml->edit.italic) | |
4608 gtk_imhtml_toggle_italic(imhtml); | |
4609 | |
4610 if (imhtml->edit.underline) | |
4611 gtk_imhtml_toggle_underline(imhtml); | |
4612 | |
9924 | 4613 if (imhtml->edit.strike) |
4614 gtk_imhtml_toggle_strike(imhtml); | |
4615 | |
8061 | 4616 if (imhtml->edit.forecolor) |
4617 gtk_imhtml_toggle_forecolor(imhtml, NULL); | |
4618 | |
4619 if (imhtml->edit.backcolor) | |
4620 gtk_imhtml_toggle_backcolor(imhtml, NULL); | |
4621 | |
4622 if (imhtml->edit.fontface) | |
4623 gtk_imhtml_toggle_fontface(imhtml, NULL); | |
4624 | |
8677 | 4625 imhtml->edit.fontsize = 0; |
4626 | |
8719 | 4627 if (imhtml->edit.link) |
4628 gtk_imhtml_toggle_link(imhtml, NULL); | |
4629 | |
8698 | 4630 gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter); |
8061 | 4631 |
4632 } | |
4633 | |
4634 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
4635 { | |
4636 GtkTextIter start, end; | |
4637 | |
4638 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
4639 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
4640 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
4641 } | |
4642 | |
8677 | 4643 char **gtk_imhtml_get_markup_lines(GtkIMHtml *imhtml) |
4644 { | |
4645 int i, j, lines; | |
4646 GtkTextIter start, end; | |
4647 char **ret; | |
4648 | |
4649 lines = gtk_text_buffer_get_line_count(imhtml->text_buffer); | |
4650 ret = g_new0(char *, lines + 1); | |
4651 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
4652 end = start; | |
4653 gtk_text_iter_forward_to_line_end(&end); | |
4654 | |
4655 for (i = 0, j = 0; i < lines; i++) { | |
9612 | 4656 if (gtk_text_iter_get_char(&start) != '\n') { |
4657 ret[j] = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
4658 if (ret[j] != NULL) | |
4659 j++; | |
4660 } | |
4661 | |
8677 | 4662 gtk_text_iter_forward_line(&start); |
4663 end = start; | |
4664 gtk_text_iter_forward_to_line_end(&end); | |
4665 } | |
4666 | |
4667 return ret; | |
4668 } | |
4669 | |
4670 char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop) | |
8061 | 4671 { |
8519 | 4672 GString *str = g_string_new(""); |
4673 GtkTextIter iter, end; | |
4674 gunichar c; | |
4675 | |
8677 | 4676 if (start == NULL) |
4677 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | |
4678 else | |
4679 iter = *start; | |
4680 | |
4681 if (stop == NULL) | |
4682 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
4683 else | |
4684 end = *stop; | |
4685 | |
4686 gtk_text_iter_order(&iter, &end); | |
8519 | 4687 |
4688 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { | |
4689 if (c == 0xFFFC) { | |
8677 | 4690 GtkTextChildAnchor* anchor; |
4691 char *text = NULL; | |
4692 | |
4693 anchor = gtk_text_iter_get_child_anchor(&iter); | |
4694 if (anchor) | |
8698 | 4695 text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_plaintext"); |
8677 | 4696 if (text) |
4697 str = g_string_append(str, text); | |
8519 | 4698 } else { |
4699 g_string_append_unichar(str, c); | |
4700 } | |
4701 gtk_text_iter_forward_char(&iter); | |
4702 } | |
4703 | |
4704 return g_string_free(str, FALSE); | |
8061 | 4705 } |
8962 | 4706 |
4707 void gtk_imhtml_set_funcs(GtkIMHtml *imhtml, GtkIMHtmlFuncs *f) | |
4708 { | |
4709 g_return_if_fail(imhtml != NULL); | |
4710 imhtml->funcs = f; | |
4711 } |