]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-webkit-utils.c
log-window: escape the body of the message
[empathy.git] / libempathy-gtk / empathy-webkit-utils.c
1 /*
2  * Copyright (C) 2008-2009 Collabora Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors: Xavier Claessens <xclaesse@gmail.com>
19  */
20
21 #include "config.h"
22
23 #include <glib/gi18n-lib.h>
24
25 #include "empathy-webkit-utils.h"
26 #include "empathy-smiley-manager.h"
27 #include "empathy-ui-utils.h"
28 #include "empathy-theme-adium.h"
29
30 #define BORING_DPI_DEFAULT 96
31
32 static void
33 empathy_webkit_match_newline (const gchar *text,
34     gssize len,
35     EmpathyStringReplace replace_func,
36     EmpathyStringParser *sub_parsers,
37     gpointer user_data)
38 {
39   GString *string = user_data;
40   gint i;
41   gint prev = 0;
42
43   if (len < 0)
44     len = G_MAXSSIZE;
45
46   /* Replace \n by <br/> */
47   for (i = 0; i < len && text[i] != '\0'; i++)
48     {
49       if (text[i] == '\n')
50         {
51           empathy_string_parser_substr (text + prev, i - prev,
52               sub_parsers, user_data);
53           g_string_append (string, "<br/>");
54           prev = i + 1;
55         }
56     }
57
58   empathy_string_parser_substr (text + prev, i - prev,
59               sub_parsers, user_data);
60 }
61
62 static void
63 empathy_webkit_replace_smiley (const gchar *text,
64     gssize len,
65     gpointer match_data,
66     gpointer user_data)
67 {
68   EmpathySmileyHit *hit = match_data;
69   GString *string = user_data;
70
71   /* Replace smiley by a <img/> tag */
72   g_string_append_printf (string,
73       "<img src=\"%s\" alt=\"%.*s\" title=\"%.*s\"/>",
74       hit->path, (int)len, text, (int)len, text);
75 }
76
77 static EmpathyStringParser string_parsers[] = {
78   { empathy_string_match_link, empathy_string_replace_link },
79   { empathy_webkit_match_newline, NULL },
80   { empathy_string_match_all, empathy_string_replace_escaped },
81   { NULL, NULL}
82 };
83
84 static EmpathyStringParser string_parsers_with_smiley[] = {
85   { empathy_string_match_link, empathy_string_replace_link },
86   { empathy_string_match_smiley, empathy_webkit_replace_smiley },
87   { empathy_webkit_match_newline, NULL },
88   { empathy_string_match_all, empathy_string_replace_escaped },
89   { NULL, NULL }
90 };
91
92 EmpathyStringParser *
93 empathy_webkit_get_string_parser (gboolean smileys)
94 {
95   if (smileys)
96     return string_parsers_with_smiley;
97   else
98     return string_parsers;
99 }
100
101 static gboolean
102 webkit_get_font_family (GValue *value,
103     GVariant *variant,
104     gpointer user_data)
105 {
106   PangoFontDescription *font = pango_font_description_from_string (
107       g_variant_get_string (variant, NULL));
108
109   if (font == NULL)
110     return FALSE;
111
112   g_value_set_string (value, pango_font_description_get_family (font));
113   pango_font_description_free (font);
114
115   return TRUE;
116 }
117
118 static gboolean
119 webkit_get_font_size (GValue *value,
120     GVariant *variant,
121     gpointer user_data)
122 {
123   PangoFontDescription *font = pango_font_description_from_string (
124       g_variant_get_string (variant, NULL));
125   int size;
126
127   if (font == NULL)
128     return FALSE;
129
130   size = pango_font_description_get_size (font) / PANGO_SCALE;
131
132   if (pango_font_description_get_size_is_absolute (font))
133     {
134       GdkScreen *screen = gdk_screen_get_default ();
135       double dpi;
136
137       if (screen != NULL)
138         dpi = gdk_screen_get_resolution (screen);
139       else
140         dpi = BORING_DPI_DEFAULT;
141
142       size = (gint) (size / (dpi / 72));
143     }
144
145   g_value_set_int (value, size);
146   pango_font_description_free (font);
147
148   return TRUE;
149 }
150
151 void
152 empathy_webkit_bind_font_setting (WebKitWebView *webview,
153     GSettings *gsettings,
154     const char *key)
155 {
156   WebKitWebSettings *settings = webkit_web_view_get_settings (webview);
157
158   g_settings_bind_with_mapping (gsettings, key,
159       settings, "default-font-family",
160       G_SETTINGS_BIND_GET,
161       webkit_get_font_family,
162       NULL,
163       NULL, NULL);
164   g_settings_bind_with_mapping (gsettings, key,
165       settings, "default-font-size",
166       G_SETTINGS_BIND_GET,
167       webkit_get_font_size,
168       NULL,
169       NULL, NULL);
170 }
171
172 static void
173 empathy_webkit_copy_address_cb (GtkMenuItem *menuitem,
174     gpointer     user_data)
175 {
176   WebKitHitTestResult   *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
177   gchar                 *uri;
178   GtkClipboard          *clipboard;
179
180   g_object_get (G_OBJECT (hit_test_result),
181       "link-uri", &uri,
182       NULL);
183
184   clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
185   gtk_clipboard_set_text (clipboard, uri, -1);
186
187   clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
188   gtk_clipboard_set_text (clipboard, uri, -1);
189
190   g_free (uri);
191 }
192
193 static void
194 empathy_webkit_open_address_cb (GtkMenuItem *menuitem,
195     gpointer     user_data)
196 {
197   WebKitHitTestResult   *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
198   gchar                 *uri;
199
200   g_object_get (G_OBJECT (hit_test_result),
201       "link-uri", &uri,
202       NULL);
203
204   empathy_url_show (GTK_WIDGET (menuitem), uri);
205
206   g_free (uri);
207 }
208
209 static void
210 empathy_webkit_context_menu_selection_done_cb (GtkMenuShell *menu,
211     gpointer user_data)
212 {
213   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
214
215   g_object_unref (hit_test_result);
216 }
217
218 void
219 empathy_webkit_context_menu_for_event (WebKitWebView *view,
220     GdkEventButton *event,
221     EmpathyWebKitMenuFlags flags)
222 {
223   WebKitHitTestResult        *hit_test_result;
224   WebKitHitTestResultContext  context;
225   GtkWidget                  *menu;
226   GtkWidget                  *item;
227
228   hit_test_result = webkit_web_view_get_hit_test_result (view, event);
229   g_object_get (G_OBJECT (hit_test_result),
230       "context", &context,
231       NULL);
232
233   /* The menu */
234   menu = empathy_context_menu_new (GTK_WIDGET (view));
235
236   /* Select all item */
237   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
238   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
239
240   g_signal_connect_swapped (item, "activate",
241       G_CALLBACK (webkit_web_view_select_all),
242       view);
243
244   /* Copy menu item */
245   if (webkit_web_view_can_copy_clipboard (view))
246     {
247       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
248       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
249
250       g_signal_connect_swapped (item, "activate",
251           G_CALLBACK (webkit_web_view_copy_clipboard),
252           view);
253     }
254
255   /* Clear menu item */
256   if (flags & EMPATHY_WEBKIT_MENU_CLEAR)
257     {
258       item = gtk_separator_menu_item_new ();
259       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
260
261       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
262       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
263
264       g_signal_connect_swapped (item, "activate",
265           G_CALLBACK (empathy_theme_adium_clear),
266           view);
267     }
268
269   /* We will only add the following menu items if we are
270    * right-clicking a link */
271   if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
272     {
273       /* Separator */
274       item = gtk_separator_menu_item_new ();
275       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
276
277       /* Copy Link Address menu item */
278       item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
279       g_signal_connect (item, "activate",
280           G_CALLBACK (empathy_webkit_copy_address_cb),
281           hit_test_result);
282       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
283
284       /* Open Link menu item */
285       item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
286       g_signal_connect (item, "activate",
287           G_CALLBACK (empathy_webkit_open_address_cb),
288           hit_test_result);
289       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
290     }
291
292   g_signal_connect (GTK_MENU_SHELL (menu), "selection-done",
293       G_CALLBACK (empathy_webkit_context_menu_selection_done_cb),
294       hit_test_result);
295
296   /* Display the menu */
297   gtk_widget_show_all (menu);
298   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
299       event->button, event->time);
300 }
301