2006-02-11 [colin] 2.0.0cvs43
[claws.git] / src / summaryview.c
index f92c1fae6f9fd06938a9521e1c580b24f8d62f64..a129c3cb520fb45e31bbbdb480f4be3668b105f5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws 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
@@ -176,7 +176,8 @@ static void summary_set_ctree_from_list     (SummaryView            *summaryview,
                                         GSList                 *mlist);
 static void summary_set_header         (SummaryView            *summaryview,
                                         gchar                  *text[],
-                                        MsgInfo                *msginfo);
+                                        MsgInfo                *msginfo,
+                                        gboolean               *free_from_to);
 static void summary_display_msg                (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
 static void summary_display_msg_full   (SummaryView            *summaryview,
@@ -236,9 +237,7 @@ void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
 #if 0
 void summary_processing(SummaryView *summaryview, GSList * mlist);
 #endif
-static void summary_filter_func                (GtkCTree               *ctree,
-                                        GtkCTreeNode           *node,
-                                        gpointer                data);
+static void summary_filter_func                (MsgInfo *msginfo);
 
 static void summary_colorlabel_menu_item_activate_cb
                                          (GtkWidget    *widget,
@@ -275,6 +274,10 @@ static void summary_selected               (GtkCTree               *ctree,
                                         GtkCTreeNode           *row,
                                         gint                    column,
                                         SummaryView            *summaryview);
+static void summary_unselected         (GtkCTree               *ctree,
+                                        GtkCTreeNode           *row,
+                                        gint                    column,
+                                        SummaryView            *summaryview);
 static void summary_col_resized                (GtkCList               *clist,
                                         gint                    column,
                                         gint                    width,
@@ -331,6 +334,20 @@ static void summary_drag_data_get       (GtkWidget        *widget,
                                         guint             info,
                                         guint             time,
                                         SummaryView      *summaryview);
+static void summary_drag_data_received(GtkWidget        *widget,
+                                       GdkDragContext   *drag_context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *data,
+                                       guint             info,
+                                       guint             time,
+                                       SummaryView       *summaryview);
+static gboolean summary_drag_motion_cb(GtkWidget      *widget,
+                                         GdkDragContext *context,
+                                         gint            x,
+                                         gint            y,
+                                         guint           time,
+                                         SummaryView    *summaryview);
 
 /* custom compare functions for sorting */
 
@@ -387,9 +404,10 @@ static void summary_find_answers   (SummaryView    *summaryview,
 
 static gboolean summary_update_msg     (gpointer source, gpointer data);
 
-GtkTargetEntry summary_drag_types[1] =
+GtkTargetEntry summary_drag_types[2] =
 {
-       {"text/plain", GTK_TARGET_SAME_APP, TARGET_DUMMY}
+       {"text/uri-list", 0, TARGET_MAIL_URI_LIST},
+       {"sylpheed-claws/internal", GTK_TARGET_SAME_APP, TARGET_DUMMY}
 };
 
 static GtkItemFactoryEntry summary_popup_entries[] =
@@ -523,7 +541,7 @@ SummaryView *summary_create(void)
 
        gtk_tooltips_set_tip(GTK_TOOLTIPS(search_tip),
                             toggle_search,
-                            _("Toggle quick-search bar"), NULL);
+                            _("Toggle quick search bar"), NULL);
        
        gtk_box_pack_start(GTK_BOX(hbox), toggle_search, FALSE, FALSE, 2);      
 
@@ -613,7 +631,7 @@ SummaryView *summary_create(void)
        summaryview->msginfo_update_callback_id =
                hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview);
 
-       summaryview->target_list = gtk_target_list_new(summary_drag_types, 1);
+       summaryview->target_list = gtk_target_list_new(summary_drag_types, 2);
 
        summaryview->quicksearch = quicksearch;
 
@@ -843,14 +861,14 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                gboolean changed = FALSE;
 
                val = alertpanel(_("Process mark"),
-                                _("Some marks are left. Process it?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, GTK_STOCK_CANCEL);
-               if (G_ALERTDEFAULT == val) {
+                                _("Some marks are left. Process them?"),
+                                GTK_STOCK_NO, GTK_STOCK_YES, GTK_STOCK_CANCEL);
+               if (G_ALERTALTERNATE == val) {
                        summary_unlock(summaryview);
                        summary_execute(summaryview);
                        summary_lock(summaryview);
                        changed = TRUE;
-               } else if (G_ALERTALTERNATE == val) {
+               } else if (G_ALERTDEFAULT == val) {
                        /* DO NOTHING */
                } else {
                        summary_unlock(summaryview);
@@ -1261,9 +1279,12 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
 
        summary_lock(summaryview);
        menuitem = gtk_item_factory_get_widget(ifactory, "/View/All header");
-       gtk_check_menu_item_set_active
-               (GTK_CHECK_MENU_ITEM(menuitem),
-                summaryview->messageview->mimeview->textview->show_all_headers);
+       if (summaryview->messageview 
+       &&  summaryview->messageview->mimeview
+       &&  summaryview->messageview->mimeview->textview)
+               gtk_check_menu_item_set_active
+                       (GTK_CHECK_MENU_ITEM(menuitem),
+                        summaryview->messageview->mimeview->textview->show_all_headers);
        summary_unlock(summaryview);
 }
 
@@ -1289,19 +1310,19 @@ void summary_select_prev_unread(SummaryView *summaryview)
                                val = alertpanel(_("No more unread messages"),
                                                 _("No unread message found. "
                                                   "Search from the end?"),
-                                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                               val = G_ALERTDEFAULT;
+                               val = G_ALERTALTERNATE;
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_NO:
-                               val = !G_ALERTDEFAULT;
+                               val = !G_ALERTALTERNATE;
                                break;
                        default:
                                debug_print(
                                        _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                }
-               if (val != G_ALERTDEFAULT) return;
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_UNREAD, FALSE);
        }
@@ -1341,10 +1362,10 @@ void summary_select_next_unread(SummaryView *summaryview)
                                        val = alertpanel(_("No more unread messages"),
                                                         _("No unread message found. "
                                                           "Go to next folder?"),
-                                                        GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                        GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                                       val = G_ALERTDEFAULT;
+                                       val = G_ALERTALTERNATE;
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_NO:
                                        val = G_ALERTOTHER;
@@ -1354,7 +1375,7 @@ void summary_select_next_unread(SummaryView *summaryview)
                                                _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                        }
 
-                       if (val == G_ALERTDEFAULT) {
+                       if (val == G_ALERTALTERNATE) {
                                folderview_select_next_unread(summaryview->folderview);
                                return;
                        } 
@@ -1388,19 +1409,19 @@ void summary_select_prev_new(SummaryView *summaryview)
                                val = alertpanel(_("No more new messages"),
                                                 _("No new message found. "
                                                   "Search from the end?"),
-                                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                               val = G_ALERTDEFAULT;
+                               val = G_ALERTALTERNATE;
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_NO:
-                               val = !G_ALERTDEFAULT;
+                               val = !G_ALERTALTERNATE;
                                break;
                        default:
                                debug_print(
                                        _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                }
-               if (val != G_ALERTDEFAULT) return;
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_NEW, FALSE);
        }
@@ -1440,10 +1461,10 @@ void summary_select_next_new(SummaryView *summaryview)
                                        val = alertpanel(_("No more new messages"),
                                                         _("No new message found. "
                                                           "Go to next folder?"),
-                                                        GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                        GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                                       val = G_ALERTDEFAULT;
+                                       val = G_ALERTALTERNATE;
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_NO:
                                        val = G_ALERTOTHER;
@@ -1453,7 +1474,7 @@ void summary_select_next_new(SummaryView *summaryview)
                                                _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                        }
 
-                       if (val == G_ALERTDEFAULT) {
+                       if (val == G_ALERTALTERNATE) {
                                folderview_select_next_new(summaryview->folderview);
                                return;
                        } 
@@ -1478,8 +1499,8 @@ void summary_select_prev_marked(SummaryView *summaryview)
                val = alertpanel(_("No more marked messages"),
                                 _("No marked message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_MARKED, TRUE);
        }
@@ -1503,8 +1524,8 @@ void summary_select_next_marked(SummaryView *summaryview)
                val = alertpanel(_("No more marked messages"),
                                 _("No marked message found. "
                                   "Search from the beginning?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                     MSG_MARKED, TRUE);
        }
@@ -1528,8 +1549,8 @@ void summary_select_prev_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_CLABEL_FLAG_MASK, TRUE);
        }
@@ -1553,8 +1574,8 @@ void summary_select_next_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the beginning?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                     MSG_CLABEL_FLAG_MASK, TRUE);
        }
@@ -1590,12 +1611,23 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
 
+       if (!summaryview->folder_item)
+               return;
        if (node) {
                gtkut_ctree_expand_parent_all(ctree, node);
                if (do_refresh) {
                        GTK_EVENTS_FLUSH();
                        gtk_widget_grab_focus(GTK_WIDGET(ctree));
-                       gtk_ctree_node_moveto(ctree, node, -1, 0.5, 0);
+                       if (GTK_CTREE_ROW(node) == NULL) {
+                               g_warning("crash avoidance hack 1\n");
+                               return;
+                       }
+                       if (((GtkCListRow *)(GTK_CTREE_ROW(node)))->state < GTK_STATE_NORMAL
+                       ||  ((GtkCListRow *)(GTK_CTREE_ROW(node)))->state > GTK_STATE_INSENSITIVE) {
+                               g_warning("crash avoidance hack 2\n");
+                               return;
+                       }
+                       gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0);
                }
                summary_unselect_all(summaryview);
                if (display_msg && summaryview->displayed == node)
@@ -1707,8 +1739,9 @@ static GtkCTreeNode *summary_find_next_flagged_msg(SummaryView *summaryview,
                msginfo = gtk_ctree_node_get_row_data(ctree, node);
                /* Find msg with matching flags but ignore messages with
                   ignore flags, if searching for new or unread messages */
-               if (!(((flags & (MSG_NEW | MSG_UNREAD)) != 0) && MSG_IS_IGNORE_THREAD(msginfo->flags)) && 
-                       (msginfo && (msginfo->flags.perm_flags & flags) != 0))
+               if ((msginfo && (msginfo->flags.perm_flags & flags) != 0) &&
+                   !(((flags & (MSG_NEW | MSG_UNREAD)) != 0) && MSG_IS_IGNORE_THREAD(msginfo->flags)) 
+                       )
                        break;
        }
 
@@ -1809,7 +1842,7 @@ void summary_attract_by_subject(SummaryView *summaryview)
 
        g_hash_table_destroy(subject_table);
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        gtk_clist_thaw(clist);
 
@@ -1879,8 +1912,8 @@ static void summary_status_show(SummaryView *summaryview)
        gchar *spc;
        gchar *itstr;
        GList *rowlist, *cur;
-       guint n_selected = 0;
-       off_t sel_size = 0;
+       guint n_selected = 0, n_new = 0, n_unread = 0, n_total = 0;
+       off_t sel_size = 0, n_size = 0;
        MsgInfo *msginfo;
        gchar *name;
        
@@ -1901,8 +1934,34 @@ static void summary_status_show(SummaryView *summaryview)
                else {
                        sel_size += msginfo->size;
                        n_selected++;
+                       
                }
        }
+       
+       if (summaryview->folder_item->hide_read_msgs 
+       || quicksearch_is_active(summaryview->quicksearch)) {
+               rowlist = GTK_CLIST(summaryview->ctree)->row_list;
+               for (cur = rowlist; cur != NULL && cur->data != NULL; cur = cur->next) {
+                       msginfo = gtk_ctree_node_get_row_data
+                               (GTK_CTREE(summaryview->ctree),
+                                GTK_CTREE_NODE(cur));
+                       if (!msginfo)
+                               g_warning("summary_status_show(): msginfo == NULL\n");
+                       else {
+                               n_size += msginfo->size;
+                               n_total++;
+                               if (MSG_IS_NEW(msginfo->flags))
+                                       n_new++;
+                               if (MSG_IS_UNREAD(msginfo->flags))
+                                       n_unread++;
+                       }
+               }
+       } else {
+               n_new = summaryview->folder_item->new_msgs;
+               n_unread = summaryview->folder_item->unread_msgs;
+               n_total = summaryview->folder_item->total_msgs;
+               n_size = summaryview->total_size;
+       }
 
        name = folder_item_get_name(summaryview->folder_item);
        gtk_label_set_text(GTK_LABEL(summaryview->statlabel_folder), name);
@@ -1954,10 +2013,8 @@ static void summary_status_show(SummaryView *summaryview)
 
        str = g_strdup_printf(_("%d new, %d unread, %d total (%s)"),
 
-                                     summaryview->folder_item->new_msgs,
-                                     summaryview->folder_item->unread_msgs,
-                                     summaryview->folder_item->total_msgs,
-                                     to_human_readable(summaryview->total_size));
+                                     n_new, n_unread, n_total,
+                                     to_human_readable(n_size));
        gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
        g_free(str);
 }
