Fix error creation and warning
[claws.git] / src / plugins / fancy / fancy_viewer.c
blobb328024a20245a256cc7fabdafe3caa0f6175492
1 /*
2 * Claws Mail -- A GTK based, lightweight, and fast e-mail client
3 * == Fancy Plugin ==
4 * Copyright(C) 1999-2023 the Claws Mail Team
5 * This file Copyright (C) 2009-2014 Salvatore De Paolis
6 * <iwkse@claws-mail.org> and the Claws Mail Team
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #include "claws-features.h"
26 #endif
28 #include "stock_pixmap.h"
30 #include <fancy_viewer.h>
31 #include <fancy_prefs.h>
32 #include <alertpanel.h>
33 #include <file-utils.h>
34 #include <utils.h>
36 #include <printing.h>
38 static void load_changed_cb(WebKitWebView *view,
39 WebKitLoadEvent event,
40 gpointer user_data);
41 static void mouse_target_changed_cb (WebKitWebView *view,
42 WebKitHitTestResult *result,
43 guint modifiers,
44 gpointer user_data);
47 static void
48 load_progress_cb(WebKitWebView *view, GParamSpec *param, FancyViewer *viewer);
50 static MimeViewerFactory fancy_viewer_factory;
53 static gboolean
54 fancy_text_search(MimeViewer *_viewer, gboolean backward, const gchar *str,
55 gboolean case_sens);
58 static void
59 viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer);
61 static gint keypress_events_cb (GtkWidget *widget, GdkEventKey *event,
62 FancyViewer *viewer);
63 static void zoom_in_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
64 static void zoom_out_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
65 static gboolean fancy_prefs_cb(GtkWidget *widget, GdkEventButton *ev, FancyViewer *viewer);
66 static void zoom_100_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
67 static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer);
68 static void fancy_create_popup_prefs_menu(FancyViewer *viewer);
69 static void fancy_show_notice(FancyViewer *viewer, const gchar *message);
70 static size_t download_file_curl_write_cb(void *buffer, size_t size,
71 size_t nmemb, void *data);
72 static void *download_file_curl (void *data);
73 static void download_file_cb(GtkWidget *widget, FancyViewer *viewer);
74 static gboolean fancy_set_contents(FancyViewer *viewer, gboolean use_defaults);
76 /*------*/
77 static GtkWidget *fancy_get_widget(MimeViewer *_viewer)
79 FancyViewer *viewer = (FancyViewer *) _viewer;
80 debug_print("fancy_get_widget: %p\n", viewer->vbox);
82 return GTK_WIDGET(viewer->vbox);
85 static void fancy_apply_prefs(FancyViewer *viewer)
87 g_object_set(viewer->settings,
88 "auto-load-images", viewer->override_prefs_images,
89 "enable-javascript", viewer->override_prefs_scripts,
90 "enable-plugins", viewer->override_prefs_plugins,
91 "enable-java", viewer->override_prefs_java,
92 #ifdef G_OS_WIN32
93 "default-font-family", "Arial",
94 "cursive-font-family", "Comic Sans MS",
95 "fantasy-font-family", "Comic Sans MS",
96 "monospace-font-family", "Courier New",
97 "sans-serif-font-family", "Arial",
98 "serif-font-family", "Times New Roman",
99 #endif
100 NULL);
101 if (fancy_prefs.stylesheet == NULL || strlen(fancy_prefs.stylesheet) == 0) {
102 gchar **msg_font_params = g_strsplit(prefs_common_get_prefs()->textfont, " ", 0);
103 guint params_len = g_strv_length(msg_font_params);
105 if (params_len > 0) {
106 gint msg_font_size = g_ascii_strtoll(msg_font_params[params_len - 1], NULL, 10);
107 g_object_set(viewer->settings, "default-font-size",
108 webkit_settings_font_size_to_pixels(msg_font_size), NULL);
110 g_strfreev(msg_font_params);
112 webkit_web_view_set_settings(viewer->view, viewer->settings);
113 webkit_web_context_set_cache_model(webkit_web_context_get_default(), WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
114 webkit_web_view_send_message_to_page(viewer->view,
115 webkit_user_message_new("LoadRemoteContent",
116 g_variant_new_boolean(viewer->override_prefs_remote_content)),
117 NULL,
118 NULL,
119 NULL);
121 if (viewer->override_stylesheet) {
122 /* copied from vimb */
123 gchar *stylesheet;
125 if (g_file_get_contents(viewer->override_stylesheet, &stylesheet, NULL, NULL)) {
126 WebKitUserContentManager *ucm;
127 WebKitUserStyleSheet *style;
129 ucm = webkit_web_view_get_user_content_manager(viewer->view);
130 style = webkit_user_style_sheet_new(
131 stylesheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
132 WEBKIT_USER_STYLE_LEVEL_USER, NULL, NULL);
134 webkit_user_content_manager_remove_all_style_sheets(ucm);
135 webkit_user_content_manager_add_style_sheet(ucm, style);
136 webkit_user_style_sheet_unref(style);
137 g_free(stylesheet);
138 } else {
139 debug_print("Could not read style file: %s\n", viewer->override_stylesheet);
144 static void fancy_auto_load_images_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
145 viewer->override_prefs_images = gtk_check_menu_item_get_active(item);
146 fancy_apply_prefs(viewer);
147 fancy_set_contents(viewer, FALSE);
150 static void fancy_enable_remote_content_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
151 viewer->override_prefs_remote_content = gtk_check_menu_item_get_active(item);
152 fancy_apply_prefs(viewer);
153 fancy_set_contents(viewer, FALSE);
156 static void fancy_enable_scripts_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
157 viewer->override_prefs_scripts = gtk_check_menu_item_get_active(item);
158 fancy_apply_prefs(viewer);
159 fancy_set_contents(viewer, FALSE);
162 static void fancy_enable_plugins_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
163 viewer->override_prefs_plugins = gtk_check_menu_item_get_active(item);
164 fancy_apply_prefs(viewer);
165 fancy_set_contents(viewer, FALSE);
168 static void fancy_enable_java_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
169 viewer->override_prefs_java = gtk_check_menu_item_get_active(item);
170 fancy_apply_prefs(viewer);
171 fancy_set_contents(viewer, FALSE);
174 static void fancy_open_external_activated(GtkCheckMenuItem *item, FancyViewer *viewer) {
175 viewer->override_prefs_external = gtk_check_menu_item_get_active(item);
176 fancy_apply_prefs(viewer);
179 static void fancy_set_defaults(FancyViewer *viewer)
181 viewer->override_prefs_remote_content = fancy_prefs.enable_remote_content;
182 viewer->override_prefs_external = fancy_prefs.open_external;
183 viewer->override_prefs_images = fancy_prefs.enable_images;
184 viewer->override_prefs_scripts = fancy_prefs.enable_scripts;
185 viewer->override_prefs_plugins = fancy_prefs.enable_plugins;
186 viewer->override_prefs_java = fancy_prefs.enable_java;
188 gchar *tmp;
190 #ifdef G_OS_WIN32
191 /* Replace backslashes with forward slashes, since we'll be
192 * using this string in an URI. */
193 gchar *tmp2 = g_strdup(fancy_prefs.stylesheet);
194 subst_char(tmp2, '\\', '/');
196 /* Escape string for use in an URI, keeping dir separators
197 * and colon for Windows drive name ("C:") intact. */
198 tmp = g_uri_escape_string(tmp2, "/:", TRUE);
199 g_free(tmp2);
200 #else
201 /* Escape string for use in an URI, keeping dir separators
202 * intact. */
203 tmp = g_uri_escape_string(fancy_prefs.stylesheet, "/", TRUE);
204 #endif
205 viewer->override_stylesheet = g_strdup(tmp);
206 g_free(tmp);
207 debug_print("Using '%s' as stylesheet\n",
208 viewer->override_stylesheet);
210 g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_images),
211 fancy_auto_load_images_activated, viewer);
212 g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_remote_content),
213 fancy_enable_remote_content_activated, viewer);
214 g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_scripts),
215 fancy_enable_scripts_activated, viewer);
216 g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_plugins),
217 fancy_enable_plugins_activated, viewer);
218 g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_java),
219 fancy_enable_java_activated, viewer);
220 g_signal_handlers_block_by_func(G_OBJECT(viewer->open_external),
221 fancy_open_external_activated, viewer);
223 gtk_check_menu_item_set_active(
224 GTK_CHECK_MENU_ITEM(viewer->enable_images),
225 viewer->override_prefs_images);
226 gtk_check_menu_item_set_active(
227 GTK_CHECK_MENU_ITEM(viewer->enable_scripts),
228 viewer->override_prefs_scripts);
229 gtk_check_menu_item_set_active(
230 GTK_CHECK_MENU_ITEM(viewer->enable_plugins),
231 viewer->override_prefs_plugins);
232 gtk_check_menu_item_set_active(
233 GTK_CHECK_MENU_ITEM(viewer->enable_java),
234 viewer->override_prefs_java);
235 gtk_check_menu_item_set_active(
236 GTK_CHECK_MENU_ITEM(viewer->enable_remote_content),
237 viewer->override_prefs_remote_content);
238 gtk_check_menu_item_set_active(
239 GTK_CHECK_MENU_ITEM(viewer->open_external),
240 viewer->override_prefs_external);
242 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_images),
243 fancy_auto_load_images_activated, viewer);
244 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_remote_content),
245 fancy_enable_remote_content_activated, viewer);
246 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_scripts),
247 fancy_enable_scripts_activated, viewer);
248 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_plugins),
249 fancy_enable_plugins_activated, viewer);
250 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_java),
251 fancy_enable_java_activated, viewer);
252 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->open_external),
253 fancy_open_external_activated, viewer);
255 fancy_apply_prefs(viewer);
258 static gboolean fancy_set_contents(FancyViewer *viewer, gboolean use_defaults)
260 MessageView *messageview = ((MimeViewer *)viewer)->mimeview
261 ? ((MimeViewer *)viewer)->mimeview->messageview
262 : NULL;
263 MimeInfo *partinfo = viewer->to_load;
265 if (messageview) {
266 messageview->updating = TRUE;
267 NoticeView *noticeview = messageview->noticeview;
268 noticeview_hide(noticeview);
271 if (viewer->filename != NULL) {
272 g_unlink(viewer->filename);
273 g_free(viewer->filename);
274 viewer->filename = NULL;
277 if (partinfo)
278 viewer->filename = procmime_get_tmp_file_name(partinfo);
279 debug_print("filename: %s\n", viewer->filename);
280 if (!viewer->filename) {
281 return FALSE;
283 if (procmime_get_part(viewer->filename, partinfo) < 0) {
284 g_free(viewer->filename);
285 viewer->filename = NULL;
287 else {
288 const gchar *charset = NULL;
289 gchar *contents = NULL;
290 GBytes *content_bytes;
291 gdouble zoom_level;
292 zoom_level = (double) fancy_prefs.zoom_level / 100;
294 if (messageview && messageview->forced_charset)
295 charset = ((MimeViewer *)viewer)->mimeview->messageview->forced_charset;
296 else
297 charset = procmime_mimeinfo_get_parameter(partinfo, "charset");
298 if (!charset)
299 charset = conv_get_locale_charset_str();
300 debug_print("using %s charset\n", charset);
301 g_object_set(viewer->settings, "default-charset", charset, NULL);
303 if (use_defaults) {
304 debug_print("zoom_level: %f\n", zoom_level);
306 webkit_web_view_set_zoom_level(viewer->view, zoom_level);
308 fancy_set_defaults(viewer);
311 contents = file_read_to_str_no_recode(viewer->filename);
312 content_bytes = g_bytes_new(contents, strlen(contents));
313 webkit_web_view_load_bytes(viewer->view,
314 content_bytes,
315 "text/html",
316 charset,
317 NULL);
318 g_free(contents);
319 g_bytes_unref(content_bytes);
321 return FALSE;
324 static gboolean fancy_show_mimepart_real(MimeViewer *_viewer)
326 return fancy_set_contents((FancyViewer *)_viewer, TRUE);
329 static void fancy_show_notice(FancyViewer *viewer, const gchar *message)
331 gtk_label_set_text(GTK_LABEL(viewer->l_link), message);
334 static gboolean fancy_show_mimepart_prepare(MimeViewer *_viewer)
336 FancyViewer *viewer = (FancyViewer *) _viewer;
338 g_timeout_add(5, (GSourceFunc)fancy_show_mimepart_real, viewer);
339 return FALSE;
342 static void fancy_show_mimepart(MimeViewer *_viewer, const gchar *infile,
343 MimeInfo *partinfo)
345 FancyViewer *viewer = (FancyViewer *) _viewer;
346 viewer->to_load = partinfo;
347 viewer->loading = TRUE;
348 g_timeout_add(5, (GSourceFunc)fancy_show_mimepart_prepare, viewer);
351 static void fancy_print_fail_cb(WebKitPrintOperation *print_operation,
352 GError *error,
353 gpointer user_data) {
354 /* avoid warning for unused variable
355 FancyViewer *viewer = (FancyViewer *) user_data;
358 debug_print("Error printing message: %s\n",
359 error ? error->message : "no details");
362 static void fancy_print(MimeViewer *_viewer)
364 FancyViewer *viewer = (FancyViewer *) _viewer;
365 WebKitPrintOperationResponse res;
366 WebKitPrintOperation *printoperation;
367 GtkPrintSettings *printsettings;
368 GtkPageSetup *pagesetup;
370 gtk_widget_realize(GTK_WIDGET(viewer->view));
372 while (viewer->loading)
373 claws_do_idle();
375 printoperation = webkit_print_operation_new(viewer->view);
376 g_signal_connect(G_OBJECT(printoperation), "failed",
377 G_CALLBACK(fancy_print_fail_cb), viewer);
379 printsettings = webkit_print_operation_get_print_settings(printoperation);
380 if (!printsettings) {
381 printsettings = printing_get_settings();
382 webkit_print_operation_set_print_settings(printoperation, printsettings);
384 pagesetup = webkit_print_operation_get_page_setup(printoperation);
385 if (!pagesetup) {
386 pagesetup = printing_get_page_setup();
387 webkit_print_operation_set_page_setup(printoperation, pagesetup);
390 MainWindow *mainwin = mainwindow_get_mainwindow();
391 res = webkit_print_operation_run_dialog(
392 printoperation,
393 mainwin ? GTK_WINDOW(mainwin->window):NULL);
395 if (res == WEBKIT_PRINT_OPERATION_RESPONSE_PRINT) {
396 // store settings for next printing session
397 printing_store_settings(
398 webkit_print_operation_get_print_settings(printoperation));
401 g_object_unref(printoperation);
404 /*static gchar *fancy_get_selection (MimeViewer *_viewer)
406 debug_print("fancy_get_selection\n");
407 FancyViewer *viewer = (FancyViewer *) _viewer;
408 viewer->doc = webkit_web_page_get_dom_document(WEBKIT_WEB_VIEW(viewer->view));
409 viewer->window = webkit_dom_document_get_default_view (viewer->doc);
410 viewer->selection = webkit_dom_dom_window_get_selection (viewer->window);
411 if (viewer->selection == NULL)
412 return NULL;
413 viewer->range = webkit_dom_dom_selection_get_range_at(viewer->selection, 0, NULL);
414 if (viewer->range == NULL)
415 return NULL;
416 gchar *sel = webkit_dom_range_get_text (viewer->range);
417 if (!viewer->view || strlen(sel) == 0) {
418 g_free(sel);
419 return NULL;
421 return sel;
424 static void fancy_clear_viewer(MimeViewer *_viewer)
426 FancyViewer *viewer = (FancyViewer *) _viewer;
427 GtkAdjustment *vadj;
428 viewer->cur_link = NULL;
429 fancy_set_defaults(viewer);
431 webkit_web_view_load_uri(viewer->view, "about:blank");
433 debug_print("fancy_clear_viewer\n");
434 fancy_prefs.zoom_level = (int) webkit_web_view_get_zoom_level(viewer->view) * 100;
435 viewer->to_load = NULL;
436 vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
437 gtk_adjustment_set_value(vadj, 0.0);
438 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
441 static void fancy_destroy_viewer(MimeViewer *_viewer)
443 FancyViewer *viewer = (FancyViewer *) _viewer;
444 fancy_prefs.zoom_level = (int) webkit_web_view_get_zoom_level(viewer->view) * 100;
445 debug_print("fancy_destroy_viewer\n");
446 g_free(viewer->filename);
447 g_free(viewer);
450 static gboolean
451 navigation_policy_cb (WebKitWebView *web_view,
452 WebKitPolicyDecision *policy_decision,
453 WebKitPolicyDecisionType policy_decision_type,
454 FancyViewer *viewer)
456 if (policy_decision_type == WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION || policy_decision_type == WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION) {
457 WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(policy_decision);
458 WebKitNavigationAction *navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision);
459 viewer->cur_link = webkit_uri_request_get_uri(webkit_navigation_action_get_request(navigation_action));
461 debug_print("navigation requested to %s\n", viewer->cur_link);
463 if (viewer->cur_link) {
464 if (!strncmp(viewer->cur_link, "mailto:", 7)) {
465 debug_print("Opening message window\n");
466 compose_new(NULL, viewer->cur_link + 7, NULL);
467 webkit_policy_decision_ignore(policy_decision);
468 } else if (!strncmp(viewer->cur_link, "file://", 7) || !strcmp(viewer->cur_link, "about:blank")) {
469 debug_print("local navigation request ACCEPTED\n");
470 webkit_policy_decision_use(policy_decision);
471 } else if (viewer->override_prefs_external && webkit_navigation_action_get_navigation_type(navigation_action) == WEBKIT_NAVIGATION_TYPE_LINK_CLICKED) {
472 debug_print("remote navigation request OPENED\n");
473 open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
474 webkit_policy_decision_ignore(policy_decision);
475 } else if (viewer->override_prefs_remote_content) {
476 debug_print("remote navigation request ACCEPTED\n");
477 webkit_policy_decision_use(policy_decision);
478 } else {
479 debug_print("remote navigation request IGNORED\n");
480 fancy_show_notice(viewer, _("Remote content loading is disabled."));
481 webkit_policy_decision_ignore(policy_decision);
484 return TRUE;
485 } else {
486 return FALSE;
490 static void load_content_cb(WebKitURISchemeRequest *request, gpointer viewer)
492 gchar *image;
493 MimeInfo *partinfo = ((FancyViewer *)viewer)->to_load;
494 gchar *mimetype;
495 GInputStream *stream;
496 GError *error;
498 image = g_strconcat("<", webkit_uri_scheme_request_get_path(request), ">", NULL);
499 while ((partinfo = procmime_mimeinfo_next(partinfo)) != NULL) {
500 if (partinfo->id && !g_ascii_strcasecmp(image, partinfo->id)) {
501 mimetype = procmime_get_content_type_str(partinfo->type, partinfo->subtype);
502 stream = procmime_get_part_as_inputstream(partinfo);
503 webkit_uri_scheme_request_finish(request, stream, partinfo->length,
504 mimetype);
505 g_object_unref(stream);
506 g_free(mimetype);
507 g_free(image);
508 return;
512 error = g_error_new(G_FILE_ERROR, 0, _("Couldn't save the part of multipart message: %s"), image);
513 webkit_uri_scheme_request_finish_error(request, error);
514 g_error_free(error);
515 g_free(image);
518 static void resource_request_starting_cb(WebKitWebView *view,
519 WebKitWebResource *resource,
520 WebKitURIRequest *request,
521 WebKitURIResponse *response,
522 FancyViewer *viewer)
524 const gchar *uri = webkit_uri_request_get_uri(request);
525 gchar *filename;
526 gchar *image;
527 gint err;
528 MimeInfo *partinfo = viewer->to_load;
530 filename = viewer->filename;
531 if ((!g_ascii_strncasecmp(uri, "cid:", 4)) || (!g_ascii_strncasecmp(uri, "mid:", 4))) {
532 image = g_strconcat("<", uri + 4, ">", NULL);
533 while ((partinfo = procmime_mimeinfo_next(partinfo)) != NULL) {
534 if (partinfo->id && !g_ascii_strcasecmp(image, partinfo->id)) {
535 filename = procmime_get_tmp_file_name(partinfo);
536 if (!filename) {
537 g_free(image);
538 return;
540 if ((err = procmime_get_part(filename, partinfo)) < 0)
541 alertpanel_error(_("Couldn't save the part of multipart message: %s"),
542 g_strerror(-err));
543 gchar *file_uri = g_filename_to_uri(filename, NULL, NULL);
544 webkit_uri_request_set_uri(request, file_uri);
545 g_free(file_uri);
546 g_free(filename);
547 break;
550 g_free(image);
553 /* refresh URI that may have changed */
554 uri = webkit_uri_request_get_uri(request);
555 if (!viewer->override_prefs_remote_content
556 && strncmp(uri, "file://", 7) && strncmp(uri, "data:", 5)) {
557 debug_print("Preventing load of %s\n", uri);
558 webkit_uri_request_set_uri(request, "about:blank");
560 else
561 debug_print("Starting request of %"G_GSIZE_FORMAT" %s\n", strlen(uri), uri);
564 /*static gboolean fancy_text_search(MimeViewer *_viewer, gboolean backward,
565 const gchar *str, gboolean case_sens)
567 return webkit_web_view_search_text(((FancyViewer*)_viewer)->view, str,
568 case_sens, !backward, TRUE);
571 static gboolean fancy_prefs_cb(GtkWidget *widget, GdkEventButton *ev, FancyViewer *viewer)
573 if ((ev->button == 1) && (ev->type == GDK_BUTTON_PRESS)) {
574 gtk_menu_popup_at_widget(GTK_MENU(viewer->fancy_prefs_menu),
575 widget, GDK_GRAVITY_CENTER, GDK_GRAVITY_SOUTH_WEST, NULL);
576 return TRUE;
578 return FALSE;
581 static void fancy_create_popup_prefs_menu(FancyViewer *viewer) {
582 GtkWidget *enable_images;
583 GtkWidget *enable_remote_content;
584 GtkWidget *enable_scripts;
585 GtkWidget *enable_plugins;
586 GtkWidget *enable_java;
587 GtkWidget *open_external;
589 enable_images = gtk_check_menu_item_new_with_label(_("Load images"));
591 enable_remote_content = gtk_check_menu_item_new_with_label(_("Enable remote content"));
593 enable_scripts = gtk_check_menu_item_new_with_label(_("Enable Javascript"));
595 enable_plugins = gtk_check_menu_item_new_with_label(_("Enable Plugins"));
597 enable_java = gtk_check_menu_item_new_with_label(_("Enable Java"));
599 open_external = gtk_check_menu_item_new_with_label(_("Open links with external browser"));
601 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_images);
602 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_remote_content);
603 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_scripts);
604 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_plugins);
605 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_java);
606 gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), open_external);
608 gtk_menu_attach_to_widget(GTK_MENU(viewer->fancy_prefs_menu), viewer->ev_fancy_prefs, NULL);
609 gtk_widget_show_all(viewer->fancy_prefs_menu);
611 viewer->enable_images = enable_images;
612 viewer->enable_scripts = enable_scripts;
613 viewer->enable_plugins = enable_plugins;
614 viewer->enable_java = enable_java;
615 viewer->enable_remote_content = enable_remote_content;
616 viewer->open_external = open_external;
618 /* Set sensitivity according to preferences and overrides */
620 g_signal_connect(G_OBJECT(enable_images), "toggled",
621 G_CALLBACK (fancy_auto_load_images_activated), viewer);
622 g_signal_connect(G_OBJECT(enable_remote_content), "toggled",
623 G_CALLBACK (fancy_enable_remote_content_activated), viewer);
624 g_signal_connect(G_OBJECT(enable_scripts), "toggled",
625 G_CALLBACK (fancy_enable_scripts_activated), viewer);
626 g_signal_connect(G_OBJECT(enable_plugins), "toggled",
627 G_CALLBACK (fancy_enable_plugins_activated), viewer);
628 g_signal_connect(G_OBJECT(enable_java), "toggled",
629 G_CALLBACK (fancy_enable_java_activated), viewer);
630 g_signal_connect(G_OBJECT(open_external), "toggled",
631 G_CALLBACK (fancy_open_external_activated), viewer);
633 fancy_apply_prefs(viewer);
636 static gboolean fancy_scroll_page(MimeViewer *_viewer, gboolean up)
638 FancyViewer *viewer = (FancyViewer *)_viewer;
639 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
640 GTK_SCROLLED_WINDOW(viewer->scrollwin));
642 if (viewer->view == NULL)
643 return FALSE;
645 return gtkutils_scroll_page(GTK_WIDGET(viewer->view), vadj, up);
648 static void fancy_scroll_one_line(MimeViewer *_viewer, gboolean up)
650 FancyViewer *viewer = (FancyViewer *)_viewer;
651 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
652 GTK_SCROLLED_WINDOW(viewer->scrollwin));
654 if (viewer->view == NULL)
655 return;
657 gtkutils_scroll_one_line(GTK_WIDGET(viewer->view), vadj, up);
660 static void load_changed_cb(WebKitWebView *view,
661 WebKitLoadEvent event,
662 gpointer user_data)
664 FancyViewer *viewer = (FancyViewer *)user_data;
666 switch (event) {
667 case WEBKIT_LOAD_STARTED:
668 gtk_widget_show(viewer->progress);
669 gtk_widget_show(viewer->ev_stop_loading);
670 break;
672 case WEBKIT_LOAD_FINISHED:
673 viewer->loading = FALSE;
674 gtk_widget_hide(viewer->progress);
675 gtk_widget_hide(viewer->ev_stop_loading);
676 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer->progress),
677 (gdouble) 0.0);
678 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress), "");
679 break;
680 default:
681 break;
685 static void mouse_target_changed_cb(WebKitWebView *view,
686 WebKitHitTestResult *result,
687 guint modifiers,
688 gpointer user_data)
690 FancyViewer *viewer = (FancyViewer *)user_data;
692 cm_return_if_fail(result != NULL);
694 /* Display the link in the bottom statusbar, or erase it
695 * if the cursor left the link. */
696 if (!webkit_hit_test_result_context_is_link(result)) {
697 gtk_label_set_text(GTK_LABEL(viewer->l_link), NULL);
698 return;
701 gtk_label_set_text(GTK_LABEL(viewer->l_link),
702 webkit_hit_test_result_get_link_uri(result));
705 static void load_progress_cb(WebKitWebView *view, GParamSpec *param,
706 FancyViewer *viewer)
708 // WebKitLoadEvent status = webkit_web_view_get_load_status(viewer->view);
709 // gdouble pbar = webkit_web_view_get_progress(viewer->view);
710 // const gchar *uri = webkit_web_view_get_uri(viewer->view);
712 gdouble progress = webkit_web_view_get_estimated_load_progress(view);
713 gchar *label = g_strdup_printf("%d%% Loading...", (gint)(progress * 100));
714 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer->progress), progress);
715 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(viewer->progress), TRUE);
716 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress),
717 (const gchar*)label);
718 g_free(label);
720 /* switch (status) {
721 case WEBKIT_LOAD_COMMITTED:
722 break;
723 case WEBKIT_LOAD_FINISHED:
724 debug_print("Load finished: %s\n", uri);
725 break;
729 static void stop_loading_cb(GtkWidget *widget, GdkEvent *ev,
730 FancyViewer *viewer)
732 webkit_web_view_stop_loading (viewer->view);
733 gtk_widget_hide(viewer->progress);
734 gtk_widget_hide(viewer->ev_stop_loading);
737 static void search_the_web_cb(GtkWidget *widget, FancyViewer *viewer)
739 debug_print("Clicked on Search on Web\n");
740 if (webkit_web_view_has_selection(viewer->view)) {
741 gchar *search;
742 viewer->doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(viewer->view));
743 viewer->window = webkit_dom_document_get_default_view (viewer->doc);
744 viewer->selection = webkit_dom_dom_window_get_selection (viewer->window);
745 viewer->range = webkit_dom_dom_selection_get_range_at(viewer->selection, 0, NULL);
746 gchar *tmp = webkit_dom_range_get_text (viewer->range);
747 search = g_strconcat(GOOGLE_SEARCH, tmp, NULL);
749 webkit_web_view_load_uri(viewer->view, search);
750 g_free(search);
751 g_free(tmp);
755 static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer)
757 debug_print("open outer: %s\n", viewer->cur_link);
758 if(viewer->cur_link)
759 open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
762 static size_t download_file_curl_write_cb(void *buffer, size_t size,
763 size_t nmemb, void *data)
765 FancyViewer *viewer = (FancyViewer *)data;
766 if (!viewer->stream) {
767 viewer->stream = claws_fopen(viewer->curlfile, "wb");
768 if (!viewer->stream)
769 return -1;
771 return claws_fwrite(buffer, size, nmemb, viewer->stream);
773 static void *download_file_curl (void *data)
775 CURL *curl;
776 CURLcode res;
777 FancyViewer *viewer = (FancyViewer *)data;
779 curl_global_init(CURL_GLOBAL_DEFAULT);
780 curl = curl_easy_init();
782 if (curl) {
783 curl_easy_setopt(curl, CURLOPT_URL, viewer->cur_link);
784 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_file_curl_write_cb);
785 curl_easy_setopt(curl, CURLOPT_WRITEDATA, viewer);
786 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
787 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
788 #ifdef G_OS_WIN32
789 curl_easy_setopt(curl, CURLOPT_CAINFO, claws_ssl_get_cert_file());
790 #endif
791 res = curl_easy_perform(curl);
792 curl_easy_cleanup(curl);
794 if (CURLE_OK != res)
795 alertpanel_error(_("An error occurred: %d\n"), res);
796 if (viewer->stream)
797 claws_safe_fclose(viewer->stream);
798 curl_global_cleanup();
800 #ifdef USE_PTHREAD
801 pthread_exit(NULL);
802 #else
803 return NULL;
804 #endif
806 static void download_file_cb(GtkWidget *widget, FancyViewer *viewer)
808 #ifdef USE_PTHREAD
809 pthread_t curljob;
810 gint result;
811 #endif
812 const gchar *link = viewer->cur_link;
813 gchar *filename = g_utf8_strchr(link, -1, g_utf8_get_char("/"));
814 filename = g_strconcat(get_home_dir(), filename, NULL);
815 gchar *fname = filesel_select_file_save(_("Save as"), filename);
816 if (!fname) {
817 g_free(filename);
818 return;
821 if (viewer->curlfile) viewer->curlfile = NULL;
822 if (viewer->stream) viewer->stream = NULL;
823 viewer->curlfile = (const gchar *)g_strdup(fname);
824 g_free(filename);
825 g_free(fname);
827 if (!viewer->curlfile) return;
829 #ifdef USE_PTHREAD
830 result = pthread_create(&curljob, NULL, download_file_curl, (void *)viewer);
831 if (result)
832 alertpanel_error("ERROR; return code from pthread_create() is %d\n", result);
833 #else
834 download_file_curl((void *)viewer);
835 #endif
838 static void save_image_cb(GtkWidget *widget, FancyViewer *viewer)
840 debug_print("Not Yet Implemented\n");
843 static void open_image_cb(GtkWidget *widget, FancyViewer *viewer)
845 debug_print("Not Yet Implemented\n");
848 static void copy_image_cb(GtkWidget *widget, FancyViewer *viewer)
850 debug_print("Not Yet Implemented\n");
852 static void import_feed_cb(GtkWidget *widget, FancyViewer *viewer)
854 if (!folder_subscribe(viewer->cur_link))
855 alertpanel_error(_("%s is a malformed or not supported feed"), viewer->cur_link);
857 static void viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer)
859 const gchar *g_name = gtk_widget_get_name(GTK_WIDGET(menuitem));
860 if (!g_ascii_strcasecmp(g_name, "GtkMenuItem")) {
862 GtkWidget *menul = gtk_bin_get_child(GTK_BIN(menuitem));
864 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
865 "Search the Web")) {
866 gtk_label_set_text(GTK_LABEL(menul), _("Search the Web"));
867 viewer->cur_link = NULL;
868 GtkMenuItem *m_search = GTK_MENU_ITEM(menuitem);
869 g_signal_connect(G_OBJECT(m_search), "activate",
870 G_CALLBACK(search_the_web_cb),
871 (gpointer *) viewer);
874 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
875 "Open Link" )) {
877 gtk_label_set_text(GTK_LABEL(menul), _("Open in Viewer"));
879 GtkMenuItem *m_new = GTK_MENU_ITEM(menuitem);
880 gtk_widget_set_sensitive(GTK_WIDGET(m_new), viewer->override_prefs_remote_content);
883 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
884 "Open Link in New Window" )) {
886 gtk_label_set_text(GTK_LABEL(menul), _("Open in Browser"));
888 GtkMenuItem *m_new = GTK_MENU_ITEM(menuitem);
889 g_signal_connect(G_OBJECT(m_new), "activate",
890 G_CALLBACK(open_in_browser_cb),
891 (gpointer *) viewer);
894 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
895 "Open Image in New Window" )) {
896 gtk_label_set_text(GTK_LABEL(menul), _("Open Image"));
897 GtkMenuItem *m_image = GTK_MENU_ITEM(menuitem);
898 g_signal_connect(G_OBJECT(m_image), "activate",
899 G_CALLBACK(open_image_cb),
900 (gpointer *) viewer);
903 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
904 "Copy Link Location" )) {
905 gtk_label_set_text(GTK_LABEL(menul), _("Copy Link"));
908 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
909 "Download Linked File" )) {
910 gtk_label_set_text(GTK_LABEL(menul), _("Download Link"));
912 GtkMenuItem *m_dlink = GTK_MENU_ITEM(menuitem);
913 g_signal_connect(G_OBJECT(m_dlink), "activate",
914 G_CALLBACK(download_file_cb),
915 (gpointer *) viewer);
918 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
919 "Save Image As" )) {
921 gtk_label_set_text(GTK_LABEL(menul), _("Save Image As"));
923 GtkMenuItem *m_simage = GTK_MENU_ITEM(menuitem);
924 g_signal_connect(G_OBJECT(m_simage), "activate",
925 G_CALLBACK(save_image_cb),
926 (gpointer *) viewer);
929 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
930 "Copy Image" )) {
931 gtk_label_set_text(GTK_LABEL(menul), _("Copy Image"));
932 GtkMenuItem *m_cimage = GTK_MENU_ITEM(menuitem);
933 g_signal_connect(G_OBJECT(m_cimage), "activate",
934 G_CALLBACK(copy_image_cb),
935 (gpointer *) viewer);
941 static gboolean context_menu_cb (WebKitWebView *view, WebKitContextMenu *menu,
942 GdkEvent *event, WebKitHitTestResult *hit_test_result,
943 gpointer user_data)
945 FancyViewer *viewer = (FancyViewer *)user_data;
946 Plugin *plugin = plugin_get_loaded_by_name("RSSyl");
947 WebKitHitTestResultContext context;
948 const gchar *link_uri = NULL;
950 context = webkit_hit_test_result_get_context(hit_test_result);
952 link_uri = webkit_hit_test_result_get_link_uri(hit_test_result);
954 debug_print("context %d, link-uri '%s'\n", context,
955 (link_uri != NULL ? link_uri : "(null)"));
956 if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK &&
957 link_uri != NULL) {
958 if (viewer != NULL && viewer->cur_link != NULL) {
959 /* g_object_get() already made a copy, no need to strdup() here */
960 viewer->cur_link = link_uri;
964 gtk_container_foreach(GTK_CONTAINER(menu),
965 (GtkCallback)viewer_menu_handler,
966 viewer);
968 if (plugin) {
969 GtkWidget *rssyl = gtk_menu_item_new_with_label(_("Import feed"));
970 gtk_widget_show(GTK_WIDGET(rssyl));
971 gtk_menu_shell_append(GTK_MENU_SHELL(menu), rssyl);
972 g_signal_connect(G_OBJECT(rssyl), "activate",
973 G_CALLBACK(import_feed_cb),
974 (gpointer *) viewer);
977 return FALSE;
980 static gint keypress_events_cb (GtkWidget *widget, GdkEventKey *event,
981 FancyViewer *viewer)
983 if (event->state == CTRL_KEY) {
984 switch (event->keyval) {
985 case GDK_KEY_plus:
986 zoom_in_cb(viewer->ev_zoom_in, NULL, viewer);
987 break;
988 case GDK_KEY_period:
989 zoom_100_cb(viewer->ev_zoom_100, NULL, viewer);
990 break;
991 case GDK_KEY_minus:
992 zoom_out_cb(viewer->ev_zoom_out, NULL, viewer);
993 break;
996 return FALSE;
999 /*static gboolean release_button_cb (WebKitWebView *view, GdkEvent *ev, FancyViewer *viewer)
1001 if (ev->button.button == 1 && viewer->cur_link && viewer->override_prefs_external) {
1002 gint x, y;
1003 WebKitHitTestResult *result;
1004 result = webkit_web_view_get_hit_test_result(view, (GdkEventButton *)ev);
1005 g_object_get(G_OBJECT(result),
1006 "x", &x, "y", &y,
1007 NULL);
1009 *//* If this button release is end of a drag or selection event
1010 * (button press happened on different coordinates), we do not
1011 * want to open the link. *//*
1012 if ((x != viewer->click_x || y != viewer->click_y))
1013 return FALSE;
1015 open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
1016 return TRUE;
1018 return FALSE;
1021 static gboolean press_button_cb (WebKitWebView *view, GdkEvent *ev,
1022 FancyViewer *viewer)
1024 gint type = 0;
1025 gchar *link = NULL;
1027 WebKitHitTestResult *result =
1028 webkit_web_view_get_hit_test_result(view, (GdkEventButton *)ev);
1030 g_object_get(G_OBJECT(result),
1031 "context", &type,
1032 "x", &viewer->click_x,
1033 "y", &viewer->click_y,
1034 "link-uri", &link,
1035 NULL);
1037 if (type & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION)
1038 return FALSE;
1040 if (viewer->cur_link) {
1041 g_free(viewer->cur_link);
1042 viewer->cur_link = NULL;
1044 if (link != NULL) {
1045 debug_print("press on %s\n", link);
1046 viewer->cur_link = link;i*/ /* g_context returned a newly-allocated string
1049 viewer->doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(viewer->view));
1050 viewer->window = webkit_dom_document_get_default_view (viewer->doc);
1051 viewer->selection = webkit_dom_dom_window_get_selection (viewer->window);
1052 if (viewer->selection != NULL)
1053 webkit_dom_dom_selection_empty(viewer->selection);
1054 return FALSE;
1057 static void zoom_100_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer)
1059 gtk_widget_grab_focus(widget);
1060 webkit_web_view_set_zoom_level(viewer->view, 1);
1063 static void zoom_in_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer)
1065 gtk_widget_grab_focus(widget);
1066 fancy_prefs.zoom_level += 10;
1067 gdouble zoom_level;
1068 zoom_level = (double) fancy_prefs.zoom_level / 100;
1069 webkit_web_view_set_zoom_level(viewer->view, zoom_level);
1071 static void zoom_out_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer)
1073 gdouble zoom_level;
1074 gtk_widget_grab_focus(widget);
1075 fancy_prefs.zoom_level -= 10;
1076 zoom_level = (double) fancy_prefs.zoom_level / 100;
1077 if (fancy_prefs.zoom_level)
1078 webkit_web_view_set_zoom_level(viewer->view, zoom_level);
1081 static void resource_load_failed_cb(WebKitWebView *web_view,
1082 WebKitWebResource *web_resource,
1083 GError *error,
1084 FancyViewer *viewer)
1086 debug_print("Loading error: %s\n", error->message);
1089 static MimeViewer *fancy_viewer_create(void)
1091 FancyViewer *viewer;
1092 GtkWidget *hbox;
1094 debug_print("fancy_viewer_create\n");
1096 viewer = g_new0(FancyViewer, 1);
1097 viewer->mimeviewer.factory = &fancy_viewer_factory;
1098 viewer->mimeviewer.get_widget = fancy_get_widget;
1099 // viewer->mimeviewer.get_selection = fancy_get_selection;
1100 viewer->mimeviewer.show_mimepart = fancy_show_mimepart;
1101 viewer->mimeviewer.print = fancy_print;
1102 viewer->mimeviewer.clear_viewer = fancy_clear_viewer;
1103 viewer->mimeviewer.destroy_viewer = fancy_destroy_viewer;
1104 // viewer->mimeviewer.text_search = fancy_text_search;
1105 viewer->mimeviewer.scroll_page = fancy_scroll_page;
1106 viewer->mimeviewer.scroll_one_line = fancy_scroll_one_line;
1107 viewer->view = WEBKIT_WEB_VIEW(webkit_web_view_new());
1109 viewer->settings = webkit_settings_new();
1110 g_object_set(viewer->settings, "user-agent", "Fancy Viewer", NULL);
1111 viewer->scrollwin = gtk_scrolled_window_new(NULL, NULL);
1112 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewer->scrollwin),
1113 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1114 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(viewer->scrollwin),
1115 GTK_SHADOW_IN);
1116 gtk_container_add(GTK_CONTAINER(viewer->scrollwin),
1117 GTK_WIDGET(viewer->view));
1119 viewer->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1120 gtk_widget_set_name(GTK_WIDGET(viewer->vbox), "fancy_viewer");
1121 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1122 viewer->progress = gtk_progress_bar_new();
1123 gtk_widget_set_size_request(GTK_WIDGET(viewer->progress), 120, -1);
1124 /* Zoom Widgets */
1125 viewer->zoom_100 = stock_pixmap_widget(STOCK_PIXMAP_ZOOM_FIT);
1126 viewer->zoom_in = stock_pixmap_widget(STOCK_PIXMAP_ZOOM_IN);
1127 viewer->zoom_out = stock_pixmap_widget(STOCK_PIXMAP_ZOOM_OUT);
1128 viewer->stop_loading = stock_pixmap_widget(STOCK_PIXMAP_CANCEL);
1129 /* Event Widgets for the Zoom Widgets */
1130 viewer->ev_zoom_100 = gtk_event_box_new();
1131 viewer->ev_zoom_in = gtk_event_box_new();
1132 viewer->ev_zoom_out = gtk_event_box_new();
1133 viewer->ev_stop_loading = gtk_event_box_new();
1135 /* Link Label */
1136 viewer->l_link = gtk_label_new("");
1137 gtk_label_set_ellipsize(GTK_LABEL(viewer->l_link), PANGO_ELLIPSIZE_END);
1139 /* Preferences Widgets to override preferences on the fly */
1140 viewer->fancy_prefs = stock_pixmap_widget(STOCK_PIXMAP_PREFERENCES);
1141 viewer->ev_fancy_prefs = gtk_event_box_new();
1143 /* Popup Menu for preferences */
1144 viewer->fancy_prefs_menu = gtk_menu_new();
1145 fancy_create_popup_prefs_menu(viewer);
1147 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->ev_zoom_100), FALSE);
1148 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->ev_zoom_in), FALSE);
1149 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->ev_zoom_out), FALSE);
1150 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->ev_fancy_prefs), FALSE);
1151 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->ev_stop_loading), FALSE);
1153 gtk_container_add(GTK_CONTAINER(viewer->ev_zoom_100), viewer->zoom_100);
1154 gtk_container_add(GTK_CONTAINER(viewer->ev_zoom_in), viewer->zoom_in);
1155 gtk_container_add(GTK_CONTAINER(viewer->ev_zoom_out), viewer->zoom_out);
1156 gtk_container_add(GTK_CONTAINER(viewer->ev_fancy_prefs), viewer->fancy_prefs);
1157 gtk_container_add(GTK_CONTAINER(viewer->ev_stop_loading), viewer->stop_loading);
1159 gtk_box_pack_start(GTK_BOX(hbox), viewer->ev_zoom_100, FALSE, FALSE, 1);
1160 gtk_box_pack_start(GTK_BOX(hbox), viewer->ev_zoom_in, FALSE, FALSE, 2);
1161 gtk_box_pack_start(GTK_BOX(hbox), viewer->ev_zoom_out, FALSE, FALSE, 2);
1162 gtk_box_pack_start(GTK_BOX(hbox), viewer->ev_fancy_prefs, FALSE, FALSE, 2);
1163 gtk_box_pack_start(GTK_BOX(hbox), viewer->l_link, FALSE, FALSE, 8);
1164 gtk_box_pack_end(GTK_BOX(hbox), viewer->progress, FALSE, FALSE, 0);
1165 gtk_box_pack_end(GTK_BOX(hbox), viewer->ev_stop_loading, FALSE, FALSE, 0);
1167 gtk_box_pack_start(GTK_BOX(viewer->vbox), viewer->scrollwin, TRUE, TRUE,
1169 gtk_box_pack_start(GTK_BOX(viewer->vbox), hbox, FALSE, FALSE, 0);
1171 gtk_widget_show(viewer->ev_zoom_100);
1172 gtk_widget_show(viewer->ev_zoom_in);
1173 gtk_widget_show(viewer->ev_zoom_out);
1174 gtk_widget_show(viewer->ev_fancy_prefs);
1176 gtk_widget_show(viewer->scrollwin);
1177 gtk_widget_show(viewer->zoom_100);
1178 gtk_widget_show(viewer->zoom_in);
1179 gtk_widget_show(viewer->zoom_out);
1180 gtk_widget_show(viewer->fancy_prefs);
1181 gtk_widget_show(viewer->stop_loading);
1183 gtk_widget_show(viewer->l_link);
1184 gtk_widget_show(viewer->vbox);
1185 gtk_widget_show(hbox);
1186 gtk_widget_show(GTK_WIDGET(viewer->view));
1188 g_signal_connect(G_OBJECT(viewer->view), "load-changed",
1189 G_CALLBACK(load_changed_cb), viewer);
1190 g_signal_connect(G_OBJECT(viewer->view), "mouse-target-changed",
1191 G_CALLBACK(mouse_target_changed_cb), viewer);
1193 g_signal_connect(G_OBJECT(viewer->view), "notify::estimated-load-progress",
1194 G_CALLBACK(load_progress_cb), viewer);
1196 g_signal_connect(G_OBJECT(viewer->view), "decide-policy",
1197 G_CALLBACK(navigation_policy_cb), viewer);
1199 g_signal_connect(G_OBJECT(viewer->view), "resource-request-starting",
1200 G_CALLBACK(resource_request_starting_cb), viewer);
1201 g_signal_connect(G_OBJECT(viewer->view), "context-menu",
1202 G_CALLBACK(context_menu_cb), viewer);
1203 /* g_signal_connect(G_OBJECT(viewer->view), "button-press-event",
1204 G_CALLBACK(press_button_cb), viewer);
1205 g_signal_connect(G_OBJECT(viewer->view), "button-release-event",
1206 G_CALLBACK(release_button_cb), viewer);*/
1207 g_signal_connect(G_OBJECT(viewer->ev_zoom_100), "button-press-event",
1208 G_CALLBACK(zoom_100_cb), (gpointer*)viewer);
1209 g_signal_connect(G_OBJECT(viewer->ev_zoom_in), "button-press-event",
1210 G_CALLBACK(zoom_in_cb), (gpointer *)viewer);
1211 g_signal_connect(G_OBJECT(viewer->ev_zoom_out), "button-press-event",
1212 G_CALLBACK(zoom_out_cb), (gpointer *)viewer);
1213 g_signal_connect(G_OBJECT(viewer->ev_fancy_prefs), "button-press-event",
1214 G_CALLBACK(fancy_prefs_cb), (gpointer *)viewer);
1215 g_signal_connect(G_OBJECT(viewer->ev_stop_loading), "button-press-event",
1216 G_CALLBACK(stop_loading_cb), viewer);
1217 g_signal_connect(G_OBJECT(viewer->view), "key_press_event",
1218 G_CALLBACK(keypress_events_cb), viewer);
1220 g_signal_connect(G_OBJECT(viewer->view), "resource-load-failed",
1221 G_CALLBACK(resource_load_failed_cb), viewer);
1223 webkit_web_context_register_uri_scheme(webkit_web_context_get_default(),
1224 "cid", load_content_cb, viewer, NULL);
1226 viewer->filename = NULL;
1227 return (MimeViewer *) viewer;
1230 static gchar *content_types[] = {"text/html", NULL};
1232 static MimeViewerFactory fancy_viewer_factory =
1234 content_types,
1236 fancy_viewer_create,
1239 gint plugin_init(gchar **error)
1241 if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,0,0,0),
1242 VERSION_NUMERIC, _("Fancy"), error))
1243 return -1;
1244 gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
1245 "fancy", NULL);
1246 if (!is_dir_exist(directory))
1247 if (make_dir (directory) < 0) {
1248 g_free(directory);
1249 return -1;
1251 g_free(directory);
1253 gchar *web_ext_filename = g_strconcat(FANCY_WEB_EXTENSION_FILE,
1254 ".",
1255 G_MODULE_SUFFIX,
1256 NULL);
1257 gchar *web_ext_file = g_build_path(G_DIR_SEPARATOR_S,
1258 FANCY_WEB_EXTENSIONS_DIR,
1259 web_ext_filename,
1260 NULL);
1262 if (!g_file_test(web_ext_file, G_FILE_TEST_EXISTS)) {
1263 *error = g_strdup_printf(_("Failed to find the companion WebKit extension %s"), web_ext_file);
1264 g_free(web_ext_filename);
1265 g_free(web_ext_file);
1266 return -1;
1269 g_free(web_ext_filename);
1270 g_free(web_ext_file);
1272 webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(),
1273 FANCY_WEB_EXTENSIONS_DIR);
1275 fancy_prefs_init();
1277 mimeview_register_viewer_factory(&fancy_viewer_factory);
1279 return 0;
1282 gboolean plugin_done(void)
1284 mimeview_unregister_viewer_factory(&fancy_viewer_factory);
1285 fancy_prefs_done();
1286 return FALSE;
1289 const gchar *plugin_name(void)
1291 /* TRANSLATORS: 'Fancy' here is name of the plugin, not the english word. */
1292 return _("Fancy HTML Viewer");
1295 const gchar *plugin_desc(void)
1297 return g_strdup_printf(_("This plugin renders HTML mail using the WebKit "
1298 "%d.%d.%d library.\nBy default all remote content is "
1299 "blocked. Options "
1300 "can be found in /Configuration/Preferences/Plugins/Fancy"),
1301 WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION,
1302 WEBKIT_MICRO_VERSION);
1305 const gchar *plugin_type(void)
1307 return "GTK3";
1310 const gchar *plugin_licence(void)
1312 return "GPL3";
1315 const gchar *plugin_version(void)
1317 return VERSION;
1320 struct PluginFeature *plugin_provides(void)
1322 static struct PluginFeature features[] = {
1323 {PLUGIN_MIMEVIEWER, "text/html"},
1324 {PLUGIN_NOTHING, NULL}
1326 return features;