Fix building against older webkitgtk versions.
[claws.git] / src / plugins / fancy / fancy_viewer.c
index 9a7e0672e42406d5b3a5a79b5bc89900851ed23a..1e29d30d04b521e1dd787f972fbf90c93e47d800 100644 (file)
@@ -1,20 +1,22 @@
-/* 
+/*
  * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
  * == Fancy Plugin ==
- * Copyright(C) 1999-2013 the Claws Mail Team
- * This file Copyright (C) 2009-2013 Salvatore De Paolis
+ * Copyright(C) 1999-2015 the Claws Mail Team
+ * This file Copyright (C) 2009-2014 Salvatore De Paolis
  * <iwkse@claws-mail.org> and the Claws Mail Team
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
+ *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write tothe Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 
 #include <alertpanel.h>
 
 #include <printing.h>
+#include <webkit/webkithittestresult.h>
 
-
-static void 
+static void
 load_start_cb (WebKitWebView *view, gint progress, FancyViewer *viewer);
 
-static void 
+static void
 load_finished_cb (WebKitWebView *view, gint progress, FancyViewer *viewer);
 
-static void 
-over_link_cb (WebKitWebView *view, const gchar *wtf, const gchar *link, 
-                         FancyViewer *viewer, void *wtfa);
+static void
+over_link_cb (WebKitWebView *view, const gchar *wtf, const gchar *link,
+             FancyViewer *viewer, void *wtfa);
 
-static void 
+static void
 load_progress_cb (WebKitWebView *view, gint progress, FancyViewer *viewer);
 
-static WebKitNavigationResponse 
-navigation_requested_cb (WebKitWebView *view, WebKitWebFrame *frame, 
-                                                WebKitNetworkRequest *netreq, FancyViewer *viewer);
+static WebKitNavigationResponse
+navigation_requested_cb (WebKitWebView *view, WebKitWebFrame *frame,
+                        WebKitNetworkRequest *netreq, FancyViewer *viewer);
 
 static MimeViewerFactory fancy_viewer_factory;
 
 static gboolean
-fancy_text_search(MimeViewer *_viewer, gboolean backward, const gchar *str, 
-                                 gboolean case_sens);
+fancy_text_search(MimeViewer *_viewer, gboolean backward, const gchar *str,
+                 gboolean case_sens);
 
-static void 
+static void
 viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer);
 
 static gint keypress_events_cb (GtkWidget *widget, GdkEventKey *event,
@@ -65,8 +67,8 @@ static void zoom_100_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
 static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer);
 static void fancy_create_popup_prefs_menu(FancyViewer *viewer);
 static void fancy_show_notice(FancyViewer *viewer, const gchar *message);
-static size_t download_file_curl_write_cb(void *buffer, size_t size, 
-                                                                                 size_t nmemb, void *data);
+static size_t download_file_curl_write_cb(void *buffer, size_t size,
+                                         size_t nmemb, void *data);
 static void *download_file_curl (void *data);
 static void download_file_cb(GtkWidget *widget, FancyViewer *viewer);
 
@@ -85,15 +87,22 @@ static GtkWidget *fancy_get_widget(MimeViewer *_viewer)
 
 static void fancy_apply_prefs(FancyViewer *viewer)
 {
-       g_object_set(viewer->settings, "auto-load-images",
-               viewer->override_prefs_images, NULL);
-       g_object_set(viewer->settings, "enable-scripts",
-               viewer->override_prefs_scripts, NULL);
-       g_object_set(viewer->settings, "enable-plugins",
-               viewer->override_prefs_plugins, NULL);
-       g_object_set(viewer->settings, "enable-java-applet",
-               viewer->override_prefs_java, NULL);
-
+       g_object_set(viewer->settings,
+               "auto-load-images", viewer->override_prefs_images,
+               "enable-scripts", viewer->override_prefs_scripts,
+               "enable-plugins", viewer->override_prefs_plugins,
+               "enable-java-applet", viewer->override_prefs_java,
+               "enable-dns-prefetching", viewer->override_prefs_remote_content,
+               "user-stylesheet-uri", viewer->override_stylesheet,
+#ifdef G_OS_WIN32
+               "default-font-family", "Arial",
+               "cursive-font-family", "Comic Sans MS",
+               "fantasy-font-family", "Comic Sans MS",
+               "monospace-font-family", "Courier New",
+               "sans-serif-font-family", "Arial",
+               "serif-font-family", "Times New Roman",
+#endif
+               NULL);
        webkit_web_view_set_settings(viewer->view, viewer->settings);
 }
 
@@ -136,12 +145,13 @@ static void fancy_set_defaults(FancyViewer *viewer)
 {
        viewer->override_prefs_remote_content = fancy_prefs.enable_remote_content;
        viewer->override_prefs_external = fancy_prefs.open_external;
-       viewer->override_prefs_images = fancy_prefs.auto_load_images;
+       viewer->override_prefs_images = fancy_prefs.enable_images;
        viewer->override_prefs_scripts = fancy_prefs.enable_scripts;
        viewer->override_prefs_plugins = fancy_prefs.enable_plugins;
        viewer->override_prefs_java = fancy_prefs.enable_java;
+       viewer->override_stylesheet = g_strconcat("file://", fancy_prefs.stylesheet, NULL);
 
-       g_signal_handlers_block_by_func(G_OBJECT(viewer->auto_load_images),
+       g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_images),
                fancy_auto_load_images_activated, viewer);
        g_signal_handlers_block_by_func(G_OBJECT(viewer->enable_remote_content),
                fancy_enable_remote_content_activated, viewer);
@@ -155,7 +165,7 @@ static void fancy_set_defaults(FancyViewer *viewer)
                fancy_open_external_activated, viewer);
 
        gtk_check_menu_item_set_active(
-               GTK_CHECK_MENU_ITEM(viewer->auto_load_images),
+               GTK_CHECK_MENU_ITEM(viewer->enable_images),
                viewer->override_prefs_images);
        gtk_check_menu_item_set_active(
                GTK_CHECK_MENU_ITEM(viewer->enable_scripts),
@@ -173,7 +183,7 @@ static void fancy_set_defaults(FancyViewer *viewer)
                GTK_CHECK_MENU_ITEM(viewer->open_external),
                viewer->override_prefs_external);
 
-       g_signal_handlers_unblock_by_func(G_OBJECT(viewer->auto_load_images),
+       g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_images),
                fancy_auto_load_images_activated, viewer);
        g_signal_handlers_unblock_by_func(G_OBJECT(viewer->enable_remote_content),
                fancy_enable_remote_content_activated, viewer);
@@ -201,12 +211,16 @@ static void fancy_load_uri(FancyViewer *viewer, const gchar *uri)
 static gboolean fancy_show_mimepart_real(MimeViewer *_viewer)
 {
        FancyViewer *viewer = (FancyViewer *) _viewer;
-       MessageView *messageview = ((MimeViewer *)viewer)->mimeview 
-                                       ? ((MimeViewer *)viewer)->mimeview->messageview 
+       MessageView *messageview = ((MimeViewer *)viewer)->mimeview
+                                       ? ((MimeViewer *)viewer)->mimeview->messageview
                                        : NULL;
        MimeInfo *partinfo = viewer->to_load;
-    
-       messageview->updating = TRUE;
+
+       if (messageview) {
+               messageview->updating = TRUE;
+               NoticeView *noticeview = messageview->noticeview;
+               noticeview_hide(noticeview);
+       }
 
        if (viewer->filename != NULL) {
                g_unlink(viewer->filename);
@@ -214,24 +228,19 @@ static gboolean fancy_show_mimepart_real(MimeViewer *_viewer)
                viewer->filename = NULL;
        }
 
-       if (messageview) {
-               NoticeView *noticeview = messageview->noticeview;
-               noticeview_hide(noticeview);
-       }
-       if (partinfo) 
+       if (partinfo)
                viewer->filename = procmime_get_tmp_file_name(partinfo);
        debug_print("filename: %s\n", viewer->filename);
-       if (!viewer->filename) {    
+       if (!viewer->filename) {
                return FALSE;
        }
        if (procmime_get_part(viewer->filename, partinfo) < 0) {
                g_free(viewer->filename);
                viewer->filename = NULL;
-       } 
+       }
        else {
                const gchar *charset = NULL;
-               if (_viewer && _viewer->mimeview &&
-                       _viewer->mimeview->messageview->forced_charset)
+               if (messageview && messageview->forced_charset)
                        charset = _viewer->mimeview->messageview->forced_charset;
                else
                        charset = procmime_mimeinfo_get_parameter(partinfo, "charset");
@@ -259,15 +268,7 @@ static gint fancy_show_mimepart_prepare(MimeViewer *_viewer)
 {
        FancyViewer *viewer = (FancyViewer *) _viewer;
 
-       if (viewer->tag > 0) {
-               gtk_timeout_remove(viewer->tag);
-               viewer->tag = -1;
-               if (viewer->loading) {
-                       viewer->stop_previous = TRUE;
-               }
-       }
-    
-       viewer->tag = g_timeout_add(5, (GSourceFunc)fancy_show_mimepart_real, viewer);
+       g_timeout_add(5, (GSourceFunc)fancy_show_mimepart_real, viewer);
        return FALSE;
 }
 
@@ -288,7 +289,7 @@ static void fancy_print(MimeViewer *_viewer)
        GtkPrintOperation *op;
 
        gtk_widget_realize(GTK_WIDGET(viewer->view));
-    
+
        while (viewer->loading)
                claws_do_idle();
 
@@ -338,7 +339,7 @@ static gchar *fancy_get_selection (MimeViewer *_viewer)
                g_free(sel);
                return NULL;
        }
-       return sel; 
+       return sel;
 }
 
 static void fancy_clear_viewer(MimeViewer *_viewer)
@@ -367,11 +368,12 @@ static void fancy_destroy_viewer(MimeViewer *_viewer)
        g_free(viewer);
 }
 
-static WebKitNavigationResponse 
-navigation_requested_cb(WebKitWebView *view, WebKitWebFrame *frame, 
+static WebKitNavigationResponse
+navigation_requested_cb(WebKitWebView *view, WebKitWebFrame *frame,
                                                WebKitNetworkRequest *netreq, FancyViewer *viewer)
 {
        const gchar *uri = webkit_network_request_get_uri(netreq);
+
        debug_print("navigation requested to %s\n", uri);
 
        if (!strncmp(uri, "mailto:", 7)) {
@@ -387,13 +389,12 @@ navigation_requested_cb(WebKitWebView *view, WebKitWebFrame *frame,
        }
 }
 
-#if WEBKIT_CHECK_VERSION (1,1,14)
-static void resource_request_starting_cb(WebKitWebView                 *view, 
-                                                                                WebKitWebFrame                 *frame,
-                                                                                WebKitWebResource              *resource,
-                                                                                WebKitNetworkRequest   *request,
-                                                                                WebKitNetworkResponse  *response,
-                                                                                FancyViewer                    *viewer)
+static void resource_request_starting_cb(WebKitWebView         *view,
+                                        WebKitWebFrame         *frame,
+                                        WebKitWebResource      *resource,
+                                        WebKitNetworkRequest   *request,
+                                        WebKitNetworkResponse  *response,
+                                        FancyViewer            *viewer)
 {
        const gchar *uri = webkit_network_request_get_uri(request);
        gchar *filename;
@@ -413,8 +414,8 @@ static void resource_request_starting_cb(WebKitWebView                      *view,
                                }
                                if ((err = procmime_get_part(filename, partinfo)) < 0)
                                        alertpanel_error(_("Couldn't save the part of multipart message: %s"),
-                                                                               strerror(-err));
-                               gchar *file_uri = g_strconcat("file://", filename, NULL);
+                                                                               g_strerror(-err));
+                               gchar *file_uri = g_filename_to_uri(filename, NULL, NULL);
                                webkit_network_request_set_uri(request, file_uri);
                                g_free(file_uri);
                                g_free(filename);
@@ -423,34 +424,44 @@ static void resource_request_starting_cb(WebKitWebView                    *view,
                }
                g_free(image);
        }
+       
+       /* refresh URI that may have changed */
+       uri = webkit_network_request_get_uri(request);
+       if (!viewer->override_prefs_remote_content
+           && strncmp(uri, "file://", 7) && strncmp(uri, "data:", 5)) {
+               debug_print("Preventing load of %s\n", uri);
+               webkit_network_request_set_uri(request, "about:blank");
+       }
+       else
+               debug_print("Starting request of %zu %s\n", strlen(uri), uri);
 }
