2007-07-14 [colin] 2.10.0cvs27
[claws.git] / src / mimeview.c
index 5ce0421a90285ab270a0f9b4b3eef521db8a497f..fcd27e9b187cfe190481a60d782cc005b0c35193 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto 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 2 of the License, or
+ * 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,
@@ -13,8 +13,8 @@
  * 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 to the 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/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -85,7 +85,7 @@ static void mimeview_show_message_part                (MimeView       *mimeview,
                                                 MimeInfo       *partinfo);
 static void mimeview_change_view_type          (MimeView       *mimeview,
                                                 MimeViewType    type);
-gchar *mimeview_get_filename_for_part          (MimeInfo       *partinfo,
+static gchar *mimeview_get_filename_for_part           (MimeInfo       *partinfo,
                                                 const gchar    *basedir,
                                                 gint            number);
 static gboolean mimeview_write_part            (const gchar    *filename,
@@ -125,6 +125,7 @@ static void mimeview_open_with              (MimeView       *mimeview);
 static void mimeview_open_part_with    (MimeView       *mimeview,
                                         MimeInfo       *partinfo,
                                         gboolean        automatic);
+static void mimeview_select_next_part  (MimeView       *mimeview);
 static void mimeview_view_file         (const gchar    *filename,
                                         MimeInfo       *partinfo,
                                         const gchar    *cmd,
@@ -165,11 +166,12 @@ static void mimeview_launch_cb(MimeView *mimeview)
 }
 static GtkItemFactoryEntry mimeview_popup_entries[] =
 {
-       {N_("/_Open"),            NULL, mimeview_launch_cb,       0, NULL},
-       {N_("/Open _with..."),    NULL, mimeview_open_with,       0, NULL},
-       {N_("/_Display as text"), NULL, mimeview_display_as_text, 0, NULL},
-       {N_("/_Save as..."),      NULL, mimeview_save_as,         0, NULL},
-       {N_("/Save _all..."),     NULL, mimeview_save_all,        0, NULL},
+       {N_("/_Open (l)"),                NULL, mimeview_launch_cb,       0, NULL},
+       {N_("/Open _with (o)..."),        NULL, mimeview_open_with,       0, NULL},
+       {N_("/_Display as text (t)"),     NULL, mimeview_display_as_text, 0, NULL},
+       {N_("/_Save as (y)..."),          NULL, mimeview_save_as,         0, NULL},
+       {N_("/Save _all..."),             NULL, mimeview_save_all,        0, NULL},
+       {N_("/Next part (a)"),            NULL, mimeview_select_next_part,0, NULL},
 };
 
 static GtkTargetEntry mimeview_mime_types[] =
@@ -283,7 +285,6 @@ MimeView *mimeview_create(MainWindow *mainwin)
        popupmenu = menu_create_items(mimeview_popup_entries, n_entries,
                                      "<MimeView>", &popupfactory, mimeview);
        tooltips = gtk_tooltips_new();
-       gtk_tooltips_set_delay(tooltips, 0); 
 
        vbox = gtk_vbox_new(FALSE, 0);
        gtk_widget_show(vbox);
@@ -305,7 +306,9 @@ MimeView *mimeview_create(MainWindow *mainwin)
 
        gtk_widget_show(hbox);
        gtk_widget_hide(ctree_mainbox);
-
+#ifdef MAEMO
+       gtk_widget_set_size_request(mime_toggle, -1, arrow->requisition.height + 8);
+#endif
        mimeview->hbox          = hbox;
        mimeview->paned         = paned;
        mimeview->scrolledwin   = scrolledwin;
@@ -340,6 +343,17 @@ void mimeview_init(MimeView *mimeview)
                GTK_WIDGET_PTR(mimeview->textview));
 }
 
