2 * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
4 * Copyright(C) 1999-2015 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/>.
25 #include "claws-features.h"
28 #include <fancy_viewer.h>
29 #include <fancy_prefs.h>
30 #include <alertpanel.h>
36 load_start_cb (WebKitWebView
*view
, gint progress
, FancyViewer
*viewer
);
39 load_finished_cb (WebKitWebView
*view
, gint progress
, FancyViewer
*viewer
);
42 over_link_cb (WebKitWebView
*view
, const gchar
*wtf
, const gchar
*link
,
43 FancyViewer
*viewer
, void *wtfa
);
46 load_progress_cb (WebKitWebView
*view
, gint progress
, FancyViewer
*viewer
);
48 static WebKitNavigationResponse
49 navigation_requested_cb (WebKitWebView
*view
, WebKitWebFrame
*frame
,
50 WebKitNetworkRequest
*netreq
, FancyViewer
*viewer
);
52 static MimeViewerFactory fancy_viewer_factory
;
55 fancy_text_search(MimeViewer
*_viewer
, gboolean backward
, const gchar
*str
,
59 viewer_menu_handler(GtkWidget
*menuitem
, FancyViewer
*viewer
);
61 static gint
keypress_events_cb (GtkWidget
*widget
, GdkEventKey
*event
,
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
);
75 #if !WEBKIT_CHECK_VERSION (1,5,1)
76 gchar
* webkit_web_view_get_selected_text(WebKitWebView
* web_view
);
80 static GtkWidget
*fancy_get_widget(MimeViewer
*_viewer
)
82 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
83 debug_print("fancy_get_widget: %p\n", viewer
->vbox
);
85 return GTK_WIDGET(viewer
->vbox
);
88 static void fancy_apply_prefs(FancyViewer
*viewer
)
90 g_object_set(viewer
->settings
,
91 "auto-load-images", viewer
->override_prefs_images
,
92 "enable-scripts", viewer
->override_prefs_scripts
,
93 "enable-plugins", viewer
->override_prefs_plugins
,
94 "enable-java-applet", viewer
->override_prefs_java
,
95 "enable-dns-prefetching", viewer
->override_prefs_remote_content
,
96 "user-stylesheet-uri", viewer
->override_stylesheet
,
98 "default-font-family", "Arial",
99 "cursive-font-family", "Comic Sans MS",
100 "fantasy-font-family", "Comic Sans MS",
101 "monospace-font-family", "Courier New",
102 "sans-serif-font-family", "Arial",
103 "serif-font-family", "Times New Roman",
106 webkit_web_view_set_settings(viewer
->view
, viewer
->settings
);
109 static void fancy_auto_load_images_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
110 viewer
->override_prefs_images
= gtk_check_menu_item_get_active(item
);
111 fancy_apply_prefs(viewer
);
112 webkit_web_view_reload (viewer
->view
);
115 static void fancy_enable_remote_content_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
116 viewer
->override_prefs_remote_content
= gtk_check_menu_item_get_active(item
);
117 fancy_apply_prefs(viewer
);
118 webkit_web_view_reload (viewer
->view
);
121 static void fancy_enable_scripts_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
122 viewer
->override_prefs_scripts
= gtk_check_menu_item_get_active(item
);
123 fancy_apply_prefs(viewer
);
124 webkit_web_view_reload (viewer
->view
);
127 static void fancy_enable_plugins_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
128 viewer
->override_prefs_plugins
= gtk_check_menu_item_get_active(item
);
129 fancy_apply_prefs(viewer
);
130 webkit_web_view_reload (viewer
->view
);
133 static void fancy_enable_java_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
134 viewer
->override_prefs_java
= gtk_check_menu_item_get_active(item
);
135 fancy_apply_prefs(viewer
);
136 webkit_web_view_reload (viewer
->view
);
139 static void fancy_open_external_activated(GtkCheckMenuItem
*item
, FancyViewer
*viewer
) {
140 viewer
->override_prefs_external
= gtk_check_menu_item_get_active(item
);
141 fancy_apply_prefs(viewer
);
144 static void fancy_set_defaults(FancyViewer
*viewer
)
146 viewer
->override_prefs_remote_content
= fancy_prefs
.enable_remote_content
;
147 viewer
->override_prefs_external
= fancy_prefs
.open_external
;
148 viewer
->override_prefs_images
= fancy_prefs
.enable_images
;
149 viewer
->override_prefs_scripts
= fancy_prefs
.enable_scripts
;
150 viewer
->override_prefs_plugins
= fancy_prefs
.enable_plugins
;
151 viewer
->override_prefs_java
= fancy_prefs
.enable_java
;
152 viewer
->override_stylesheet
= g_strconcat("file://", fancy_prefs
.stylesheet
, NULL
);
154 g_signal_handlers_block_by_func(G_OBJECT(viewer
->enable_images
),
155 fancy_auto_load_images_activated
, viewer
);
156 g_signal_handlers_block_by_func(G_OBJECT(viewer
->enable_remote_content
),
157 fancy_enable_remote_content_activated
, viewer
);
158 g_signal_handlers_block_by_func(G_OBJECT(viewer
->enable_scripts
),
159 fancy_enable_scripts_activated
, viewer
);
160 g_signal_handlers_block_by_func(G_OBJECT(viewer
->enable_plugins
),
161 fancy_enable_plugins_activated
, viewer
);
162 g_signal_handlers_block_by_func(G_OBJECT(viewer
->enable_java
),
163 fancy_enable_java_activated
, viewer
);
164 g_signal_handlers_block_by_func(G_OBJECT(viewer
->open_external
),
165 fancy_open_external_activated
, viewer
);
167 gtk_check_menu_item_set_active(
168 GTK_CHECK_MENU_ITEM(viewer
->enable_images
),
169 viewer
->override_prefs_images
);
170 gtk_check_menu_item_set_active(
171 GTK_CHECK_MENU_ITEM(viewer
->enable_scripts
),
172 viewer
->override_prefs_scripts
);
173 gtk_check_menu_item_set_active(
174 GTK_CHECK_MENU_ITEM(viewer
->enable_plugins
),
175 viewer
->override_prefs_plugins
);
176 gtk_check_menu_item_set_active(
177 GTK_CHECK_MENU_ITEM(viewer
->enable_java
),
178 viewer
->override_prefs_java
);
179 gtk_check_menu_item_set_active(
180 GTK_CHECK_MENU_ITEM(viewer
->enable_remote_content
),
181 viewer
->override_prefs_remote_content
);
182 gtk_check_menu_item_set_active(
183 GTK_CHECK_MENU_ITEM(viewer
->open_external
),
184 viewer
->override_prefs_external
);
186 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->enable_images
),
187 fancy_auto_load_images_activated
, viewer
);
188 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->enable_remote_content
),
189 fancy_enable_remote_content_activated
, viewer
);
190 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->enable_scripts
),
191 fancy_enable_scripts_activated
, viewer
);
192 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->enable_plugins
),
193 fancy_enable_plugins_activated
, viewer
);
194 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->enable_java
),
195 fancy_enable_java_activated
, viewer
);
196 g_signal_handlers_unblock_by_func(G_OBJECT(viewer
->open_external
),
197 fancy_open_external_activated
, viewer
);
199 fancy_apply_prefs(viewer
);
202 static void fancy_load_uri(FancyViewer
*viewer
, const gchar
*uri
)
204 #if WEBKIT_CHECK_VERSION(1,1,1)
205 webkit_web_view_load_uri(viewer
->view
, uri
);
207 webkit_web_view_open(viewer
->view
, uri
);
211 static gboolean
fancy_show_mimepart_real(MimeViewer
*_viewer
)
213 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
214 MessageView
*messageview
= ((MimeViewer
*)viewer
)->mimeview
215 ? ((MimeViewer
*)viewer
)->mimeview
->messageview
217 MimeInfo
*partinfo
= viewer
->to_load
;
220 messageview
->updating
= TRUE
;
221 NoticeView
*noticeview
= messageview
->noticeview
;
222 noticeview_hide(noticeview
);
225 if (viewer
->filename
!= NULL
) {
226 g_unlink(viewer
->filename
);
227 g_free(viewer
->filename
);
228 viewer
->filename
= NULL
;
232 viewer
->filename
= procmime_get_tmp_file_name(partinfo
);
233 debug_print("filename: %s\n", viewer
->filename
);
234 if (!viewer
->filename
) {
237 if (procmime_get_part(viewer
->filename
, partinfo
) < 0) {
238 g_free(viewer
->filename
);
239 viewer
->filename
= NULL
;
242 const gchar
*charset
= NULL
;
243 if (messageview
&& messageview
->forced_charset
)
244 charset
= _viewer
->mimeview
->messageview
->forced_charset
;
246 charset
= procmime_mimeinfo_get_parameter(partinfo
, "charset");
248 charset
= conv_get_locale_charset_str();
249 debug_print("using %s charset\n", charset
);
250 g_object_set(viewer
->settings
, "default-encoding", charset
, NULL
);
251 gchar
*tmp
= g_filename_to_uri(viewer
->filename
, NULL
, NULL
);
252 debug_print("zoom_level: %i\n", fancy_prefs
.zoom_level
);
253 webkit_web_view_set_zoom_level(viewer
->view
, (fancy_prefs
.zoom_level
/ 100.0));
255 fancy_set_defaults(viewer
);
256 fancy_load_uri(viewer
, tmp
);
260 viewer
->loading
= FALSE
;
263 static void fancy_show_notice(FancyViewer
*viewer
, const gchar
*message
)
265 gtk_label_set_text(GTK_LABEL(viewer
->l_link
), message
);
267 static gint
fancy_show_mimepart_prepare(MimeViewer
*_viewer
)
269 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
271 g_timeout_add(5, (GSourceFunc
)fancy_show_mimepart_real
, viewer
);
275 static void fancy_show_mimepart(MimeViewer
*_viewer
, const gchar
*infile
,
278 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
279 viewer
->to_load
= partinfo
;
280 viewer
->loading
= TRUE
;
281 g_timeout_add(5, (GtkFunction
)fancy_show_mimepart_prepare
, viewer
);
284 static void fancy_print(MimeViewer
*_viewer
)
286 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
287 GtkPrintOperationResult res
;
288 GError
*error
= NULL
;
289 GtkPrintOperation
*op
;
291 gtk_widget_realize(GTK_WIDGET(viewer
->view
));
293 while (viewer
->loading
)
296 op
= gtk_print_operation_new();
298 /* Config for printing */
299 gtk_print_operation_set_print_settings(op
, printing_get_settings());
300 gtk_print_operation_set_default_page_setup(op
, printing_get_page_setup());
301 #if GTK_CHECK_VERSION(2,18,0)
302 /* enable Page Size and Orientation in the print dialog */
303 gtk_print_operation_set_embed_page_setup(op
, TRUE
);
306 /* Start printing process */
307 res
= webkit_web_frame_print_full(webkit_web_view_get_main_frame(viewer
->view
),
308 op
, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
,
311 if (res
== GTK_PRINT_OPERATION_RESULT_ERROR
) {
312 gtk_print_operation_get_error(op
, &error
);
313 debug_print("Error printing message: %s\n",
314 error
? error
->message
: "no details");
315 } else if (res
== GTK_PRINT_OPERATION_RESULT_APPLY
) {
316 /* store settings for next printing session */
317 printing_store_settings(gtk_print_operation_get_print_settings(op
));
321 static gchar
*fancy_get_selection (MimeViewer
*_viewer
)
323 debug_print("fancy_get_selection\n");
324 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
325 #if WEBKIT_CHECK_VERSION(1,5,1)
326 viewer
->doc
= webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(viewer
->view
));
327 viewer
->window
= webkit_dom_document_get_default_view (viewer
->doc
);
328 viewer
->selection
= webkit_dom_dom_window_get_selection (viewer
->window
);
329 if (viewer
->selection
== NULL
)
331 viewer
->range
= webkit_dom_dom_selection_get_range_at(viewer
->selection
, 0, NULL
);
332 if (viewer
->range
== NULL
)
334 gchar
*sel
= webkit_dom_range_get_text (viewer
->range
);
336 gchar
*sel
= webkit_web_view_get_selected_text(viewer
->view
);
338 if (!viewer
->view
|| strlen(sel
) == 0) {
345 static void fancy_clear_viewer(MimeViewer
*_viewer
)
347 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
349 viewer
->cur_link
= NULL
;
350 fancy_set_defaults(viewer
);
352 fancy_load_uri(viewer
, "about:blank");
354 debug_print("fancy_clear_viewer\n");
355 fancy_prefs
.zoom_level
= webkit_web_view_get_zoom_level(viewer
->view
) * 100;
356 viewer
->to_load
= NULL
;
357 vadj
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer
->scrollwin
));
358 gtk_adjustment_set_value(vadj
, 0.0);
359 g_signal_emit_by_name(G_OBJECT(vadj
), "value-changed", 0);
362 static void fancy_destroy_viewer(MimeViewer
*_viewer
)
364 FancyViewer
*viewer
= (FancyViewer
*) _viewer
;
365 fancy_prefs
.zoom_level
= webkit_web_view_get_zoom_level(viewer
->view
) * 100;
366 debug_print("fancy_destroy_viewer\n");
367 g_free(viewer
->filename
);
371 static WebKitNavigationResponse
372 navigation_requested_cb(WebKitWebView
*view
, WebKitWebFrame
*frame
,
373 WebKitNetworkRequest
*netreq
, FancyViewer
*viewer
)
375 const gchar
*uri
= webkit_network_request_get_uri(netreq
);
377 debug_print("navigation requested to %s\n", uri
);
379 if (!strncmp(uri
, "mailto:", 7)) {
380 compose_new(NULL
, uri
+ 7, NULL
);
381 return WEBKIT_NAVIGATION_RESPONSE_IGNORE
;
382 } else if (!strncmp(uri
, "file://", 7)) {
383 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT
;
384 } else if (viewer
->override_prefs_remote_content
)
385 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT
;
387 fancy_show_notice(viewer
, _("Remote content loading is disabled."));
388 return WEBKIT_NAVIGATION_RESPONSE_IGNORE
;
392 static void resource_request_starting_cb(WebKitWebView
*view
,
393 WebKitWebFrame
*frame
,
394 WebKitWebResource
*resource
,
395 WebKitNetworkRequest
*request
,
396 WebKitNetworkResponse
*response
,
399 const gchar
*uri
= webkit_network_request_get_uri(request
);
403 MimeInfo
*partinfo
= viewer
->to_load
;
405 filename
= viewer
->filename
;
406 if ((!g_ascii_strncasecmp(uri
, "cid:", 4)) || (!g_ascii_strncasecmp(uri
, "mid:", 4))) {
407 image
= g_strconcat("<", uri
+ 4, ">", NULL
);
408 while ((partinfo
= procmime_mimeinfo_next(partinfo
)) != NULL
) {
409 if (!g_ascii_strcasecmp(image
, partinfo
->id
)) {
410 filename
= procmime_get_tmp_file_name(partinfo
);
415 if ((err
= procmime_get_part(filename
, partinfo
)) < 0)
416 alertpanel_error(_("Couldn't save the part of multipart message: %s"),
418 gchar
*file_uri
= g_filename_to_uri(filename
, NULL
, NULL
);
419 webkit_network_request_set_uri(request
, file_uri
);
428 /* refresh URI that may have changed */
429 uri
= webkit_network_request_get_uri(request
);
430 if (!viewer
->override_prefs_remote_content
431 && strncmp(uri
, "file://", 7) && strncmp(uri
, "data:", 5)) {
432 debug_print("Preventing load of %s\n", uri
);
433 webkit_network_request_set_uri(request
, "about:blank");
436 debug_print("Starting request of %zu %s\n", strlen(uri
), uri
);
439 static gboolean
fancy_text_search(MimeViewer
*_viewer
, gboolean backward
,
440 const gchar
*str
, gboolean case_sens
)
442 return webkit_web_view_search_text(((FancyViewer
*)_viewer
)->view
, str
,
443 case_sens
, !backward
, TRUE
);
446 static gboolean
fancy_prefs_cb(GtkWidget
*widget
, GdkEventButton
*ev
, FancyViewer
*viewer
)
448 if ((ev
->button
== 1) && (ev
->type
== GDK_BUTTON_PRESS
)) {
449 gtk_menu_popup(GTK_MENU(viewer
->fancy_prefs_menu
), NULL
, NULL
, NULL
, NULL
,
450 ev
->button
, ev
->time
);
456 static void fancy_create_popup_prefs_menu(FancyViewer
*viewer
) {
457 GtkWidget
*enable_images
;
458 GtkWidget
*enable_remote_content
;
459 GtkWidget
*enable_scripts
;
460 GtkWidget
*enable_plugins
;
461 GtkWidget
*enable_java
;
462 GtkWidget
*open_external
;
464 enable_images
= gtk_check_menu_item_new_with_label(_("Load images"));
466 enable_remote_content
= gtk_check_menu_item_new_with_label(_("Enable remote content"));
468 enable_scripts
= gtk_check_menu_item_new_with_label(_("Enable Javascript"));
470 enable_plugins
= gtk_check_menu_item_new_with_label(_("Enable Plugins"));
472 enable_java
= gtk_check_menu_item_new_with_label(_("Enable Java"));
474 open_external
= gtk_check_menu_item_new_with_label(_("Open links with external browser"));
476 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), enable_images
);
477 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), enable_remote_content
);
478 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), enable_scripts
);
479 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), enable_plugins
);
480 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), enable_java
);
481 gtk_menu_shell_append(GTK_MENU_SHELL(viewer
->fancy_prefs_menu
), open_external
);
483 gtk_menu_attach_to_widget(GTK_MENU(viewer
->fancy_prefs_menu
), viewer
->ev_fancy_prefs
, NULL
);
484 gtk_widget_show_all(viewer
->fancy_prefs_menu
);
486 viewer
->enable_images
= enable_images
;
487 viewer
->enable_scripts
= enable_scripts
;
488 viewer
->enable_plugins
= enable_plugins
;
489 viewer
->enable_java
= enable_java
;
490 viewer
->enable_remote_content
= enable_remote_content
;
491 viewer
->open_external
= open_external
;
493 /* Set sensitivity according to preferences and overrides */
495 g_signal_connect(G_OBJECT(enable_images
), "toggled",
496 G_CALLBACK (fancy_auto_load_images_activated
), viewer
);
497 g_signal_connect(G_OBJECT(enable_remote_content
), "toggled",
498 G_CALLBACK (fancy_enable_remote_content_activated
), viewer
);
499 g_signal_connect(G_OBJECT(enable_scripts
), "toggled",
500 G_CALLBACK (fancy_enable_scripts_activated
), viewer
);
501 g_signal_connect(G_OBJECT(enable_plugins
), "toggled",
502 G_CALLBACK (fancy_enable_plugins_activated
), viewer
);
503 g_signal_connect(G_OBJECT(enable_java
), "toggled",
504 G_CALLBACK (fancy_enable_java_activated
), viewer
);
505 g_signal_connect(G_OBJECT(open_external
), "toggled",
506 G_CALLBACK (fancy_open_external_activated
), viewer
);
508 fancy_apply_prefs(viewer
);
511 static gboolean
fancy_scroll_page(MimeViewer
*_viewer
, gboolean up
)
513 FancyViewer
*viewer
= (FancyViewer
*)_viewer
;
514 GtkAdjustment
*vadj
= gtk_scrolled_window_get_vadjustment(
515 GTK_SCROLLED_WINDOW(viewer
->scrollwin
));
517 if (viewer
->view
== NULL
)
520 return gtkutils_scroll_page(GTK_WIDGET(viewer
->view
), vadj
, up
);
523 static void fancy_scroll_one_line(MimeViewer
*_viewer
, gboolean up
)
525 FancyViewer
*viewer
= (FancyViewer
*)_viewer
;
526 GtkAdjustment
*vadj
= gtk_scrolled_window_get_vadjustment(
527 GTK_SCROLLED_WINDOW(viewer
->scrollwin
));
529 if (viewer
->view
== NULL
)
532 gtkutils_scroll_one_line(GTK_WIDGET(viewer
->view
), vadj
, up
);
535 static void load_start_cb(WebKitWebView
*view
, gint progress
,
538 gtk_widget_show(viewer
->progress
);
539 gtk_widget_show(viewer
->ev_stop_loading
);
542 static void load_finished_cb(WebKitWebView
*view
, gint progress
,
545 gtk_widget_hide(viewer
->progress
);
546 gtk_widget_hide(viewer
->ev_stop_loading
);
547 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer
->progress
),
549 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer
->progress
), "");
552 static void over_link_cb(WebKitWebView
*view
, const gchar
*wtf
,
553 const gchar
*link
, FancyViewer
*viewer
, void *wtfa
)
555 gtk_label_set_text(GTK_LABEL(viewer
->l_link
), link
);
556 g_free(viewer
->cur_link
);
557 viewer
->cur_link
= NULL
;
559 viewer
->cur_link
= g_strdup(link
);
563 static void load_progress_cb(WebKitWebView
*view
, gint progress
,
567 gchar
*label
= g_strdup_printf("%d%% Loading...", progress
);
568 pbar
= (gdouble
) progress
/ 100;
569 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer
->progress
), pbar
);
570 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer
->progress
),
571 (const gchar
*)label
);
574 static void stop_loading_cb(GtkWidget
*widget
, GdkEvent
*ev
,
577 webkit_web_view_stop_loading (viewer
->view
);
578 gtk_widget_hide(viewer
->progress
);
579 gtk_widget_hide(viewer
->ev_stop_loading
);
582 static void search_the_web_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
584 debug_print("Clicked on Search on Web\n");
585 if (webkit_web_view_has_selection(viewer
->view
)) {
587 #if WEBKIT_CHECK_VERSION(1,5,1)
588 viewer
->doc
= webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(viewer
->view
));
589 viewer
->window
= webkit_dom_document_get_default_view (viewer
->doc
);
590 viewer
->selection
= webkit_dom_dom_window_get_selection (viewer
->window
);
591 viewer
->range
= webkit_dom_dom_selection_get_range_at(viewer
->selection
, 0, NULL
);
592 gchar
*tmp
= webkit_dom_range_get_text (viewer
->range
);
594 gchar
*tmp
= webkit_web_view_get_selected_text(viewer
->view
);
596 search
= g_strconcat(GOOGLE_SEARCH
, tmp
, NULL
);
597 #if WEBKIT_CHECK_VERSION(1,1,1)
598 webkit_web_view_load_uri(viewer
->view
, search
);
600 webkit_web_view_open(viewer
->view
, search
);
607 static void open_in_browser_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
609 debug_print("open outer: %s\n", viewer
->cur_link
);
611 open_uri(viewer
->cur_link
, prefs_common_get_uri_cmd());
614 static size_t download_file_curl_write_cb(void *buffer
, size_t size
,
615 size_t nmemb
, void *data
)
617 FancyViewer
*viewer
= (FancyViewer
*)data
;
618 if (!viewer
->stream
) {
619 viewer
->stream
= fopen(viewer
->curlfile
, "wb");
623 return fwrite(buffer
, size
, nmemb
, viewer
->stream
);
625 static void *download_file_curl (void *data
)
629 FancyViewer
*viewer
= (FancyViewer
*)data
;
631 curl_global_init(CURL_GLOBAL_DEFAULT
);
632 curl
= curl_easy_init();
635 curl_easy_setopt(curl
, CURLOPT_URL
, viewer
->cur_link
);
636 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, download_file_curl_write_cb
);
637 curl_easy_setopt(curl
, CURLOPT_WRITEDATA
, viewer
);
638 curl_easy_setopt(curl
, CURLOPT_VERBOSE
, 1L);
639 res
= curl_easy_perform(curl
);
640 curl_easy_cleanup(curl
);
643 alertpanel_error(_("An error occurred: %d\n"), res
);
645 fclose(viewer
->stream
);
646 curl_global_cleanup();
654 static void download_file_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
660 const gchar
*link
= (const gchar
*)viewer
->cur_link
;
661 gchar
*filename
= g_utf8_strchr(link
, -1, g_utf8_get_char("/"));
662 filename
= g_strconcat(g_get_home_dir(), filename
, NULL
);
663 gchar
*fname
= filesel_select_file_save(_("Save as"), filename
);
665 if (viewer
->curlfile
) viewer
->curlfile
= NULL
;
666 if (viewer
->stream
) viewer
->stream
= NULL
;
667 viewer
->curlfile
= (const gchar
*)g_strdup(fname
);
671 if (!viewer
->curlfile
) return;
674 result
= pthread_create(&curljob
, NULL
, download_file_curl
, (void *)viewer
);
676 alertpanel_error("ERROR; return code from pthread_create() is %d\n", result
);
678 download_file_curl((void *)viewer
);
682 static void save_image_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
684 debug_print("Not Yet Implemented\n");
687 static void open_image_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
689 debug_print("Not Yet Implemented\n");
692 static void copy_image_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
694 debug_print("Not Yet Implemented\n");
696 static void import_feed_cb(GtkWidget
*widget
, FancyViewer
*viewer
)
698 if (!folder_subscribe(viewer
->cur_link
))
699 alertpanel_error(_("%s is a malformed or not supported feed"), viewer
->cur_link
);
701 static void viewer_menu_handler(GtkWidget
*menuitem
, FancyViewer
*viewer
)
703 const gchar
*g_name
= gtk_widget_get_name(GTK_WIDGET(menuitem
));
704 if (!g_ascii_strcasecmp(g_name
, "GtkImageMenuItem")) {
706 GtkWidget
*menul
= gtk_bin_get_child(GTK_BIN(menuitem
));
708 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
710 gtk_label_set_text(GTK_LABEL(menul
), _("Search the Web"));
711 viewer
->cur_link
= NULL
;
712 GtkImageMenuItem
*m_search
= GTK_IMAGE_MENU_ITEM(menuitem
);
713 g_signal_connect(G_OBJECT(m_search
), "activate",
714 G_CALLBACK(search_the_web_cb
),
715 (gpointer
*) viewer
);
718 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
721 if (viewer
->override_prefs_remote_content
)
722 gtk_label_set_text(GTK_LABEL(menul
), _("Open in Viewer"));
724 gtk_label_set_text(GTK_LABEL(menul
), _("Open in Viewer (enable remote content)"));
726 GtkImageMenuItem
*m_new
= GTK_IMAGE_MENU_ITEM(menuitem
);
727 gtk_widget_set_sensitive(GTK_WIDGET(m_new
), viewer
->override_prefs_remote_content
);
730 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
731 "Open Link in New Window" )) {
733 gtk_label_set_text(GTK_LABEL(menul
), _("Open in Browser"));
735 GtkImageMenuItem
*m_new
= GTK_IMAGE_MENU_ITEM(menuitem
);
736 g_signal_connect(G_OBJECT(m_new
), "activate",
737 G_CALLBACK(open_in_browser_cb
),
738 (gpointer
*) viewer
);
741 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
742 "Open Image in New Window" )) {
743 gtk_label_set_text(GTK_LABEL(menul
), _("Open Image"));
744 GtkImageMenuItem
*m_image
= GTK_IMAGE_MENU_ITEM(menuitem
);
745 g_signal_connect(G_OBJECT(m_image
), "activate",
746 G_CALLBACK(open_image_cb
),
747 (gpointer
*) viewer
);
750 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
751 "Copy Link Location" )) {
752 gtk_label_set_text(GTK_LABEL(menul
), _("Copy Link"));
754 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
755 "Download Linked File" )) {
756 gtk_label_set_text(GTK_LABEL(menul
), _("Download Link"));
758 GtkImageMenuItem
*m_dlink
= GTK_IMAGE_MENU_ITEM(menuitem
);
759 g_signal_connect(G_OBJECT(m_dlink
), "activate",
760 G_CALLBACK(download_file_cb
),
761 (gpointer
*) viewer
);
764 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
767 gtk_label_set_text(GTK_LABEL(menul
), _("Save Image As"));
769 GtkImageMenuItem
*m_simage
= GTK_IMAGE_MENU_ITEM(menuitem
);
770 g_signal_connect(G_OBJECT(m_simage
), "activate",
771 G_CALLBACK(save_image_cb
),
772 (gpointer
*) viewer
);
775 if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul
)),
777 gtk_label_set_text(GTK_LABEL(menul
), _("Copy Image"));
778 GtkImageMenuItem
*m_cimage
= GTK_IMAGE_MENU_ITEM(menuitem
);
779 g_signal_connect(G_OBJECT(m_cimage
), "activate",
780 G_CALLBACK(copy_image_cb
),
781 (gpointer
*) viewer
);
787 static gboolean
populate_popup_cb (WebKitWebView
*view
, GtkWidget
*menu
,
790 Plugin
*plugin
= plugin_get_loaded_by_name("RSSyl");
791 gtk_container_foreach(GTK_CONTAINER(menu
),
792 (GtkCallback
)viewer_menu_handler
,
795 GtkWidget
*rssyl
= gtk_image_menu_item_new_with_label(_("Import feed"));
796 GtkWidget
*img
= gtk_image_new_from_stock(GTK_STOCK_ADD
, GTK_ICON_SIZE_MENU
);
797 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(rssyl
), img
);
798 gtk_widget_show(GTK_WIDGET(rssyl
));
799 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), rssyl
);
800 g_signal_connect(G_OBJECT(rssyl
), "activate",
801 G_CALLBACK(import_feed_cb
),
802 (gpointer
*) viewer
);
807 static gint
keypress_events_cb (GtkWidget
*widget
, GdkEventKey
*event
,
810 if (event
->state
== CTRL_KEY
) {
811 switch (event
->keyval
) {
813 zoom_in_cb(viewer
->ev_zoom_in
, NULL
, viewer
);
816 zoom_100_cb(viewer
->ev_zoom_100
, NULL
, viewer
);
819 zoom_out_cb(viewer
->ev_zoom_out
, NULL
, viewer
);
826 static gboolean
release_button_cb (WebKitWebView
*view
, GdkEvent
*ev
,
829 if (ev
->button
.button
== 1 && viewer
->cur_link
&& viewer
->override_prefs_external
) {
830 open_uri(viewer
->cur_link
, prefs_common_get_uri_cmd());
835 static void zoom_100_cb(GtkWidget
*widget
, GdkEvent
*ev
, FancyViewer
*viewer
)
837 gtk_widget_grab_focus(widget
);
838 webkit_web_view_set_zoom_level(viewer
->view
, 1);
841 static void zoom_in_cb(GtkWidget
*widget
, GdkEvent
*ev
, FancyViewer
*viewer
)
843 gtk_widget_grab_focus(widget
);
844 webkit_web_view_zoom_in(viewer
->view
);
846 static void zoom_out_cb(GtkWidget
*widget
, GdkEvent
*ev
, FancyViewer
*viewer
)
848 gtk_widget_grab_focus(widget
);
849 webkit_web_view_zoom_out(viewer
->view
);
852 static MimeViewer
*fancy_viewer_create(void)
857 debug_print("fancy_viewer_create\n");
859 viewer
= g_new0(FancyViewer
, 1);
860 viewer
->mimeviewer
.factory
= &fancy_viewer_factory
;
861 viewer
->mimeviewer
.get_widget
= fancy_get_widget
;
862 viewer
->mimeviewer
.get_selection
= fancy_get_selection
;
863 viewer
->mimeviewer
.show_mimepart
= fancy_show_mimepart
;
864 viewer
->mimeviewer
.print
= fancy_print
;
865 viewer
->mimeviewer
.clear_viewer
= fancy_clear_viewer
;
866 viewer
->mimeviewer
.destroy_viewer
= fancy_destroy_viewer
;
867 viewer
->mimeviewer
.text_search
= fancy_text_search
;
868 viewer
->mimeviewer
.scroll_page
= fancy_scroll_page
;
869 viewer
->mimeviewer
.scroll_one_line
= fancy_scroll_one_line
;
870 viewer
->view
= WEBKIT_WEB_VIEW(webkit_web_view_new());
872 #ifdef HAVE_LIBSOUP_GNOME
873 /* Use GNOME proxy settings through libproxy */
874 if (fancy_prefs
.enable_gnome_proxy
) {
875 SoupSession
*session
= webkit_get_default_session();
876 soup_session_add_feature_by_type (session
, SOUP_TYPE_PROXY_RESOLVER_GNOME
);
880 if (fancy_prefs
.enable_proxy
) {
881 SoupSession
*session
= webkit_get_default_session();
882 SoupURI
* pURI
= soup_uri_new(fancy_prefs
.proxy_str
);
883 g_object_set(session
, "proxy-uri", pURI
, NULL
);
886 viewer
->settings
= webkit_web_settings_new();
887 g_object_set(viewer
->settings
, "user-agent", "Fancy Viewer", NULL
);
888 viewer
->scrollwin
= gtk_scrolled_window_new(NULL
, NULL
);
889 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewer
->scrollwin
),
890 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
891 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(viewer
->scrollwin
),
893 gtk_container_add(GTK_CONTAINER(viewer
->scrollwin
),
894 GTK_WIDGET(viewer
->view
));
896 viewer
->vbox
= gtk_vbox_new(FALSE
, 0);
897 hbox
= gtk_hbox_new(FALSE
, 0);
898 viewer
->progress
= gtk_progress_bar_new();
900 viewer
->zoom_100
= gtk_image_new_from_stock(GTK_STOCK_ZOOM_100
, GTK_ICON_SIZE_MENU
);
901 viewer
->zoom_in
= gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN
, GTK_ICON_SIZE_MENU
);
902 viewer
->zoom_out
= gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT
, GTK_ICON_SIZE_MENU
);
903 viewer
->stop_loading
= gtk_image_new_from_stock(GTK_STOCK_CANCEL
, GTK_ICON_SIZE_MENU
);
904 /* Event Widgets for the Zoom Widgets */
905 viewer
->ev_zoom_100
= gtk_event_box_new();
906 viewer
->ev_zoom_in
= gtk_event_box_new();
907 viewer
->ev_zoom_out
= gtk_event_box_new();
908 viewer
->ev_stop_loading
= gtk_event_box_new();
911 viewer
->l_link
= gtk_label_new("");
913 /* Preferences Widgets to override preferences on the fly */
914 viewer
->fancy_prefs
= gtk_image_new_from_stock(GTK_STOCK_PREFERENCES
, GTK_ICON_SIZE_MENU
);
915 viewer
->ev_fancy_prefs
= gtk_event_box_new();
917 /* Popup Menu for preferences */
918 viewer
->fancy_prefs_menu
= gtk_menu_new();
919 fancy_create_popup_prefs_menu(viewer
);
921 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer
->ev_zoom_100
), FALSE
);
922 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer
->ev_zoom_in
), FALSE
);
923 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer
->ev_zoom_out
), FALSE
);
924 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer
->ev_fancy_prefs
), FALSE
);
925 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer
->ev_stop_loading
), FALSE
);
927 gtk_container_add(GTK_CONTAINER(viewer
->ev_zoom_100
), viewer
->zoom_100
);
928 gtk_container_add(GTK_CONTAINER(viewer
->ev_zoom_in
), viewer
->zoom_in
);
929 gtk_container_add(GTK_CONTAINER(viewer
->ev_zoom_out
), viewer
->zoom_out
);
930 gtk_container_add(GTK_CONTAINER(viewer
->ev_fancy_prefs
), viewer
->fancy_prefs
);
931 gtk_container_add(GTK_CONTAINER(viewer
->ev_stop_loading
), viewer
->stop_loading
);
933 gtk_box_pack_start(GTK_BOX(hbox
), viewer
->ev_zoom_100
, FALSE
, FALSE
, 1);
934 gtk_box_pack_start(GTK_BOX(hbox
), viewer
->ev_zoom_in
, FALSE
, FALSE
, 2);
935 gtk_box_pack_start(GTK_BOX(hbox
), viewer
->ev_zoom_out
, FALSE
, FALSE
, 2);
936 gtk_box_pack_start(GTK_BOX(hbox
), viewer
->ev_fancy_prefs
, FALSE
, FALSE
, 2);
937 gtk_box_pack_start(GTK_BOX(hbox
), viewer
->l_link
, FALSE
, FALSE
, 8);
938 gtk_box_pack_end(GTK_BOX(hbox
), viewer
->progress
, FALSE
, FALSE
, 0);
939 gtk_box_pack_end(GTK_BOX(hbox
), viewer
->ev_stop_loading
, FALSE
, FALSE
, 0);
941 gtk_box_pack_start(GTK_BOX(viewer
->vbox
), viewer
->scrollwin
, TRUE
, TRUE
,
943 gtk_box_pack_start(GTK_BOX(viewer
->vbox
), hbox
, FALSE
, FALSE
, 0);
945 gtk_widget_show(viewer
->ev_zoom_100
);
946 gtk_widget_show(viewer
->ev_zoom_in
);
947 gtk_widget_show(viewer
->ev_zoom_out
);
948 gtk_widget_show(viewer
->ev_fancy_prefs
);
950 gtk_widget_show(viewer
->scrollwin
);
951 gtk_widget_show(viewer
->zoom_100
);
952 gtk_widget_show(viewer
->zoom_in
);
953 gtk_widget_show(viewer
->zoom_out
);
954 gtk_widget_show(viewer
->fancy_prefs
);
955 gtk_widget_show(viewer
->stop_loading
);
957 gtk_widget_show(viewer
->l_link
);
958 gtk_widget_show(viewer
->vbox
);
959 gtk_widget_show(hbox
);
960 gtk_widget_show(GTK_WIDGET(viewer
->view
));
962 g_signal_connect(G_OBJECT(viewer
->view
), "load-started",
963 G_CALLBACK(load_start_cb
), viewer
);
964 g_signal_connect(G_OBJECT(viewer
->view
), "load-finished",
965 G_CALLBACK(load_finished_cb
), viewer
);
966 g_signal_connect(G_OBJECT(viewer
->view
), "hovering-over-link",
967 G_CALLBACK(over_link_cb
), viewer
);
968 g_signal_connect(G_OBJECT(viewer
->view
), "load-progress-changed",
969 G_CALLBACK(load_progress_cb
), viewer
);
970 g_signal_connect(G_OBJECT(viewer
->view
), "navigation-requested",
971 G_CALLBACK(navigation_requested_cb
), viewer
);
972 g_signal_connect(G_OBJECT(viewer
->view
), "resource-request-starting",
973 G_CALLBACK(resource_request_starting_cb
), viewer
);
974 g_signal_connect(G_OBJECT(viewer
->view
), "populate-popup",
975 G_CALLBACK(populate_popup_cb
), viewer
);
976 g_signal_connect(G_OBJECT(viewer
->view
), "button-release-event",
977 G_CALLBACK(release_button_cb
), viewer
);
978 g_signal_connect(G_OBJECT(viewer
->ev_zoom_100
), "button-press-event",
979 G_CALLBACK(zoom_100_cb
), (gpointer
*)viewer
);
980 g_signal_connect(G_OBJECT(viewer
->ev_zoom_in
), "button-press-event",
981 G_CALLBACK(zoom_in_cb
), (gpointer
*)viewer
);
982 g_signal_connect(G_OBJECT(viewer
->ev_zoom_out
), "button-press-event",
983 G_CALLBACK(zoom_out_cb
), (gpointer
*)viewer
);
984 g_signal_connect(G_OBJECT(viewer
->ev_fancy_prefs
), "button-press-event",
985 G_CALLBACK(fancy_prefs_cb
), (gpointer
*)viewer
);
986 g_signal_connect(G_OBJECT(viewer
->ev_stop_loading
), "button-press-event",
987 G_CALLBACK(stop_loading_cb
), viewer
);
988 g_signal_connect(G_OBJECT(viewer
->view
), "key_press_event",
989 G_CALLBACK(keypress_events_cb
), viewer
);
991 viewer
->filename
= NULL
;
992 return (MimeViewer
*) viewer
;
995 static gchar
*content_types
[] = {"text/html", NULL
};
997 static MimeViewerFactory fancy_viewer_factory
=
1001 fancy_viewer_create
,
1004 gint
plugin_init(gchar
**error
)
1006 if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
1007 VERSION_NUMERIC
, _("Fancy"), error
))
1009 gchar
*directory
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
1011 if (!is_dir_exist(directory
))
1012 if (make_dir (directory
) < 0) {
1020 mimeview_register_viewer_factory(&fancy_viewer_factory
);
1025 gboolean
plugin_done(void)
1027 mimeview_unregister_viewer_factory(&fancy_viewer_factory
);
1032 const gchar
*plugin_name(void)
1034 /* i18n: 'Fancy' here is name of the plugin, not the english word. */
1035 return _("Fancy HTML Viewer");
1038 const gchar
*plugin_desc(void)
1040 return g_strdup_printf(_("This plugin renders HTML mail using the WebKit "
1041 "%d.%d.%d library.\nBy default all remote content is "
1043 "can be found in /Configuration/Preferences/Plugins/Fancy"),
1044 WEBKIT_MAJOR_VERSION
, WEBKIT_MINOR_VERSION
,
1045 WEBKIT_MICRO_VERSION
);
1048 const gchar
*plugin_type(void)
1053 const gchar
*plugin_licence(void)
1058 const gchar
*plugin_version(void)
1063 struct PluginFeature
*plugin_provides(void)
1065 static struct PluginFeature features
[] = {
1066 {PLUGIN_MIMEVIEWER
, "text/html"},
1067 {PLUGIN_NOTHING
, NULL
}