@@ -2164,7 +2221,7 @@ void summary_sort(SummaryView *summaryview,
 
                gtk_sctree_sort_recursive(ctree, NULL);
 
-               gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+               gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
                main_window_cursor_normal(summaryview->mainwin);
                 gtk_clist_thaw(clist);
@@ -2187,10 +2244,11 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        gint *col_pos = summaryview->col_pos;
        const gchar *msgid = msginfo->msgid;
        GHashTable *msgid_table = summaryview->msgid_table;
+       gboolean free_from_to = FALSE;
+       
+       summary_set_header(summaryview, text, msginfo, &free_from_to);
 
-       summary_set_header(summaryview, text, msginfo);
-
-       gtk_ctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
+       gtk_sctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
                                NULL, NULL, NULL, NULL, FALSE,
                                gnode->parent->parent ? TRUE : FALSE);
 #define SET_TEXT(col) \
@@ -2205,6 +2263,13 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        SET_TEXT(S_COL_TO);
        /* SET_TEXT(S_COL_SUBJECT);  already set by node info */
 
+       if (free_from_to) {
+               g_free(text[col_pos[S_COL_FROM]]);
+               g_free(text[col_pos[S_COL_TO]]);
+               text[col_pos[S_COL_FROM]] = NULL;
+               text[col_pos[S_COL_TO]] = NULL;
+       }
+
 #undef SET_TEXT
 
        GTKUT_CTREE_NODE_SET_ROW_DATA(cnode, msginfo);