-#endif
-static gboolean fancy_text_search(MimeViewer *_viewer, gboolean backward, 
-                                                                 const gchar *str, gboolean case_sens)
+
+static gboolean fancy_text_search(MimeViewer *_viewer, gboolean backward,
+                                 const gchar *str, gboolean case_sens)
 {
        return webkit_web_view_search_text(((FancyViewer*)_viewer)->view, str,
-                                                                          case_sens, !backward, TRUE);
+                                          case_sens, !backward, TRUE);
 }
 
 static gboolean fancy_prefs_cb(GtkWidget *widget, GdkEventButton *ev, FancyViewer *viewer)
 {
        if ((ev->button == 1) && (ev->type == GDK_BUTTON_PRESS)) {
                gtk_menu_popup(GTK_MENU(viewer->fancy_prefs_menu), NULL, NULL, NULL, NULL,
-                                          ev->button, ev->time);
+                               ev->button, ev->time);
                return TRUE;
        }
        return FALSE;
 }
 
 static void fancy_create_popup_prefs_menu(FancyViewer *viewer) {
-       GtkWidget *auto_load_images;
+       GtkWidget *enable_images;
        GtkWidget *enable_remote_content;
        GtkWidget *enable_scripts;
        GtkWidget *enable_plugins;
        GtkWidget *enable_java;
        GtkWidget *open_external;
 
-       auto_load_images = gtk_check_menu_item_new_with_label(_("Load images"));
+       enable_images = gtk_check_menu_item_new_with_label(_("Load images"));
 
        enable_remote_content = gtk_check_menu_item_new_with_label(_("Enable remote content"));
 
@@ -462,7 +473,7 @@ static void fancy_create_popup_prefs_menu(FancyViewer *viewer) {
 
        open_external = gtk_check_menu_item_new_with_label(_("Open links with external browser"));
 
-       gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), auto_load_images);
+       gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_images);
        gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_remote_content);
        gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_scripts);
        gtk_menu_shell_append(GTK_MENU_SHELL(viewer->fancy_prefs_menu), enable_plugins);
