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