@@ -2262,15 +2327,25 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                summary_thread_init(summaryview);
        } else {
                gchar *text[N_SUMMARY_COLS];
+               gboolean free_from_to = FALSE;
+               gint *col_pos = summaryview->col_pos;
+
                cur = mlist;
                for (; mlist != NULL; mlist = mlist->next) {
                        msginfo = (MsgInfo *)mlist->data;
 
-                       summary_set_header(summaryview, text, msginfo);
+                       summary_set_header(summaryview, text, msginfo, &free_from_to);
 
-                       node = gtk_ctree_insert_node
+                       node = gtk_sctree_insert_node
                                (ctree, NULL, node, text, 2,
-                                NULL, NULL, NULL, NULL, FALSE, FALSE);
+                                NULL, NULL, NULL, NULL,
+                                FALSE, FALSE);
+                       if (free_from_to) {
+                               g_free(text[col_pos[S_COL_FROM]]);
+                               g_free(text[col_pos[S_COL_TO]]);
+                               text[col_pos[S_COL_FROM]] = NULL;
+                               text[col_pos[S_COL_TO]] = NULL;
+                       }
                        GTKUT_CTREE_NODE_SET_ROW_DATA(node, msginfo);
                        summary_set_marks_func(ctree, node, summaryview);
 
@@ -2352,7 +2427,7 @@ static gchar *summary_complete_address(const gchar *addr)
 }
 
 static void summary_set_header(SummaryView *summaryview, gchar *text[],
-                              MsgInfo *msginfo)
+                              MsgInfo *msginfo, gboolean *free_from_to)
 {
        static gchar date_modified[80];
        static gchar col_score[11];
@@ -2417,12 +2492,14 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        if (!should_swap) {
                text[col_pos[S_COL_FROM]] = from_text;
                text[col_pos[S_COL_TO]] = to_text;
+               *free_from_to = FALSE;
        } else {
                gchar *tmp = NULL;
                tmp = g_strconcat("-->", to_text, NULL);
                text[col_pos[S_COL_FROM]] = tmp;
                tmp = g_strconcat("<--", from_text, NULL);
                text[col_pos[S_COL_TO]] = tmp;
+               *free_from_to = TRUE;
        }
        
        if (summaryview->simplify_subject_preg != NULL)
@@ -3214,8 +3291,8 @@ void summary_delete(SummaryView *summaryview)
 
        aval = alertpanel(_("Delete message(s)"),
                          _("Do you really want to delete selected message(s)?"),
-                         GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-       if (aval != G_ALERTDEFAULT) return;
+                         GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
+       if (aval != G_ALERTALTERNATE) return;
 
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; 
             cur = cur->next) {
@@ -3371,6 +3448,8 @@ void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
 
        END_LONG_OPERATION(summaryview);
 
+       summaryview->display_msg = prefs_common.always_show_msg;
+       
        if (prefs_common.immediate_exec) {
                summary_execute(summaryview);
        } else {
@@ -3606,8 +3685,10 @@ static void print_mimeview(MimeView *mimeview)
        ||  !mimeview->textview->text)
                alertpanel_warning(_("Cannot print: the message doesn't "
                                     "contain text."));
-       else
+       else {
+               gtk_widget_realize(mimeview->textview->text);
                gedit_print(GTK_TEXT_VIEW(mimeview->textview->text));
+       }
 }
 #endif
 
@@ -3752,7 +3833,7 @@ gboolean summary_execute(SummaryView *summaryview)
        summary_update_status(summaryview);
        summary_status_show(summaryview);
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        summary_unlock(summaryview);
        
@@ -4096,7 +4177,7 @@ void summary_expand_threads(SummaryView *summaryview)
 
        summaryview->thread_collapsed = FALSE;
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
 void summary_collapse_threads(SummaryView *summaryview)
@@ -4116,11 +4197,12 @@ void summary_collapse_threads(SummaryView *summaryview)
        
        summaryview->thread_collapsed = TRUE;
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
 void summary_filter(SummaryView *summaryview, gboolean selected_only)
 {
+       GSList *mlist = NULL, *cur_list;
        summary_lock(summaryview);
 
        folder_item_update_freeze();
@@ -4136,15 +4218,23 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
 
                for (cur = GTK_CLIST(summaryview->ctree)->selection;
                     cur != NULL && cur->data != NULL; cur = cur->next) {
-                       summary_filter_func(GTK_CTREE(summaryview->ctree),
-                                           GTK_CTREE_NODE(cur->data),
-                                           summaryview);
+                       mlist = g_slist_prepend(mlist, 
+                                procmsg_msginfo_new_ref(
+                                 GTKUT_CTREE_NODE_GET_ROW_DATA(cur->data)));
                }
+               mlist = g_slist_reverse(mlist);
        } else {
-               gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL,
-                                       GTK_CTREE_FUNC(summary_filter_func),
-                                       summaryview);
+               mlist = folder_item_get_msg_list(summaryview->folder_item);
+       }
+       for (cur_list = mlist; cur_list; cur_list = cur_list->next) {
+               summary_filter_func((MsgInfo *)cur_list->data);
+       }
+       filtering_move_and_copy_msgs(mlist);
+       for (cur_list = mlist; cur_list; cur_list = cur_list->next) {
+               procmsg_msginfo_free((MsgInfo *)cur_list->data);
        }