+static gboolean any_part_is_signed(MimeInfo *mimeinfo)
+{
+       while (mimeinfo) {
+               if (privacy_mimeinfo_is_signed(mimeinfo))
+                       return TRUE;
+               mimeinfo = procmime_mimeinfo_next(mimeinfo);
+       }
+
+       return FALSE;
+}
+
 void mimeview_show_message(MimeView *mimeview, MimeInfo *mimeinfo,
                           const gchar *file)
 {
@@ -358,7 +372,13 @@ void mimeview_show_message(MimeView *mimeview, MimeInfo *mimeinfo,
        g_signal_handlers_block_by_func(G_OBJECT(ctree), mimeview_selected,
                                        mimeview);
 
+       /* check if the mail's signed - it can change the mail structure */
+       
+       if (any_part_is_signed(mimeinfo))
+               debug_print("signed mail\n");
+
        mimeview_set_multipart_tree(mimeview, mimeinfo, NULL);
+       icon_list_clear(mimeview);
        icon_list_create(mimeview, mimeinfo);
 
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
@@ -428,6 +448,28 @@ MimeInfo *mimeview_get_selected_part(MimeView *mimeview)
                (GTK_CTREE(mimeview->ctree), mimeview->opened);
 }
 
+gint mimeview_get_selected_part_num(MimeView *mimeview)
+{
+       gint i = 0;
+       GList *rows = GTK_CLIST(mimeview->ctree)->row_list;
+       while (rows) {
+               if (mimeview->opened == GTK_CTREE_NODE(rows))
+                       return i;
+               i++;
+               rows = rows->next;
+       }
+       return -1;
+}
+
+void mimeview_select_part_num(MimeView *mimeview, gint i)
+{
+       if (i < 0)
+               return;
+       gtk_clist_unselect_all(GTK_CLIST(mimeview->ctree));
+       gtk_clist_select_row(GTK_CLIST(mimeview->ctree), i, -1);
+       gtkut_clist_set_focus_row(GTK_CLIST(mimeview->ctree), i);
+}
+
 static void mimeview_set_multipart_tree(MimeView *mimeview,
                                        MimeInfo *mimeinfo,
                                        GtkCTreeNode *parent)
@@ -1159,18 +1201,18 @@ static gboolean part_button_pressed(MimeView *mimeview, GdkEventButton *event,
                                 partinfo->type == MIMETYPE_IMAGE ||
                                 partinfo->type == MIMETYPE_MULTIPART))
                        menu_set_sensitive(mimeview->popupfactory,
-                                          "/Display as text", FALSE);
+                                          "/Display as text (t)", FALSE);
                else
                        menu_set_sensitive(mimeview->popupfactory,
-                                          "/Display as text", TRUE);
+                                          "/Display as text (t)", TRUE);
                if (partinfo &&
                    partinfo->type == MIMETYPE_APPLICATION &&
                    !g_ascii_strcasecmp(partinfo->subtype, "octet-stream"))
                        menu_set_sensitive(mimeview->popupfactory,
-                                          "/Open", FALSE);
+                                          "/Open (l)", FALSE);
                else
                        menu_set_sensitive(mimeview->popupfactory,
-                                          "/Open", TRUE);
+                                          "/Open (l)", TRUE);
 
                g_object_set_data(G_OBJECT(mimeview->popupmenu),
                                  "pop_partinfo", partinfo);
@@ -1192,6 +1234,44 @@ void mimeview_pass_key_press_event(MimeView *mimeview, GdkEventKey *event)
        mimeview_key_pressed(mimeview->ctree, event, mimeview);
 }
 
