2008-09-18 [colin] 3.5.0cvs113
[claws.git] / src / textview.c
index 07403b79fd89caaabe507e93d217b9cca35a271a..cdc84999269ab3578514390f6713fae70f2f6ae6 100644 (file)
@@ -27,9 +27,7 @@
 #include <glib/gi18n.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkscrolledwindow.h>
-#include <gtk/gtksignal.h>
+#include <gtk/gtk.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -187,45 +185,42 @@ static void textview_toggle_quote         (TextView       *textview,
                                                 ClickableText  *uri,
                                                 gboolean        expand_only);
 
-static void open_uri_cb                                (TextView       *textview,
-                                                guint           action,
-                                                void           *data);
-static void copy_uri_cb                                (TextView       *textview,
-                                                guint           action,
-                                                void           *data);
-static void add_uri_to_addrbook_cb             (TextView       *textview, 
-                                                guint           action, 
-                                                void           *data);
-static void mail_to_uri_cb                     (TextView       *textview, 
-                                                guint           action, 
-                                                void           *data);
-static void copy_mail_to_uri_cb                        (TextView       *textview,
-                                                guint           action,
-                                                void           *data);
-static void save_file_cb                       (TextView       *textview,
-                                                guint           action,
-                                                void           *data);
-static void open_image_cb                      (TextView       *textview,
-                                                guint           action,
-                                                void           *data);
-
-static GtkItemFactoryEntry textview_link_popup_entries[] = 
-{
-       {N_("/_Open with Web browser"), NULL, open_uri_cb, 0, NULL},
-       {N_("/Copy this _link"),        NULL, copy_uri_cb, 0, NULL},
+static void open_uri_cb                                (GtkAction      *action,
+                                                TextView       *textview);
+static void copy_uri_cb                                (GtkAction      *action,
+                                                TextView       *textview);
+static void add_uri_to_addrbook_cb             (GtkAction      *action,
+                                                TextView       *textview);
+static void mail_to_uri_cb                     (GtkAction      *action,
+                                                TextView       *textview);
+static void copy_mail_to_uri_cb                        (GtkAction      *action,
+                                                TextView       *textview);
+static void save_file_cb                       (GtkAction      *action,
+                                                TextView       *textview);
+static void open_image_cb                      (GtkAction      *action,
+                                                TextView       *textview);
+static void textview_show_tags(TextView *textview);
+
+static GtkActionEntry textview_link_popup_entries[] = 
+{
+       {"TextviewPopupLink",                   NULL, "TextviewPopupLink" },
+       {"TextviewPopupLink/Open",              NULL, N_("_Open in web browser"), NULL, NULL, G_CALLBACK(open_uri_cb) },
+       {"TextviewPopupLink/Copy",              NULL, N_("Copy this _link"), NULL, NULL, G_CALLBACK(copy_uri_cb) },
 };
 
-static GtkItemFactoryEntry textview_mail_popup_entries[] = 
+static GtkActionEntry textview_mail_popup_entries[] = 
 {
-       {N_("/Compose _new message"),   NULL, mail_to_uri_cb, 0, NULL},
-       {N_("/Add to _address book"),   NULL, add_uri_to_addrbook_cb, 0, NULL},
-       {N_("/Copy this add_ress"),     NULL, copy_mail_to_uri_cb, 0, NULL},
+       {"TextviewPopupMail",                   NULL, "TextviewPopupMail" },
+       {"TextviewPopupMail/Compose",           NULL, N_("Compose _new message"), NULL, NULL, G_CALLBACK(mail_to_uri_cb) },
+       {"TextviewPopupMail/AddAB",             NULL, N_("Add to _Address book"), NULL, NULL, G_CALLBACK(add_uri_to_addrbook_cb) },
+       {"TextviewPopupMail/Copy",              NULL, N_("Copy this add_ress"), NULL, NULL, G_CALLBACK(copy_mail_to_uri_cb) },
 };
 
-static GtkItemFactoryEntry textview_file_popup_entries[] = 
+static GtkActionEntry textview_file_popup_entries[] = 
 {
-       {N_("/_Open image"),            NULL, open_image_cb, 0, NULL},
-       {N_("/_Save image..."),         NULL, save_file_cb, 0, NULL},
+       {"TextviewPopupFile",                   NULL, "TextviewPopupFile" },
+       {"TextviewPopupFile/Open",              NULL, N_("_Open image"), NULL, NULL, G_CALLBACK(open_image_cb) },
+       {"TextviewPopupFile/Save",              NULL, N_("_Save image..."), NULL, NULL, G_CALLBACK(save_file_cb) },
 };
 
 static void scrolled_cb (GtkAdjustment *adj, TextView *textview)
@@ -260,10 +255,7 @@ TextView *textview_create(void)
        GtkWidget *text;
        GtkTextBuffer *buffer;
        GtkClipboard *clipboard;
-       GtkItemFactory *link_popupfactory, *mail_popupfactory, *file_popupfactory;
-       GtkWidget *link_popupmenu, *mail_popupmenu, *file_popupmenu;
        GtkAdjustment *adj;
-       gint n_entries;
 
        debug_print("Creating text view...\n");
        textview = g_new0(TextView, 1);
@@ -293,7 +285,7 @@ TextView *textview_create(void)
 
        gtk_widget_ensure_style(text);
 
-       gtk_widget_ref(scrolledwin);
+       g_object_ref(scrolledwin);
 
        gtk_container_add(GTK_CONTAINER(scrolledwin), text);
 
@@ -321,23 +313,35 @@ TextView *textview_create(void)
 
        gtk_widget_show(vbox);
 
-       n_entries = sizeof(textview_link_popup_entries) /
-               sizeof(textview_link_popup_entries[0]);
-       link_popupmenu = menu_create_items(textview_link_popup_entries, n_entries,
-                                     "<UriPopupMenu>", &link_popupfactory,
-                                     textview);
-
-       n_entries = sizeof(textview_mail_popup_entries) /
-               sizeof(textview_mail_popup_entries[0]);
-       mail_popupmenu = menu_create_items(textview_mail_popup_entries, n_entries,
-                                     "<UriPopupMenu>", &mail_popupfactory,
-                                     textview);
-
-       n_entries = sizeof(textview_file_popup_entries) /
-               sizeof(textview_file_popup_entries[0]);
-       file_popupmenu = menu_create_items(textview_file_popup_entries, n_entries,
-                                     "<FilePopupMenu>", &file_popupfactory,
-                                     textview);
+       
+       textview->link_action_group = cm_menu_create_action_group("TextviewPopupLink",
+                       textview_link_popup_entries,
+                       G_N_ELEMENTS(textview_link_popup_entries), (gpointer)textview);
+       textview->mail_action_group = cm_menu_create_action_group("TextviewPopupMail",
+                       textview_mail_popup_entries,
+                       G_N_ELEMENTS(textview_mail_popup_entries), (gpointer)textview);
+       textview->file_action_group = cm_menu_create_action_group("TextviewPopupFile",
+                       textview_file_popup_entries,
+                       G_N_ELEMENTS(textview_file_popup_entries), (gpointer)textview);
+
+       MENUITEM_ADDUI("/Menus", "TextviewPopupLink", "TextviewPopupLink", GTK_UI_MANAGER_MENU)
+       MENUITEM_ADDUI("/Menus", "TextviewPopupMail", "TextviewPopupMail", GTK_UI_MANAGER_MENU)
+       MENUITEM_ADDUI("/Menus", "TextviewPopupFile", "TextviewPopupFile", GTK_UI_MANAGER_MENU)
+
+       MENUITEM_ADDUI("/Menus/TextviewPopupLink", "Open", "TextviewPopupLink/Open", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupLink", "Copy", "TextviewPopupLink/Copy", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupMail", "Compose", "TextviewPopupMail/Compose", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupMail", "AddAB", "TextviewPopupMail/AddAB", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupMail", "Copy", "TextviewPopupMail/Copy", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupFile", "Open", "TextviewPopupFile/Open", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI("/Menus/TextviewPopupFile", "Save", "TextviewPopupFile/Save", GTK_UI_MANAGER_MENUITEM)
+
+       textview->link_popup_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
+                               gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/TextviewPopupLink")) );
+       textview->mail_popup_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
+                               gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/TextviewPopupMail")) );
+       textview->file_popup_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
+                               gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/TextviewPopupFile")) );
 
        textview->vbox               = vbox;
        textview->scrolledwin        = scrolledwin;
@@ -346,12 +350,6 @@ TextView *textview_create(void)
        textview->body_pos           = 0;
        textview->show_all_headers   = FALSE;
        textview->last_buttonpress   = GDK_NOTHING;
-       textview->link_popup_menu    = link_popupmenu;
-       textview->link_popup_factory = link_popupfactory;
-       textview->mail_popup_menu    = mail_popupmenu;
-       textview->mail_popup_factory = mail_popupfactory;
-       textview->file_popup_menu    = file_popupmenu;
-       textview->file_popup_factory = file_popupfactory;
        textview->image              = NULL;
        return textview;
 }
@@ -627,13 +625,23 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
 
        if ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_ascii_strcasecmp(mimeinfo->subtype, "rfc822")) {
                FILE *fp;
-
-               fp = g_fopen(mimeinfo->data.filename, "rb");
+               if (mimeinfo->content == MIMECONTENT_MEM)
+                       fp = str_open_as_stream(mimeinfo->data.mem);
+               else
+                       fp = g_fopen(mimeinfo->data.filename, "rb");
+               if (!fp) {
+                       FILE_OP_ERROR(mimeinfo->data.filename, "fopen");
+                       END_TIMING();
+                       return;
+               }
                fseek(fp, mimeinfo->offset, SEEK_SET);
                headers = textview_scan_header(textview, fp);
                if (headers) {
                        if (charcount > 0)
                                gtk_text_buffer_insert(buffer, &iter, "\n", 1);
+                       
+                       if (procmime_mimeinfo_parent(mimeinfo) == NULL)
+                               textview_show_tags(textview);
                        textview_show_header(textview, headers);
                        procheader_header_array_destroy(headers);
                }
@@ -753,7 +761,7 @@ static void recursive_add_parts(TextView *textview, GNode *node)
         mimeinfo = (MimeInfo *) node->data;
         
         textview_add_part(textview, mimeinfo);
-#ifdef MAEMO
+#ifdef GENERIC_UMPC
        textview_set_position(textview, 0);
 #endif        
         if ((mimeinfo->type != MIMETYPE_MULTIPART) &&
@@ -868,20 +876,20 @@ void textview_show_mime_part(TextView *textview, MimeInfo *partinfo)
                TEXTVIEW_INSERT(" (");
                TEXTVIEW_INSERT(content_type);
                TEXTVIEW_INSERT(", ");
-               TEXTVIEW_INSERT(to_human_readable(partinfo->length));
+               TEXTVIEW_INSERT(to_human_readable((goffset)partinfo->length));
                TEXTVIEW_INSERT("):\n\n");
                
                g_free(content_type);
        }
        TEXTVIEW_INSERT(_("  The following can be performed on this part\n"));
-#ifndef MAEMO
+#ifndef GENERIC_UMPC
        TEXTVIEW_INSERT(_("  by right-clicking the icon or list item:"));
 #endif
        TEXTVIEW_INSERT("\n");
 
        TEXTVIEW_INSERT(_("     - To save, select "));
        TEXTVIEW_INSERT_LINK(_("'Save as...'"), "sc://save_as", NULL);
-#ifndef MAEMO
+#ifndef GENERIC_UMPC
        TEXTVIEW_INSERT(_(" (Shortcut key: 'y')"));
 #endif
        TEXTVIEW_INSERT("\n");
@@ -889,7 +897,7 @@ void textview_show_mime_part(TextView *textview, MimeInfo *partinfo)
        TEXTVIEW_INSERT(_("     - To display as text, select "));
        TEXTVIEW_INSERT_LINK(_("'Display as text'"), "sc://display_as_text", NULL);
 
-#ifndef MAEMO
+#ifndef GENERIC_UMPC
        TEXTVIEW_INSERT(_(" (Shortcut key: 't')"));
 #endif
        TEXTVIEW_INSERT("\n");
@@ -897,7 +905,7 @@ void textview_show_mime_part(TextView *textview, MimeInfo *partinfo)
        TEXTVIEW_INSERT(_("     - To open with an external program, select "));
        TEXTVIEW_INSERT_LINK(_("'Open'"), "sc://open", NULL);
 
-#ifndef MAEMO
+#ifndef GENERIC_UMPC
        TEXTVIEW_INSERT(_(" (Shortcut key: 'l')\n"));
        TEXTVIEW_INSERT(_("       (alternately double-click, or click the middle "));
        TEXTVIEW_INSERT(_("mouse button)\n"));
@@ -917,11 +925,16 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo)
        CodeConverter *conv;
        const gchar *charset, *p, *cmd;
        GSList *cur;