+       g_slist_free(mlist);
+
        gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
 
        folder_item_update_thaw();
@@ -4161,11 +4251,9 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
        summary_show(summaryview, summaryview->folder_item);
 }
 
-static void summary_filter_func(GtkCTree *ctree, GtkCTreeNode *node,
-                               gpointer data)
+static void summary_filter_func(MsgInfo *msginfo)
 {
        MailFilteringData mail_filtering_data;
-       MsgInfo *msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
 
        mail_filtering_data.msginfo = msginfo;
        if (hooks_invoke(MAIL_MANUAL_FILTERING_HOOKLIST, &mail_filtering_data))
@@ -4483,7 +4571,7 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                                     GTK_CTREE_EXPANDER_TRIANGLE);
 #endif
        gtk_ctree_set_indent(GTK_CTREE(ctree), 12);
-       g_object_set_data(G_OBJECT(ctree), "user_data", summaryview);
+       g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(ctree)->column[pos].button,
@@ -4516,6 +4604,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
 
        g_signal_connect(G_OBJECT(ctree), "tree_select_row",
                         G_CALLBACK(summary_selected), summaryview);
+       g_signal_connect(G_OBJECT(ctree), "tree_unselect_row",
+                        G_CALLBACK(summary_unselected), summaryview);
        g_signal_connect(G_OBJECT(ctree), "button_press_event",
                         G_CALLBACK(summary_button_pressed),
                         summaryview);