@@ -472,7 +483,7 @@ static void fancy_create_popup_prefs_menu(FancyViewer *viewer) {
        gtk_menu_attach_to_widget(GTK_MENU(viewer->fancy_prefs_menu), viewer->ev_fancy_prefs, NULL);
        gtk_widget_show_all(viewer->fancy_prefs_menu);
 
-       viewer->auto_load_images = auto_load_images;
+       viewer->enable_images = enable_images;
        viewer->enable_scripts = enable_scripts;
        viewer->enable_plugins = enable_plugins;
        viewer->enable_java = enable_java;
@@ -481,18 +492,18 @@ static void fancy_create_popup_prefs_menu(FancyViewer *viewer) {
 
        /* Set sensitivity according to preferences and overrides */
 
-       g_signal_connect(G_OBJECT(auto_load_images), "toggled",
-                                        G_CALLBACK (fancy_auto_load_images_activated), viewer);
+       g_signal_connect(G_OBJECT(enable_images), "toggled",
+                        G_CALLBACK (fancy_auto_load_images_activated), viewer);
        g_signal_connect(G_OBJECT(enable_remote_content), "toggled",
-                                        G_CALLBACK (fancy_enable_remote_content_activated), viewer);
+                        G_CALLBACK (fancy_enable_remote_content_activated), viewer);
        g_signal_connect(G_OBJECT(enable_scripts), "toggled",
-                                        G_CALLBACK (fancy_enable_scripts_activated), viewer);
+                        G_CALLBACK (fancy_enable_scripts_activated), viewer);
        g_signal_connect(G_OBJECT(enable_plugins), "toggled",
-                                        G_CALLBACK (fancy_enable_plugins_activated), viewer);
+                        G_CALLBACK (fancy_enable_plugins_activated), viewer);
        g_signal_connect(G_OBJECT(enable_java), "toggled",
-                                        G_CALLBACK (fancy_enable_java_activated), viewer);
+                        G_CALLBACK (fancy_enable_java_activated), viewer);
        g_signal_connect(G_OBJECT(open_external), "toggled",
-                                        G_CALLBACK (fancy_open_external_activated), viewer);
+                        G_CALLBACK (fancy_open_external_activated), viewer);
 
        fancy_apply_prefs(viewer);
 }