-       
+       gboolean continue_write = TRUE;
+       size_t wrote = 0, i = 0;
+
        if (textview->messageview->forced_charset)
                charset = textview->messageview->forced_charset;
-       else
+       else {
                charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+               if (!strcasecmp(charset, CS_ISO_8859_1))
+                       charset = CS_WINDOWS_1252;
+       }
 
        textview_set_font(textview, charset);
 
@@ -942,7 +955,7 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo)
                        tmpfp = g_fopen(filename, "rb");
                        textview_show_html(textview, tmpfp, conv);
                        fclose(tmpfp);
-                       g_unlink(filename);
+                       claws_unlink(filename);
                }
                g_free(filename);
        } else if (!g_ascii_strcasecmp(mimeinfo->subtype, "enriched")) {
@@ -953,7 +966,7 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo)
                        tmpfp = g_fopen(filename, "rb");
                        textview_show_ertf(textview, tmpfp, conv);
                        fclose(tmpfp);
-                       g_unlink(filename);
+                       claws_unlink(filename);
                }
                g_free(filename);
 #ifndef G_OS_WIN32
@@ -1019,16 +1032,30 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo)
 #endif
        } else {
 textview_default:
-               tmpfp = g_fopen(mimeinfo->data.filename, "rb");
+               if (mimeinfo->content == MIMECONTENT_MEM)
+                       tmpfp = str_open_as_stream(mimeinfo->data.mem);
+               else
+                       tmpfp = g_fopen(mimeinfo->data.filename, "rb");
+               if (!tmpfp) {
+                       FILE_OP_ERROR(mimeinfo->data.filename, "fopen");
+                       return;
+               }
                fseek(tmpfp, mimeinfo->offset, SEEK_SET);
                debug_print("Viewing text content of type: %s (length: %d)\n", mimeinfo->subtype, mimeinfo->length);
-               while ((ftell(tmpfp) < mimeinfo->offset + mimeinfo->length) &&
-                      (fgets(buf, sizeof(buf), tmpfp) != NULL)) {
+               while (((i = ftell(tmpfp)) < mimeinfo->offset + mimeinfo->length) &&
+                      (fgets(buf, sizeof(buf), tmpfp) != NULL)
+                      && continue_write) {
                        textview_write_line(textview, buf, conv, TRUE);
                        if (textview->stop_loading) {
                                fclose(tmpfp);
                                return;
                        }
+                       wrote += ftell(tmpfp)-i;
+                       if (mimeinfo->length > 1024*1024 
+                       &&  wrote > 1024*1024
+                       && !textview->messageview->show_full_text) {
+                               continue_write = FALSE;
+                       }
                }
                fclose(tmpfp);
        }
@@ -1050,6 +1077,12 @@ textview_default:
                }
        }
        