@@ -4543,6 +4633,18 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                         G_CALLBACK(summary_drag_data_get),
                         summaryview);
 
+       gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT,
+                         summary_drag_types, 2,
+                         GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_DEFAULT);
+
+       g_signal_connect(G_OBJECT(ctree), "drag_data_received",
+                        G_CALLBACK(summary_drag_data_received),
+                        summaryview);
+
+       g_signal_connect(G_OBJECT(ctree), "drag_motion",
+                        G_CALLBACK(summary_drag_motion_cb),
+                        summaryview);
+
        return ctree;
 }
 
@@ -4728,6 +4830,8 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        case GDK_l:
        case GDK_c:
                if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
+                       g_signal_stop_emission_by_name(G_OBJECT(widget), 
+                                       "key_press_event");
                        mimeview_pass_key_press_event(messageview->mimeview,
                                                      event);
                        break;
@@ -4798,6 +4902,17 @@ static void summary_tree_collapsed(GtkCTree *ctree, GtkCTreeNode *node,
        summary_set_row_marks(summaryview, node);
 }
 
+static void summary_unselected(GtkCTree *ctree, GtkCTreeNode *row,
+                              gint column, SummaryView *summaryview)
+{
+       if (summary_is_locked(summaryview)
+       ||  GTK_SCTREE(ctree)->selecting_range) {
+               return;
+       }
+
+       summary_status_show(summaryview);
+}
+
 static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                             gint column, SummaryView *summaryview)
 {
@@ -5076,7 +5191,24 @@ static void summary_drag_data_get(GtkWidget        *widget,
                                (ctree, GTK_CTREE_NODE(cur->data));
                        tmp2 = procmsg_get_message_file(msginfo);
                        if (!tmp2) continue;
-                       tmp1 = g_strconcat("file://", tmp2, NULL);
+                       if (msginfo->subject) {
+                               gchar *san_subject = g_strdup(msginfo->subject);
+                               gchar *dest = NULL;
+                               subst_for_filename(san_subject);
+                               dest = g_strdup_printf("%s%s%s.%d.txt",
+                                               get_tmp_dir(),
+                                               G_DIR_SEPARATOR_S,
+                                               san_subject, msginfo->msgnum);
+                               g_free(san_subject);
+                               san_subject = g_filename_from_utf8(dest, -1, NULL, NULL, NULL);
+                               g_free(dest);
+                               dest = san_subject;
+                               if (copy_file(tmp2, dest, TRUE) == 0) {
+                                       g_free(tmp2);
+                                       tmp2 = dest;
+                               }
+                       } 
+                       tmp1 = g_strconcat("file://", tmp2, "\r\n", NULL);
                        g_free(tmp2);
 
                        if (!mail_list) {
@@ -5104,6 +5236,54 @@ static void summary_drag_data_get(GtkWidget        *widget,
        }
 }
 
+static gboolean summary_drag_motion_cb(GtkWidget      *widget,
+                                         GdkDragContext *context,
+                                         gint            x,
+                                         gint            y,
+                                         guint           time,
+                                         SummaryView    *summaryview)
+{
+       FolderItem *item = summaryview->folder_item;
+       if (!(item && item->folder && folder_item_parent(item) != NULL
+                   && FOLDER_CLASS(item->folder)->add_msg != NULL)) {
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else if (gtk_drag_get_source_widget(context) ==
+               mainwindow_get_mainwindow()->folderview->ctree) {
+               /* no folders */
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else if (gtk_drag_get_source_widget(context) ==
+               summaryview->ctree) {
+               /* not from same folder */
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else {
+               gdk_drag_status(context, GDK_ACTION_COPY, time);
+               return TRUE;
+       }
+}
+
+static void summary_drag_data_received(GtkWidget        *widget,
+                                       GdkDragContext   *drag_context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *data,
+                                       guint             info,
+                                       guint             time,
+                                       SummaryView       *summaryview)
+{
+       if (info == TARGET_MAIL_URI_LIST) {
+               FolderItem *item = summaryview->folder_item;
+               if (!item) {
+                       gtk_drag_finish(drag_context, FALSE, FALSE, time);                      
+                       return;
+               } else {
+                       folderview_finish_dnd(data->data, drag_context, time, item);
+               }
+       }
+}
+
 
 /* custom compare functions for sorting */
 
@@ -5368,65 +5548,6 @@ void summary_toggle_ignore_thread(SummaryView *summaryview)
                summary_ignore_thread(summaryview);
 }
 
-#if 0 /* OLD PROCESSING */
-static gboolean processing_apply_func(GNode *node, gpointer data)
-{
-       FolderItem *item;
-       GSList * processing;
-       SummaryView * summaryview = (SummaryView *) data;
-       
-       if (node == NULL)
-               return FALSE;
-
-       item = node->data;
-       /* prevent from the warning */
-       if (item->path == NULL)
-               return FALSE;
-       processing = item->prefs->processing;
-
-
-       if (processing != NULL) {
-               gchar * buf;
-               GSList * mlist;
-               GSList * cur;
-
-               buf = g_strdup_printf(_("Processing (%s)..."), item->path);
-               debug_print(buf);
-               STATUSBAR_PUSH(summaryview->mainwin, buf);
-               g_free(buf);
-
-               mlist = folder_item_get_msg_list(item);
-               for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = cur->next) {
-                       MsgInfo * msginfo;
-                       
-                       msginfo = (MsgInfo *) cur->data;
-                       filter_message_by_msginfo(processing, msginfo, NULL);
-                       procmsg_msginfo_free(msginfo);
-               }
-
-               g_slist_free(mlist);
-               
-               STATUSBAR_POP(summaryview->mainwin);
-       }
-
-
-       return FALSE;
-}
-
-void processing_apply(SummaryView * summaryview)
-{
-       GList * cur;
-
-       for (cur = folder_get_list() ; cur != NULL && cur->data != NULL ; cur = g_list_next(cur)) {
-               Folder *folder;
-
-               folder = (Folder *) cur->data;
-               g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
-                               processing_apply_func, summaryview);
-       }
-}
-#endif
-
 void summary_toggle_show_read_messages(SummaryView *summaryview)
 {
        FolderItemUpdateData source;
@@ -5437,6 +5558,7 @@ void summary_toggle_show_read_messages(SummaryView *summaryview)
 
        source.item = summaryview->folder_item;
        source.update_flags = F_ITEM_UPDATE_NAME;
+       source.msg = NULL;
        hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source);
        summary_show(summaryview, summaryview->folder_item);
 }