+static void mimeview_select_next_part(MimeView *mimeview)
+{
+       gboolean is_next = FALSE;
+
+       GList *child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
+       for (; child != NULL; child = g_list_next(child)) {
+               if (GTK_IS_TOGGLE_BUTTON(child->data) &&  
+                   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data))) {
+                       is_next = TRUE;
+               } else if (GTK_IS_TOGGLE_BUTTON(child->data) &&
+                          is_next) {
+                       toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
+                       gtk_toggle_button_set_active
+                               (GTK_TOGGLE_BUTTON(child->data), TRUE);
+                       icon_selected(mimeview, -1, 
+                               (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
+                                     "partinfo"));
+                       is_next = FALSE;
+                       break;
+               }
+       }
+       if (is_next) {
+               /* we were on the last one, go to first */
+               child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
+               for (; child != NULL; child = g_list_next(child)) {
+                       if (GTK_IS_TOGGLE_BUTTON(child->data)) {
+                               toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
+                               gtk_toggle_button_set_active
+                                       (GTK_TOGGLE_BUTTON(child->data), TRUE);
+                               icon_selected(mimeview, -1, 
+                                       (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
+                                               "partinfo"));
+                               break;
+                       }
+               }
+       }
+}
+
 #define BREAK_ON_MODIFIER_KEY() \
        if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0) break
 
@@ -1230,6 +1310,7 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                mimeview_scroll_page(mimeview, TRUE);
                return TRUE;
        case GDK_Return:
+       case GDK_KP_Enter:
                mimeview_scroll_one_line(mimeview,
                                         (event->state & GDK_MOD1_MASK) != 0);
                return TRUE;
@@ -1274,6 +1355,11 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                KEY_PRESS_EVENT_STOP();
                mimeview_check_signature(mimeview);
                return TRUE;
+       case GDK_a:
+               BREAK_ON_MODIFIER_KEY();
+               KEY_PRESS_EVENT_STOP();
+               mimeview_select_next_part(mimeview);
+               return TRUE;
        default:
                break;
        }