@@ -501,7 +512,7 @@ static gboolean fancy_scroll_page(MimeViewer *_viewer, gboolean up)
 {
        FancyViewer *viewer = (FancyViewer *)_viewer;
        GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
-                                                 GTK_SCROLLED_WINDOW(viewer->scrollwin));
+                                       GTK_SCROLLED_WINDOW(viewer->scrollwin));
 
        if (viewer->view == NULL)
                return FALSE;
@@ -513,7 +524,7 @@ static void fancy_scroll_one_line(MimeViewer *_viewer, gboolean up)
 {
        FancyViewer *viewer = (FancyViewer *)_viewer;
        GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
-                                                 GTK_SCROLLED_WINDOW(viewer->scrollwin));
+                                       GTK_SCROLLED_WINDOW(viewer->scrollwin));
 
        if (viewer->view == NULL)
                return;
@@ -521,25 +532,25 @@ static void fancy_scroll_one_line(MimeViewer *_viewer, gboolean up)
        gtkutils_scroll_one_line(GTK_WIDGET(viewer->view), vadj, up);
 }
 
-static void load_start_cb(WebKitWebView *view, gint progress, 
+static void load_start_cb(WebKitWebView *view, gint progress,
                           FancyViewer *viewer)
 {
        gtk_widget_show(viewer->progress);
        gtk_widget_show(viewer->ev_stop_loading);
 }
 
-static void load_finished_cb(WebKitWebView *view, gint progress, 
-                                                        FancyViewer *viewer)
+static void load_finished_cb(WebKitWebView *view, gint progress,
+                            FancyViewer *viewer)
 {
        gtk_widget_hide(viewer->progress);
        gtk_widget_hide(viewer->ev_stop_loading);
-       gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer->progress), 
-                                                                (gdouble) 0.0);
+       gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer->progress),
+                                     (gdouble) 0.0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress), "");
 }
 
-static void over_link_cb(WebKitWebView *view, const gchar *wtf, 
-                                                const gchar *link, FancyViewer *viewer, void *wtfa)
+static void over_link_cb(WebKitWebView *view, const gchar *wtf,
+                        const gchar *link, FancyViewer *viewer, void *wtfa)
 {
        gtk_label_set_text(GTK_LABEL(viewer->l_link), link);
        g_free(viewer->cur_link);
@@ -549,18 +560,18 @@ static void over_link_cb(WebKitWebView *view, const gchar *wtf,
        }
 }
 