+       if (continue_write == FALSE) {
+               messageview_show_partial_display(
+                       textview->messageview, 
+                       textview->messageview->msginfo,
+                       mimeinfo->length);
+       }
        GTK_EVENTS_FLUSH();
 }
 
@@ -2088,8 +2121,6 @@ static void textview_show_header(TextView *textview, GPtrArray *headers)
 
        g_return_if_fail(headers != NULL);
 
-       textview_show_tags(textview);
-
        for (i = 0; i < headers->len; i++) {
                header = g_ptr_array_index(headers, i);
                g_return_if_fail(header->name != NULL);
@@ -2719,6 +2750,8 @@ gboolean textview_uri_security_check(TextView *textview, ClickableText *uri)
        if (visible_str == NULL)
                return TRUE;
 
+       g_strstrip(visible_str);
+
        if (strcmp(visible_str, uri->uri) != 0 && is_uri_string(visible_str)) {
                gchar *uri_path;
                gchar *visible_uri_path;
@@ -2775,21 +2808,28 @@ static void textview_uri_list_remove_all(GSList *uri_list)
        g_slist_free(uri_list);
 }
 
-static void open_uri_cb (TextView *textview, guint action, void *data)
+static void open_uri_cb (GtkAction *action, TextView *textview)
 {
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->link_popup_menu),
                                           "menu_button");