@@ -1293,6 +1379,7 @@ static void mimeview_drag_data_get(GtkWidget          *widget,
 {
        gchar *filename = NULL, *uriname, *tmp;
        MimeInfo *partinfo;
+       gint err;
 
        if (!mimeview->opened) return;
        if (!mimeview->file) return;
@@ -1331,10 +1418,14 @@ static void mimeview_drag_data_get(GtkWidget        *widget,
        }
        if (filename == NULL)
                filename = g_path_get_basename("Unnamed part");
-               
 
-       tmp = g_filename_from_utf8(filename, -1, NULL, NULL, NULL);
-       
+       if (!g_utf8_validate(filename, -1, NULL))
+               tmp = conv_codeset_strdup(filename,
+                               conv_get_locale_charset_str(),
+                               CS_UTF_8);
+       else
+               tmp = g_strdup(filename);
+
        if (tmp == NULL) {
                g_warning("filename not in UTF-8");
                tmp = g_strdup("Unnamed part");
@@ -1344,9 +1435,11 @@ static void mimeview_drag_data_get(GtkWidget         *widget,
 
        g_free(tmp);
 
-       if (procmime_get_part(filename, partinfo) < 0)
+       if ((err = procmime_get_part(filename, partinfo)) < 0)
                alertpanel_error
-                       (_("Couldn't save the part of multipart message."));
+                       (_("Couldn't save the part of multipart message: %s"), 
+                               strerror(-err));
+
        uriname = g_strconcat("file://", filename, "\r\n", NULL);
 
        gtk_selection_data_set(selection_data, selection_data->target, 8,
@@ -1362,7 +1455,7 @@ static void mimeview_drag_data_get(GtkWidget          *widget,
  * \param basedir The target directory
  * \param number Used for dummy filename if attachment is unnamed
  */
-gchar *mimeview_get_filename_for_part(MimeInfo *partinfo,
+static gchar *mimeview_get_filename_for_part(MimeInfo *partinfo,
                                      const gchar *basedir,
                                      gint number)
 {
@@ -1400,7 +1493,8 @@ static gboolean mimeview_write_part(const gchar *filename,
                                    MimeInfo *partinfo)
 {
        gchar *dir;
-       
+       gint err;
+
        dir= g_path_get_dirname(filename);
        if (!is_dir_exist(dir))
                make_dir_hier(dir);
@@ -1425,9 +1519,10 @@ static gboolean mimeview_write_part(const gchar *filename,
                if (G_ALERTALTERNATE != aval) return FALSE;
        }
 
-       if (procmime_get_part(filename, partinfo) < 0) {
+       if ((err = procmime_get_part(filename, partinfo)) < 0) {
                alertpanel_error
-                       (_("Couldn't save the part of multipart message."));
+                       (_("Couldn't save the part of multipart message: %s"), 
+                               strerror(-err));
                return FALSE;
        }
 
@@ -1450,9 +1545,11 @@ static void mimeview_save_all(MimeView *mimeview)
        if (!mimeview->mimeinfo) return;
 
        partinfo = mimeview->mimeinfo;
-       if (prefs_common.attach_save_dir)
+       if (prefs_common.attach_save_dir && *prefs_common.attach_save_dir)
                startdir = g_strconcat(prefs_common.attach_save_dir,
                                       G_DIR_SEPARATOR_S, NULL);
+       else
+               startdir = g_strdup(get_home_dir());
 
        dirname = filesel_select_file_save_folder(_("Select destination folder"), startdir);
        if (!dirname) {
@@ -1495,7 +1592,8 @@ static void mimeview_save_all(MimeView *mimeview)
 
        g_free(prefs_common.attach_save_dir);
        g_free(startdir);
-       prefs_common.attach_save_dir = g_strdup(dirname);
+       prefs_common.attach_save_dir = g_filename_to_utf8(dirname,
+                                       -1, NULL, NULL, NULL);
 }
 
 static MimeInfo *mimeview_get_part_to_use(MimeView *mimeview)
@@ -1543,8 +1641,15 @@ static void mimeview_save_as(MimeView *mimeview)
        
        if (!g_utf8_validate(partname, -1, NULL)) {
                gchar *tmp = conv_filename_to_utf8(partname);
-               g_free(partname);
-               partname = tmp;
+               if (!tmp) {
+                       tmp = conv_codeset_strdup(partname,
+                               conv_get_locale_charset_str(),
+                               CS_UTF_8);
+               }
+               if (tmp) {
+                       g_free(partname);
+                       partname = tmp;
+               }
        }
 
        subst_for_filename(partname);
@@ -1568,7 +1673,7 @@ static void mimeview_save_as(MimeView *mimeview)
        filedir = g_path_get_dirname(filename);
        if (filedir && strcmp(filedir, ".")) {
                g_free(prefs_common.attach_save_dir);
-               prefs_common.attach_save_dir = g_strdup(filedir);
+               prefs_common.attach_save_dir = g_filename_to_utf8(filedir, -1, NULL, NULL, NULL);
        }
 
        g_free(filedir);
@@ -1590,6 +1695,7 @@ static void mimeview_display_as_text(MimeView *mimeview)
 static void mimeview_launch(MimeView *mimeview, MimeInfo *partinfo)
 {
        gchar *filename;
+       gint err;
 
        if (!mimeview->opened) return;
        if (!mimeview->file) return;
@@ -1601,9 +1707,10 @@ static void mimeview_launch(MimeView *mimeview, MimeInfo *partinfo)
 
        filename = procmime_get_tmp_file_name(partinfo);
 
-       if (procmime_get_part(filename, partinfo) < 0)
+       if ((err = procmime_get_part(filename, partinfo)) < 0)
                alertpanel_error
-                       (_("Couldn't save the part of multipart message."));
+                       (_("Couldn't save the part of multipart message: %s"), 
+                               strerror(-err));
        else
                mimeview_view_file(filename, partinfo, NULL, mimeview);
 
@@ -1629,14 +1736,15 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
        gchar *cmd;
        gchar *mime_command = NULL;
        gchar *content_type = NULL;
-
+       gint err;
        g_return_if_fail(partinfo != NULL);
 
        filename = procmime_get_tmp_file_name(partinfo);
 
-       if (procmime_get_part(filename, partinfo) < 0) {
+       if ((err = procmime_get_part(filename, partinfo)) < 0) {
                alertpanel_error
-                       (_("Couldn't save the part of multipart message."));
+                       (_("Couldn't save the part of multipart message: %s"), 
+                               strerror(-err));
                g_free(filename);
                return;
        }
@@ -1791,6 +1899,7 @@ static void icon_selected (MimeView *mimeview, gint num, MimeInfo *partinfo)
 {
        GtkCTreeNode *node;
        node = gtk_ctree_find_by_row_data(GTK_CTREE(mimeview->ctree), NULL, partinfo);
+
        if (node)
                gtk_ctree_select(GTK_CTREE(mimeview->ctree), node);
 }              
@@ -1842,6 +1951,7 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
                mimeview_scroll_page(mimeview, TRUE);
                return TRUE;
        case GDK_Return:
+       case GDK_KP_Enter:
                if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
                        KEY_PRESS_EVENT_STOP();
                        mimeview_scroll_one_line(mimeview,
@@ -1896,6 +2006,11 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
                KEY_PRESS_EVENT_STOP();
                mimeview_check_signature(mimeview);
                return TRUE;
+       case GDK_a:
+               BREAK_ON_MODIFIER_KEY();
+               KEY_PRESS_EVENT_STOP();
+               mimeview_select_next_part(mimeview);
+               return TRUE;
        default:
                break;
        }
@@ -1920,6 +2035,19 @@ static void toggle_icon(GtkToggleButton *button, MimeView *mimeview)
        }
 }
 
+static gboolean icon_popup_menu(GtkWidget *widget, gpointer data)
+{
+       MimeView *mimeview = (MimeView *)data;
+       MimeInfo *partinfo = g_object_get_data(G_OBJECT(widget), "partinfo");
+
+       g_object_set_data(G_OBJECT(mimeview->popupmenu),
+                         "pop_partinfo", partinfo);
+       gtk_menu_popup(GTK_MENU(mimeview->popupmenu),
+                      NULL, NULL, NULL, NULL,
+                      0, gtk_get_current_event_time());
+       return TRUE;
+}
+
 static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo) 
 {
        GtkWidget *pixmap = NULL;
@@ -1943,7 +2071,7 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                          GINT_TO_POINTER(mimeview->icon_count));
        g_object_set_data(G_OBJECT(button), "partinfo", 
                          mimeinfo);
-       
+
        switch (mimeinfo->type) {
                
        case MIMETYPE_TEXT:
@@ -1951,6 +2079,8 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                        stockp = STOCK_PIXMAP_MIME_TEXT_HTML;
                else if  (mimeinfo->subtype && !g_ascii_strcasecmp(mimeinfo->subtype, "enriched"))
                        stockp = STOCK_PIXMAP_MIME_TEXT_ENRICHED;
+               else if  (mimeinfo->subtype && !g_ascii_strcasecmp(mimeinfo->subtype, "calendar"))
+                       stockp = STOCK_PIXMAP_MIME_TEXT_CALENDAR;
                else
                        stockp = STOCK_PIXMAP_MIME_TEXT_PLAIN;
                break;
@@ -1958,7 +2088,14 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                stockp = STOCK_PIXMAP_MIME_MESSAGE;
                break;
        case MIMETYPE_APPLICATION:
-               stockp = STOCK_PIXMAP_MIME_APPLICATION;
+               if (mimeinfo->subtype && !g_ascii_strcasecmp(mimeinfo->subtype, "pgp-signature"))
+                       stockp = STOCK_PIXMAP_MIME_PGP_SIG;
+               else if (mimeinfo->subtype && !g_ascii_strcasecmp(mimeinfo->subtype, "pdf"))
+                       stockp = STOCK_PIXMAP_MIME_PDF;
+               else if  (mimeinfo->subtype && !g_ascii_strcasecmp(mimeinfo->subtype, "postscript"))
+                       stockp = STOCK_PIXMAP_MIME_PS;
+               else
+                       stockp = STOCK_PIXMAP_MIME_APPLICATION;
                break;
        case MIMETYPE_IMAGE:
                stockp = STOCK_PIXMAP_MIME_IMAGE;
@@ -2014,7 +2151,6 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                                                          OVERLAY_NONE, 6, 3);
        }
        gtk_container_add(GTK_CONTAINER(button), pixmap);
-       
        if (!desc) {
                if (prefs_common.attach_desc)
                        desc = get_part_description(mimeinfo);
@@ -2052,6 +2188,15 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
        gtk_widget_show_all(button);
        gtk_drag_source_set(button, GDK_BUTTON1_MASK|GDK_BUTTON3_MASK, 
                            mimeview_mime_types, 1, GDK_ACTION_COPY);
+#ifndef MAEMO
+       g_signal_connect(G_OBJECT(button), "popup-menu",
+                        G_CALLBACK(icon_popup_menu), mimeview);
+#else
+       gtk_widget_tap_and_hold_setup(GTK_WIDGET(button), NULL, NULL,
+                       GTK_TAP_AND_HOLD_NONE | GTK_TAP_AND_HOLD_NO_INTERNALS);
+       g_signal_connect(G_OBJECT(button), "tap-and-hold",
+                        G_CALLBACK(icon_popup_menu), mimeview);
+#endif
        g_signal_connect(G_OBJECT(button), "button_release_event", 
                         G_CALLBACK(icon_clicked_cb), mimeview);
        g_signal_connect(G_OBJECT(button), "key_press_event", 
@@ -2059,6 +2204,10 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
        g_signal_connect(G_OBJECT(button), "drag_data_get",
                         G_CALLBACK(mimeview_drag_data_get), mimeview);
        gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+#ifdef MAEMO
+       gtk_widget_set_size_request(vbox, -1, pixmap->requisition.height + 8);
+       gtk_widget_set_size_request(button, -1, pixmap->requisition.height + 4);
+#endif
 
 }
 
@@ -2066,7 +2215,7 @@ static void icon_list_clear (MimeView *mimeview)
 {
        GList     *child;
        GtkAdjustment *adj;
-       
+               
        child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
        for (; child != NULL; child = g_list_next(child)) {
                gtkut_container_remove(GTK_CONTAINER(mimeview->icon_vbox), 
@@ -2091,7 +2240,7 @@ static void icon_list_toggle_by_mime_info(MimeView        *mimeview,
                                      "partinfo") == (gpointer)mimeinfo) {
                        toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
                        gtk_toggle_button_set_active
-                               (GTK_TOGGLE_BUTTON(child->data), TRUE);
+                               (GTK_TOGGLE_BUTTON(child->data), TRUE); 
                }                                
        }
 }
@@ -2167,7 +2316,6 @@ static void icon_list_create(MimeView *mimeview, MimeInfo *mimeinfo)
                gtk_widget_set_size_request(mimeview->icon_mainbox, 
                                            size.width, -1);
        }
-
 }
 
 static void mime_toggle_button_cb (GtkWidget *button, MimeView *mimeview) 
@@ -2255,6 +2403,15 @@ void mimeview_handle_cmd(MimeView *mimeview, const gchar *cmd, GdkEventButton *e
        } else if (!strcmp(cmd, "sc://menu_attachment") && data != NULL) {
                mimeview->spec_part = (MimeInfo *)data;
                part_button_pressed(mimeview, event, (MimeInfo *)data);
+       } else if (!strncmp(cmd, "sc://search_tags:", strlen("sc://search_tags:"))) {
+               const gchar *tagname = cmd + strlen("sc://search_tags:");
+               gchar *buf = g_strdup_printf("tag matchcase \"%s\"", tagname);
+               gtk_toggle_button_set_active(
+                               GTK_TOGGLE_BUTTON(mimeview->messageview->mainwin->summaryview->toggle_search), 
+                               TRUE);
+               quicksearch_set(mimeview->messageview->mainwin->summaryview->quicksearch, 
+                               QUICK_SEARCH_EXTENDED, buf);
+               g_free(buf);
        }
 }