-static void load_progress_cb(WebKitWebView *view, gint progress, 
-                                                        FancyViewer *viewer)
+static void load_progress_cb(WebKitWebView *view, gint progress,
+                            FancyViewer *viewer)
 {
        gdouble pbar;
        gchar *label = g_strdup_printf("%d%% Loading...", progress);
        pbar = (gdouble) progress / 100;
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(viewer->progress), pbar);
-       gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress), 
-                                                        (const gchar*)label);
+       gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress),
+                                 (const gchar*)label);
        g_free(label);
 }
-static void stop_loading_cb(GtkWidget *widget, GdkEvent *ev, 
+static void stop_loading_cb(GtkWidget *widget, GdkEvent *ev,
                                                        FancyViewer *viewer)
 {
        webkit_web_view_stop_loading (viewer->view);
@@ -600,8 +611,8 @@ static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer)
                open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
 }
 
-static size_t download_file_curl_write_cb(void *buffer, size_t size, 
-                                                                                 size_t nmemb, void *data)
+static size_t download_file_curl_write_cb(void *buffer, size_t size,
+                                         size_t nmemb, void *data)
 {
        FancyViewer *viewer = (FancyViewer *)data;
        if (!viewer->stream) {
@@ -658,16 +669,21 @@ static void download_file_cb(GtkWidget *widget, FancyViewer *viewer)
        g_free(fname);
 
        if (!viewer->curlfile) return;
-    
+
 #ifdef USE_PTHREAD
        result = pthread_create(&curljob, NULL, download_file_curl, (void *)viewer);
-       if (result)   
+       if (result)
                alertpanel_error("ERROR; return code from pthread_create() is %d\n", result);
 #else
        download_file_curl((void *)viewer);
 #endif
 }
 
+static void save_image_cb(GtkWidget *widget, FancyViewer *viewer)
+{
+       debug_print("Not Yet Implemented\n");
+}
+
 static void open_image_cb(GtkWidget *widget, FancyViewer *viewer)
 {
        debug_print("Not Yet Implemented\n");
@@ -689,18 +705,18 @@ static void viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer)
 
                GtkWidget *menul = gtk_bin_get_child(GTK_BIN(menuitem));
 
-        if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Search the Web")) {
+        if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                               "Search the Web")) {
                        gtk_label_set_text(GTK_LABEL(menul), _("Search the Web"));
                        viewer->cur_link = NULL;
                        GtkImageMenuItem *m_search = GTK_IMAGE_MENU_ITEM(menuitem);
                        g_signal_connect(G_OBJECT(m_search), "activate",
-                                                        G_CALLBACK(search_the_web_cb),
-                                                        (gpointer *) viewer);
+                                        G_CALLBACK(search_the_web_cb),
+                                        (gpointer *) viewer);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Open Link" )) {
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                                       "Open Link" )) {
 
                        if (viewer->override_prefs_remote_content)
                                gtk_label_set_text(GTK_LABEL(menul), _("Open in Viewer"));
@@ -711,79 +727,79 @@ static void viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer)
                        gtk_widget_set_sensitive(GTK_WIDGET(m_new), viewer->override_prefs_remote_content);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
                                                                "Open Link in New Window" )) {
 
                        gtk_label_set_text(GTK_LABEL(menul), _("Open in Browser"));
 
                        GtkImageMenuItem *m_new = GTK_IMAGE_MENU_ITEM(menuitem);
                        g_signal_connect(G_OBJECT(m_new), "activate",
-                                                        G_CALLBACK(open_in_browser_cb),
-                                                        (gpointer *) viewer);
+                                        G_CALLBACK(open_in_browser_cb),
+                                        (gpointer *) viewer);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Open Image in New Window" )) {
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                                       "Open Image in New Window" )) {
                        gtk_label_set_text(GTK_LABEL(menul), _("Open Image"));
                        GtkImageMenuItem *m_image = GTK_IMAGE_MENU_ITEM(menuitem);
                        g_signal_connect(G_OBJECT(m_image), "activate",
-                                                        G_CALLBACK(open_image_cb),
-                                                        (gpointer *) viewer);
+                                        G_CALLBACK(open_image_cb),
+                                        (gpointer *) viewer);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Copy Link Location" )) {
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                                       "Copy Link Location" )) {
                        gtk_label_set_text(GTK_LABEL(menul), _("Copy Link"));
                }