-       if (uri == NULL)
-               return;
+       const gchar *raw_url = g_object_get_data(G_OBJECT(textview->link_popup_menu),
+                                          "raw_url");
 
-       if (textview_uri_security_check(textview, uri) == TRUE) 
-               open_uri(uri->uri,
-                        prefs_common_get_uri_cmd());
-       g_object_set_data(G_OBJECT(textview->link_popup_menu), "menu_button",
-                         NULL);
+       if (uri) {
+               if (textview_uri_security_check(textview, uri) == TRUE) 
+                       open_uri(uri->uri,
+                                prefs_common_get_uri_cmd());
+               g_object_set_data(G_OBJECT(textview->link_popup_menu), "menu_button",
+                                 NULL);
+       }
+       if (raw_url) {
+               open_uri(raw_url, prefs_common_get_uri_cmd());
+               g_object_set_data(G_OBJECT(textview->link_popup_menu), "raw_url",
+                                 NULL);
+       }
 }
 
-static void open_image_cb (TextView *textview, guint action, void *data)
+static void open_image_cb (GtkAction *action, TextView *textview)
 {
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->file_popup_menu),
                                           "menu_button");
@@ -2851,7 +2891,7 @@ static void open_image_cb (TextView *textview, guint action, void *data)
                          NULL);
 }
 
-static void save_file_cb (TextView *textview, guint action, void *data)
+static void save_file_cb (GtkAction *action, TextView *textview)
 {
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->file_popup_menu),
                                           "menu_button");
@@ -2919,20 +2959,27 @@ static void save_file_cb (TextView *textview, guint action, void *data)
                          NULL);
 }
 
-static void copy_uri_cb        (TextView *textview, guint action, void *data)
+static void copy_uri_cb        (GtkAction *action, TextView *textview)
 {
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->link_popup_menu),
                                           "menu_button");
-       if (uri == NULL)
-               return;
-
-       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), uri->uri, -1);
-       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri->uri, -1);
-       g_object_set_data(G_OBJECT(textview->link_popup_menu), "menu_button",
+       const gchar *raw_url =  g_object_get_data(G_OBJECT(textview->link_popup_menu),
+                                          "raw_url");
+       if (uri) {
+               gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), uri->uri, -1);
+               gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri->uri, -1);
+               g_object_set_data(G_OBJECT(textview->link_popup_menu), "menu_button",
                          NULL);
+       }
+       if (raw_url) {
+               gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), raw_url, -1);
+               gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), raw_url, -1);
+               g_object_set_data(G_OBJECT(textview->link_popup_menu), "raw_url",
+                         NULL);
+       }
 }
 
-static void add_uri_to_addrbook_cb (TextView *textview, guint action, void *data)
+static void add_uri_to_addrbook_cb (GtkAction *action, TextView *textview)
 {
        gchar *fromname, *fromaddress;
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->mail_popup_menu),
@@ -2978,7 +3025,7 @@ static void add_uri_to_addrbook_cb (TextView *textview, guint action, void *data
        g_free(fromname);
 }
 
-static void mail_to_uri_cb (TextView *textview, guint action, void *data)
+static void mail_to_uri_cb (GtkAction *action, TextView *textview)
 {
        PrefsAccount *account = NULL;
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->mail_popup_menu),
@@ -2993,11 +3040,14 @@ static void mail_to_uri_cb (TextView *textview, guint action, void *data)
                folder_item = textview->messageview->msginfo->folder;
                if (folder_item->prefs && folder_item->prefs->enable_default_account)
                        account = account_find_from_id(folder_item->prefs->default_account);
+               
+               compose_new_with_folderitem(account, folder_item, uri->uri+7);
+       } else {
+               compose_new(account, uri->uri + 7, NULL);
        }
-       compose_new(account, uri->uri + 7, NULL);
 }
 
-static void copy_mail_to_uri_cb        (TextView *textview, guint action, void *data)
+static void copy_mail_to_uri_cb        (GtkAction *action, TextView *textview)
 {
        ClickableText *uri = g_object_get_data(G_OBJECT(textview->mail_popup_menu),
                                           "menu_button");