-        if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Download Linked File" )) {
+        if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                               "Download Linked File" )) {
                        gtk_label_set_text(GTK_LABEL(menul), _("Download Link"));
 
                        GtkImageMenuItem *m_dlink = GTK_IMAGE_MENU_ITEM(menuitem);
                        g_signal_connect(G_OBJECT(m_dlink), "activate",
-                                                        G_CALLBACK(download_file_cb),
-                                                        (gpointer *) viewer);
+                                        G_CALLBACK(download_file_cb),
+                                        (gpointer *) viewer);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Save Image As" )) {
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                                       "Save Image As" )) {
 
                        gtk_label_set_text(GTK_LABEL(menul), _("Save Image As"));
 
                        GtkImageMenuItem *m_simage = GTK_IMAGE_MENU_ITEM(menuitem);
-                       g_signal_connect(G_OBJECT(m_simage), "activate", 
-                                                        G_CALLBACK(download_file_cb), (gpointer *) viewer);
+                       g_signal_connect(G_OBJECT(m_simage), "activate",
+                                        G_CALLBACK(save_image_cb),
+                                        (gpointer *) viewer);
                }
 
-               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)), 
-                                                               "Copy Image" )) {
+               if (!g_ascii_strcasecmp(gtk_label_get_text(GTK_LABEL(menul)),
+                                       "Copy Image" )) {
                        gtk_label_set_text(GTK_LABEL(menul), _("Copy Image"));
                        GtkImageMenuItem *m_cimage = GTK_IMAGE_MENU_ITEM(menuitem);
                        g_signal_connect(G_OBJECT(m_cimage), "activate",
-                                                        G_CALLBACK(copy_image_cb),
-                                                        (gpointer *) viewer);
+                                        G_CALLBACK(copy_image_cb),
+                                        (gpointer *) viewer);
                }
 
        }
 }
 
-static gboolean populate_popup_cb (WebKitWebView *view, GtkWidget *menu, 
-                                                                  FancyViewer *viewer)
+static gboolean populate_popup_cb (WebKitWebView *view, GtkWidget *menu,
+                                  FancyViewer *viewer)
 {
        Plugin *plugin = plugin_get_loaded_by_name("RSSyl");
-       gtk_container_foreach(GTK_CONTAINER(menu), 
-                                                 (GtkCallback)viewer_menu_handler, 
-                                                 viewer);
+       gtk_container_foreach(GTK_CONTAINER(menu),
+                             (GtkCallback)viewer_menu_handler,
+                             viewer);
        if (plugin) {
                GtkWidget *rssyl = gtk_image_menu_item_new_with_label(_("Import feed"));
-               GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_ADD, 
-                                                                                                 GTK_ICON_SIZE_MENU);
+               GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
                gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(rssyl), img);
                gtk_widget_show(GTK_WIDGET(rssyl));
-               gtk_menu_shell_append(GTK_MENU_SHELL(menu), rssyl);    
+               gtk_menu_shell_append(GTK_MENU_SHELL(menu), rssyl);
                g_signal_connect(G_OBJECT(rssyl), "activate",
-                                                G_CALLBACK(import_feed_cb),
-                                                (gpointer *) viewer);
+                                G_CALLBACK(import_feed_cb),
+                                (gpointer *) viewer);
        }
        return TRUE;
 }
@@ -811,11 +827,55 @@ static gboolean release_button_cb (WebKitWebView *view, GdkEvent *ev,
                                   FancyViewer *viewer)
 {
        if (ev->button.button == 1 && viewer->cur_link && viewer->override_prefs_external) {
+#if WEBKIT_CHECK_VERSION(1,9,3)
+               /* The x and y properties were added in 1.9.3 */
+               gint x, y;
+               WebKitHitTestResult *result;
+               result = webkit_web_view_get_hit_test_result(view, (GdkEventButton *)ev);
+               g_object_get(G_OBJECT(result),
+                               "x", &x, "y", &y,
+                               NULL);
+
+               /* If this button release is end of a drag or selection event
+                * (button press happened on different coordinates), we do not
+                * want to open the link. */
+               if ((x != viewer->click_x || y != viewer->click_y))
+                       return FALSE;
+#endif
+
                open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
                return TRUE;
        }
        return FALSE;
 }
+
+static gboolean press_button_cb (WebKitWebView *view, GdkEvent *ev,
+               FancyViewer *viewer)
+{
+#if WEBKIT_CHECK_VERSION(1,5,1)
+# if WEBKIT_CHECK_VERSION(1,9,3)
+       /* The x and y properties were added in 1.9.3 */
+       gint type;
+       WebKitHitTestResult *result =
+               webkit_web_view_get_hit_test_result(view, (GdkEventButton *)ev);
+
+       g_object_get(G_OBJECT(result),
+                       "context", &type,
+                       "x", &viewer->click_x, "y", &viewer->click_y,
+                       NULL);
+# endif /* 1.9.3 */
+       if (type & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION)
+               return FALSE;
+
+       viewer->doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(viewer->view));
+       viewer->window = webkit_dom_document_get_default_view (viewer->doc);
+       viewer->selection = webkit_dom_dom_window_get_selection (viewer->window);
+       if (viewer->selection != NULL)
+               webkit_dom_dom_selection_empty(viewer->selection);
+#endif /* 1.5.1 */
+       return FALSE;
+}
+
 static void zoom_100_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer)
 {
        gtk_widget_grab_focus(widget);
@@ -837,7 +897,7 @@ static MimeViewer *fancy_viewer_create(void)
 {
        FancyViewer    *viewer;
        GtkWidget      *hbox;
-    
+
        debug_print("fancy_viewer_create\n");
 
        viewer = g_new0(FancyViewer, 1);
@@ -853,7 +913,7 @@ static MimeViewer *fancy_viewer_create(void)
        viewer->mimeviewer.scroll_one_line = fancy_scroll_one_line;
        viewer->view = WEBKIT_WEB_VIEW(webkit_web_view_new());
 
-#ifdef HAVE_LIBSOUP_GNOME    
+#ifdef HAVE_LIBSOUP_GNOME
  /* Use GNOME proxy settings through libproxy */
        if (fancy_prefs.enable_gnome_proxy) {
                SoupSession *session = webkit_get_default_session();
@@ -866,42 +926,36 @@ static MimeViewer *fancy_viewer_create(void)
                SoupURI* pURI = soup_uri_new(fancy_prefs.proxy_str);
                g_object_set(session, "proxy-uri", pURI, NULL);
        }
-    
-       viewer->settings = webkit_web_settings_new();    
+
+       viewer->settings = webkit_web_settings_new();
        g_object_set(viewer->settings, "user-agent", "Fancy Viewer", NULL);
        viewer->scrollwin = gtk_scrolled_window_new(NULL, NULL);
-       viewer->tag = -1;
-       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewer->scrollwin), 
-                                                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewer->scrollwin),
+                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(viewer->scrollwin),
-                                                                               GTK_SHADOW_IN);
+                                           GTK_SHADOW_IN);
        gtk_container_add(GTK_CONTAINER(viewer->scrollwin),
-                                         GTK_WIDGET(viewer->view));
+                         GTK_WIDGET(viewer->view));
 
        viewer->vbox = gtk_vbox_new(FALSE, 0);
        hbox = gtk_hbox_new(FALSE, 0);
        viewer->progress = gtk_progress_bar_new();
        /* Zoom Widgets */
-       viewer->zoom_100 = gtk_image_new_from_stock(GTK_STOCK_ZOOM_100,
-                                                                                               GTK_ICON_SIZE_MENU);
-       viewer->zoom_in = gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, 
-                                                                                          GTK_ICON_SIZE_MENU);
-       viewer->zoom_out = gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, 
-                                                                                               GTK_ICON_SIZE_MENU);
-       viewer->stop_loading = gtk_image_new_from_stock(GTK_STOCK_CANCEL, 
-                                                                                                       GTK_ICON_SIZE_MENU);
+       viewer->zoom_100 = gtk_image_new_from_stock(GTK_STOCK_ZOOM_100, GTK_ICON_SIZE_MENU);
+       viewer->zoom_in = gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU);
+       viewer->zoom_out = gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU);
+       viewer->stop_loading = gtk_image_new_from_stock(GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
        /* Event Widgets for the Zoom Widgets  */
        viewer->ev_zoom_100 = gtk_event_box_new();
        viewer->ev_zoom_in = gtk_event_box_new();
        viewer->ev_zoom_out = gtk_event_box_new();
        viewer->ev_stop_loading = gtk_event_box_new();
-   
+
        /* Link Label */
        viewer->l_link = gtk_label_new("");
 
        /* Preferences Widgets to override preferences on the fly  */
-       viewer->fancy_prefs = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,
-                                                                                                  GTK_ICON_SIZE_MENU);
+       viewer->fancy_prefs = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
        viewer->ev_fancy_prefs = gtk_event_box_new();
 
        /* Popup Menu for preferences  */
@@ -928,7 +982,7 @@ static MimeViewer *fancy_viewer_create(void)
        gtk_box_pack_end(GTK_BOX(hbox), viewer->progress, FALSE, FALSE, 0);
        gtk_box_pack_end(GTK_BOX(hbox), viewer->ev_stop_loading, FALSE, FALSE, 0);
 
-       gtk_box_pack_start(GTK_BOX(viewer->vbox), viewer->scrollwin, TRUE, TRUE, 
+       gtk_box_pack_start(GTK_BOX(viewer->vbox), viewer->scrollwin, TRUE, TRUE,
                        1);
        gtk_box_pack_start(GTK_BOX(viewer->vbox), hbox, FALSE, FALSE, 0);
 
@@ -949,34 +1003,36 @@ static MimeViewer *fancy_viewer_create(void)
        gtk_widget_show(hbox);
        gtk_widget_show(GTK_WIDGET(viewer->view));
 
-       g_signal_connect(G_OBJECT(viewer->view), "load-started", 
-                                        G_CALLBACK(load_start_cb), viewer);
-       g_signal_connect(G_OBJECT(viewer->view), "load-finished", 
-                                        G_CALLBACK(load_finished_cb), viewer);
-       g_signal_connect(G_OBJECT(viewer->view), "hovering-over-link", 
-                                        G_CALLBACK(over_link_cb), viewer);
-       g_signal_connect(G_OBJECT(viewer->view), "load-progress-changed", 
-                                        G_CALLBACK(load_progress_cb), viewer);
+       g_signal_connect(G_OBJECT(viewer->view), "load-started",
+                        G_CALLBACK(load_start_cb), viewer);
+       g_signal_connect(G_OBJECT(viewer->view), "load-finished",
+                        G_CALLBACK(load_finished_cb), viewer);
+       g_signal_connect(G_OBJECT(viewer->view), "hovering-over-link",
+                        G_CALLBACK(over_link_cb), viewer);
+       g_signal_connect(G_OBJECT(viewer->view), "load-progress-changed",
+                        G_CALLBACK(load_progress_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->view), "navigation-requested",
-                                        G_CALLBACK(navigation_requested_cb), viewer);
+                        G_CALLBACK(navigation_requested_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->view), "resource-request-starting",
                        G_CALLBACK(resource_request_starting_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->view), "populate-popup",
-                                        G_CALLBACK(populate_popup_cb), viewer);
+                        G_CALLBACK(populate_popup_cb), viewer);
+       g_signal_connect(G_OBJECT(viewer->view), "button-press-event",
+                        G_CALLBACK(press_button_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->view), "button-release-event",
-                                       G_CALLBACK(release_button_cb), viewer);
+                        G_CALLBACK(release_button_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->ev_zoom_100), "button-press-event",
-                                        G_CALLBACK(zoom_100_cb), (gpointer*)viewer);
+                        G_CALLBACK(zoom_100_cb), (gpointer*)viewer);
        g_signal_connect(G_OBJECT(viewer->ev_zoom_in), "button-press-event",
-                                        G_CALLBACK(zoom_in_cb), (gpointer *)viewer);
+                        G_CALLBACK(zoom_in_cb), (gpointer *)viewer);
        g_signal_connect(G_OBJECT(viewer->ev_zoom_out), "button-press-event",
-                                        G_CALLBACK(zoom_out_cb), (gpointer *)viewer);
+                        G_CALLBACK(zoom_out_cb), (gpointer *)viewer);
        g_signal_connect(G_OBJECT(viewer->ev_fancy_prefs), "button-press-event",
-                                        G_CALLBACK(fancy_prefs_cb), (gpointer *)viewer);
+                        G_CALLBACK(fancy_prefs_cb), (gpointer *)viewer);
        g_signal_connect(G_OBJECT(viewer->ev_stop_loading), "button-press-event",
-                                        G_CALLBACK(stop_loading_cb), viewer);
+                        G_CALLBACK(stop_loading_cb), viewer);
        g_signal_connect(G_OBJECT(viewer->view), "key_press_event",
-                                        G_CALLBACK(keypress_events_cb), viewer);
+                        G_CALLBACK(keypress_events_cb), viewer);
 
        viewer->filename = NULL;
        return (MimeViewer *) viewer;
@@ -994,16 +1050,19 @@ static MimeViewerFactory fancy_viewer_factory =
 gint plugin_init(gchar **error)
 {
        if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
-                                                         VERSION_NUMERIC, _("Fancy"), error))
+                                 VERSION_NUMERIC, _("Fancy"), error))
                return -1;
        gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                "fancy", NULL);
        if (!is_dir_exist(directory))
-               make_dir (directory);
+               if (make_dir (directory) < 0) {
+                       g_free(directory);
+                       return -1;
+               }
        g_free(directory);
 
        fancy_prefs_init();
-    
+
        mimeview_register_viewer_factory(&fancy_viewer_factory);
 
        return 0;
@@ -1024,12 +1083,12 @@ const gchar *plugin_name(void)
 
 const gchar *plugin_desc(void)
 {
-       return g_strdup_printf(_("This plugin renders HTML mail using the WebKit " 
-                                                  "%d.%d.%d library.\nBy default all remote content is "
-                                                  "blocked and images are not automatically loaded. Options "
-                                                  "can be found in /Configuration/Preferences/Plugins/Fancy"), 
-                                                  WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, 
-                                                  WEBKIT_MICRO_VERSION);
+       return g_strdup_printf(_("This plugin renders HTML mail using the WebKit "
+                              "%d.%d.%d library.\nBy default all remote content is "
+                              "blocked. Options "
+                              "can be found in /Configuration/Preferences/Plugins/Fancy"),
+                              WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION,
+                              WEBKIT_MICRO_VERSION);
 }
 
 const gchar *plugin_type(void)