2006-07-31 [wwp] 2.4.0cvs3
[claws.git] / src / summaryview.c
index 96a20e0988590406091c896b6c19db04a3a7aab8..7c11a321075653eed317186556a72804656c1033 100644 (file)
@@ -88,6 +88,7 @@
 #include "timing.h"
 #include "gedit-print.h"
 #include "log.h"
+#include "manual.h"
 
 #define SUMMARY_COL_MARK_WIDTH         10
 #define SUMMARY_COL_STATUS_WIDTH       13
@@ -498,6 +499,8 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        gtk_clist_freeze(GTK_CLIST(summaryview->ctree));        \
        folder_item_update_freeze();                            \
        inc_lock();                                             \
+       hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,          \
+                     summaryview->msginfo_update_callback_id); \
 }
 #define END_LONG_OPERATION(summaryview) {                      \
        inc_unlock();                                           \
@@ -505,6 +508,9 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        gtk_clist_thaw(GTK_CLIST(summaryview->ctree));          \
        main_window_cursor_normal(summaryview->mainwin);        \
        summary_unlock(summaryview);                            \
+       summaryview->msginfo_update_callback_id =               \
+               hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,    \
+               summary_update_msg, (gpointer) summaryview);    \
 }
 
 SummaryView *summary_create(void)
@@ -823,6 +829,17 @@ static void summary_switch_from_to(SummaryView *summaryview, FolderItem *item)
        summary_set_column_titles(summaryview);
 }
 
+static gboolean summaryview_quicksearch_recurse(gpointer data)
+{
+       SummaryView *summaryview = (SummaryView *)data;
+       main_window_cursor_wait(summaryview->mainwin);
+       quicksearch_reset_cur_folder_item(summaryview->quicksearch);
+       quicksearch_search_subfolders(summaryview->quicksearch, 
+                             summaryview->folderview,
+                             summaryview->folder_item);
+       main_window_cursor_normal(summaryview->mainwin);
+       return FALSE;
+}
 gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
@@ -995,17 +1012,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                statusbar_pop_all();
                
                hidden_removed = TRUE;
-               if (quicksearch_is_running(summaryview->quicksearch)) {
-                       /* only scan subfolders when quicksearch changed,
-                        * not when search is the same and folder changed */
-                       main_window_cursor_wait(summaryview->mainwin);
-                       quicksearch_reset_cur_folder_item(summaryview->quicksearch);
-                       quicksearch_search_subfolders(summaryview->quicksearch, 
-                                             summaryview->folderview,
-                                             summaryview->folder_item);
-                       main_window_cursor_normal(summaryview->mainwin);
-               }
-
                if (!quicksearch_is_active(summaryview->quicksearch)) {
                        debug_print("search cancelled!\n");
                        gtk_clist_thaw(GTK_CLIST(ctree));
@@ -1021,6 +1027,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        }
 
        if (!hidden_removed) {
+               START_TIMING("removing hidden");
                not_killed = NULL;
                for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
@@ -1032,6 +1039,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                }
                g_slist_free(mlist);
                mlist = not_killed;
+               END_TIMING();
        }
 
        STATUSBAR_POP(summaryview->mainwin);
@@ -1042,6 +1050,13 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        g_slist_free(mlist);
 
+       if (quicksearch_is_active(summaryview->quicksearch) &&
+           quicksearch_is_running(summaryview->quicksearch)) {
+               /* only scan subfolders when quicksearch changed,
+                * not when search is the same and folder changed */
+               g_timeout_add(100, summaryview_quicksearch_recurse, summaryview);
+       }
+
        if (is_refresh) {
                summaryview->displayed =
                        summary_find_msg_by_msgnum(summaryview,
@@ -1599,27 +1614,56 @@ void summary_select_prev_marked(SummaryView *summaryview)
 
 void summary_select_next_marked(SummaryView *summaryview)
 {
-       GtkCTreeNode *node;
+       GtkCTreeNode *node = summaryview->selected;
+       gboolean skip_cur = FALSE;
+       
+       if (summaryview->displayed 
+       &&  summaryview->selected == summaryview->displayed) {
+               debug_print("skipping cur (%p %p)\n",
+                       summaryview->displayed, summaryview->selected);
+               skip_cur = TRUE;
+       }
+
 
        node = summary_find_next_flagged_msg
-               (summaryview, summaryview->selected, MSG_MARKED, TRUE);
+               (summaryview, node, MSG_MARKED, skip_cur);
+       
+       if (node)
+               summary_select_node(summaryview, node, TRUE, FALSE);
+       else {
+               node = summary_find_next_flagged_msg
+                       (summaryview, NULL, MSG_MARKED, FALSE);
+               if (node == NULL || node == summaryview->selected) {
+                       AlertValue val = 0;
 
-       if (!node) {
-               AlertValue val;
+                       switch (prefs_common.next_unread_msg_dialog) {
+                               case NEXTUNREADMSGDIALOG_ALWAYS:
+                                       val = alertpanel(_("No more marked messages"),
+                                                        _("No marked message found. "
+                                                          "Go to next folder?"),
+                                                        GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                       break;
+                               case NEXTUNREADMSGDIALOG_ASSUME_YES:
+                                       val = G_ALERTALTERNATE;
+                                       break;
+                               case NEXTUNREADMSGDIALOG_ASSUME_NO:
+                                       val = G_ALERTOTHER;
+                                       break;
+                               default:
+                                       debug_print(
+                                               _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
+                       }
 
-               val = alertpanel(_("No more marked messages"),
-                                _("No marked message found. "
-                                  "Search from the beginning?"),
-                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
-               if (val != G_ALERTALTERNATE) return;
-               node = summary_find_next_flagged_msg(summaryview, NULL,
-                                                    MSG_MARKED, TRUE);
-       }
+                       if (val == G_ALERTALTERNATE) {
+                               folderview_select_next_marked(summaryview->folderview);
+                               return;
+                       } 
+                       else
+                               return;
+               } else
+                       summary_select_node(summaryview, node, TRUE, FALSE);
 
-       if (!node)
-               alertpanel_notice(_("No marked messages."));
-       else
-               summary_select_node(summaryview, node, TRUE, FALSE);
+       }
 }
 
 void summary_select_prev_labeled(SummaryView *summaryview)
@@ -1696,7 +1740,6 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
                         gboolean display_msg, gboolean do_refresh)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-
        if (summary_is_locked(summaryview))
                return;
        if (!summaryview->folder_item)
@@ -1780,7 +1823,8 @@ static GtkCTreeNode *summary_find_next_msg(SummaryView *summaryview,
 
        for (; node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
                msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo && !MSG_IS_DELETED(msginfo->flags)) break;
+               if (msginfo && !MSG_IS_DELETED(msginfo->flags) 
+               && !MSG_IS_MOVE(msginfo->flags)) break;
        }
 
        return node;
@@ -2022,12 +2066,9 @@ static void summary_status_show(SummaryView *summaryview)
                msginfo = gtk_ctree_node_get_row_data
                        (GTK_CTREE(summaryview->ctree),
                         GTK_CTREE_NODE(cur->data));
-               if (!msginfo)
-                       g_warning("summary_status_show(): msginfo == NULL\n");
-               else {
+               if (msginfo) {
                        sel_size += msginfo->size;
                        n_selected++;
-                       
                }
        }
        
@@ -2038,9 +2079,7 @@ static void summary_status_show(SummaryView *summaryview)
                        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 {
+                       if (msginfo) {
                                n_size += msginfo->size;
                                n_total++;
                                if (MSG_IS_NEW(msginfo->flags))
@@ -2315,7 +2354,6 @@ void summary_sort(SummaryView *summaryview,
                gtk_clist_set_compare_func(clist, cmp_func);
 
                gtk_clist_set_sort_type(clist, (GtkSortType)sort_type);
-
                gtk_sctree_sort_recursive(ctree, NULL);
 
                gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
@@ -2348,18 +2386,23 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
 
        gtk_sctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
                                NULL, NULL, NULL, NULL, FALSE, summaryview->threaded && !summaryview->thread_collapsed);
-                               //gnode->parent->parent ? TRUE : FALSE);
-#define SET_TEXT(col) \
-       gtk_ctree_node_set_text(ctree, cnode, col_pos[col], \
-                               text[col_pos[col]])
-
-       SET_TEXT(S_COL_NUMBER);
-       SET_TEXT(S_COL_SCORE);
-       SET_TEXT(S_COL_SIZE);
-       SET_TEXT(S_COL_DATE);
-       SET_TEXT(S_COL_FROM);
-       SET_TEXT(S_COL_TO);
-       /* SET_TEXT(S_COL_SUBJECT);  already set by node info */
+#define SET_TEXT(col) {                                                \
+       gtk_ctree_node_set_text(ctree, cnode, col_pos[col],     \
+                               text[col_pos[col]]);            \
+}
+
+       if (summaryview->col_state[summaryview->col_pos[S_COL_NUMBER]].visible)
+               SET_TEXT(S_COL_NUMBER);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_SCORE]].visible)
+               SET_TEXT(S_COL_SCORE);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_SIZE]].visible)
+               SET_TEXT(S_COL_SIZE);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_DATE]].visible)
+               SET_TEXT(S_COL_DATE);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_FROM]].visible)
+               SET_TEXT(S_COL_FROM);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
+               SET_TEXT(S_COL_TO);
 
        if (free_from) {
                g_free(text[col_pos[S_COL_FROM]]);
@@ -2404,7 +2447,7 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        summaryview->subject_table = subject_table;
 
        if (prefs_common.use_addr_book)
-               start_address_completion();
+               start_address_completion(NULL);
        
        if (summaryview->threaded) {
                GNode *root, *gnode;
@@ -2413,14 +2456,13 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
 
                for (gnode = root->children; gnode != NULL;
                     gnode = gnode->next) {
-                       node = gtk_ctree_insert_gnode
+                       node = gtk_sctree_insert_gnode
                                (ctree, NULL, node, gnode,
                                 summary_insert_gnode_func, summaryview);
                }
 
                g_node_destroy(root);
                 
-               //summary_thread_init(summaryview);
                END_TIMING();
        } else {
                gchar *text[N_SUMMARY_COLS];
@@ -2543,20 +2585,33 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        text[col_pos[S_COL_MIME]]   = "";
        text[col_pos[S_COL_LOCKED]] = "";
        text[col_pos[S_COL_DATE]]   = "";
-       text[col_pos[S_COL_NUMBER]] = itos(msginfo->msgnum);
-       text[col_pos[S_COL_SIZE]]   = to_human_readable(msginfo->size);
-       text[col_pos[S_COL_SCORE]]  = itos_buf(col_score, msginfo->score);
-
-       if (msginfo->date_t) {
-               procheader_date_get_localtime(date_modified,
-                                             sizeof(date_modified),
-                                             msginfo->date_t);
-               text[col_pos[S_COL_DATE]] = date_modified;
-       } else if (msginfo->date)
-               text[col_pos[S_COL_DATE]] = msginfo->date;
+       if (summaryview->col_state[summaryview->col_pos[S_COL_NUMBER]].visible)
+               text[col_pos[S_COL_NUMBER]] = itos(msginfo->msgnum);
+       else
+               text[col_pos[S_COL_NUMBER]] = "";
+
+       if (summaryview->col_state[summaryview->col_pos[S_COL_SIZE]].visible)
+               text[col_pos[S_COL_SIZE]] = to_human_readable(msginfo->size);
        else
-               text[col_pos[S_COL_DATE]] = _("(No Date)");
+               text[col_pos[S_COL_SIZE]] = "";
 
+       if (summaryview->col_state[summaryview->col_pos[S_COL_SCORE]].visible)
+               text[col_pos[S_COL_SCORE]] = itos_buf(col_score, msginfo->score);
+       else
+               text[col_pos[S_COL_SCORE]] = "";
+
+       if (summaryview->col_state[summaryview->col_pos[S_COL_DATE]].visible) {
+               if (msginfo->date_t) {
+                       procheader_date_get_localtime(date_modified,
+                                                     sizeof(date_modified),
+                                                     msginfo->date_t);
+                       text[col_pos[S_COL_DATE]] = date_modified;
+               } else if (msginfo->date)
+                       text[col_pos[S_COL_DATE]] = msginfo->date;
+               else
+                       text[col_pos[S_COL_DATE]] = _("(No Date)");
+       }
+       
        if (prefs_common.swap_from && msginfo->from && msginfo->to
        &&  !summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible) {
                gchar *addr = NULL;
@@ -2577,10 +2632,17 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
                                msginfo->fromname :
                                _("(No From)");
        } else {
+               gchar buf[BUFFSIZE];
                gchar *tmp = summary_complete_address(msginfo->from);
-               from_text = tmp ? tmp : (msginfo->fromname ?
-                                        msginfo->fromname: 
-                                               _("(No From)"));
+               if (tmp) {
+                       strncpy2(buf, tmp, sizeof(buf));
+                       g_free(tmp);
+                       from_text = buf;
+               } else {
+                       from_text = (msginfo->fromname) ?
+                                       msginfo->fromname: 
+                                       _("(No From)");
+               }
        }
        
        to_text = msginfo->to ? msginfo->to : 
@@ -2716,7 +2778,6 @@ static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo,
                summary_msginfo_unset_flags
                        (msginfo, MSG_NEW | MSG_UNREAD, 0);
                summary_set_row_marks(summaryview, row);
-               gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
                summary_status_show(summaryview);
        }
 }
@@ -2749,14 +2810,13 @@ static void summary_display_msg_full(SummaryView *summaryview,
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        MsgInfo *msginfo;
        gint val;
-
+       START_TIMING("summary_display_msg_full");
        if (!new_window) {
                if (summaryview->displayed == row)
                        return;
                else
                        summaryview->messageview->filtered = FALSE;
        }                       
-       
        g_return_if_fail(row != NULL);
 
        if (summary_is_locked(summaryview)) return;
@@ -2808,6 +2868,7 @@ static void summary_display_msg_full(SummaryView *summaryview,
        messageview_set_menu_sensitive(summaryview->messageview);
 
        summary_unlock(summaryview);
+       END_TIMING();
 }
 
 void summary_display_msg_selected(SummaryView *summaryview,
@@ -2868,7 +2929,7 @@ void summary_reedit(SummaryView *summaryview)
                                              summaryview->selected);
        if (!msginfo) return;
 
-       compose_reedit(msginfo);
+       compose_reedit(msginfo, FALSE);
 }
 
 gboolean summary_step(SummaryView *summaryview, GtkScrollType type)
@@ -3162,7 +3223,8 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
                msginfo->msgnum);
 }
 
-void summary_mark_as_read(SummaryView *summaryview)
+void summary_mark_as_read
+(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
@@ -3216,12 +3278,11 @@ void summary_mark_all_read(SummaryView *summaryview)
                val = alertpanel_full(_("Mark all as read"),
                        _("Do you really want to mark all mails in this "
                          "folder as read ?"), GTK_STOCK_NO, GTK_STOCK_YES, NULL,
-                         TRUE, NULL, ALERT_QUESTION, G_ALERTALTERNATE);
+                         TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
 
-               if (val == G_ALERTDEFAULT ||
-                   val == (G_ALERTDEFAULT|G_ALERTDISABLE))
+               if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
                        return;
-               else if (val == (G_ALERTALTERNATE|G_ALERTDISABLE))
+               else if (val & G_ALERTDISABLE)
                        prefs_common.ask_mark_all_read = FALSE;
        }
        
@@ -3275,6 +3336,7 @@ void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *wid
                        } else {
                                summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
                        }
+                       summary_set_row_marks(summaryview, row);
                }
        } else {
                log_error(_("An error happened while learning.\n"));
@@ -3454,10 +3516,12 @@ void summary_delete(SummaryView *summaryview)
 
        if (!summaryview->folder_item) return;
 
-       aval = alertpanel(_("Delete message(s)"),
-                         _("Do you really want to delete selected message(s)?"),
-                         GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
-       if (aval != G_ALERTALTERNATE) return;
+       if (!prefs_common.live_dangerously) {
+               aval = alertpanel(_("Delete message(s)"),
+                                 _("Do you really want to delete selected message(s)?"),
+                                 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) {
@@ -3594,7 +3658,7 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
 void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
 {
        GList *cur;
-
+       GtkCTreeNode *sel_last = NULL;
        if (!to_folder) return;
        if (!summaryview->folder_item ||
            FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS) return;
@@ -3606,13 +3670,14 @@ void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
                return;
        }
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview); 
 
        for (cur = GTK_CLIST(summaryview->ctree)->selection;
-            cur != NULL && cur->data != NULL; cur = cur->next)
+            cur != NULL && cur->data != NULL; cur = cur->next) {
+               sel_last = GTK_CTREE_NODE(cur->data);
                summary_move_row_to
                        (summaryview, GTK_CTREE_NODE(cur->data), to_folder);
-
+       }
        END_LONG_OPERATION(summaryview);
 
        summaryview->display_msg = prefs_common.always_show_msg;
@@ -3620,6 +3685,10 @@ void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
        if (prefs_common.immediate_exec) {
                summary_execute(summaryview);
        } else {
+               GtkCTreeNode *node = summary_find_next_msg(summaryview, sel_last);
+               if (!node)
+                       node = summary_find_prev_msg(summaryview, sel_last);
+               summary_select_node(summaryview, node, prefs_common.always_show_msg, TRUE);
                summary_status_show(summaryview);
        }
        
@@ -3956,8 +4025,18 @@ gboolean summary_execute(SummaryView *summaryview)
                        summaryview->displayed = NULL;
                }
                if (GTK_CTREE_ROW(node)->children != NULL) {
-                       g_warning("summary_execute(): children != NULL\n");
-                       continue;
+                       next = NULL;
+                       if (GTK_CTREE_ROW(node)->sibling) {
+                               next = GTK_CTREE_ROW(node)->sibling;
+                       } else {
+                               GtkCTreeNode *parent = NULL;
+                               for (parent = GTK_CTREE_ROW(node)->parent; parent != NULL;
+                                    parent = GTK_CTREE_ROW(parent)->parent) {
+                                       if (GTK_CTREE_ROW(parent)->sibling) {
+                                               next = GTK_CTREE_ROW(parent)->sibling;
+                                       }
+                               }
+                       }
                }
 
                if (!new_selected &&
@@ -4024,7 +4103,12 @@ static gint summary_execute_move(SummaryView *summaryview)
                                summaryview);
 
        if (summaryview->mlist) {
+               hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,
+                       summaryview->msginfo_update_callback_id);
                val = procmsg_move_messages(summaryview->mlist);
+               summaryview->msginfo_update_callback_id =
+               hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, 
+                       summary_update_msg, (gpointer) summaryview);
 
                for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next)
                        procmsg_msginfo_free((MsgInfo *)cur->data);
@@ -4053,6 +4137,12 @@ static void summary_execute_move_func(GtkCTree *ctree, GtkCTreeNode *node,
                                                msginfo->msgid))
                        g_hash_table_remove(summaryview->msgid_table,
                                            msginfo->msgid);
+               if (msginfo->subject && *msginfo->subject && 
+                   node == subject_table_lookup(summaryview->subject_table,
+                                                msginfo->subject)) {
+                       subject_table_remove(summaryview->subject_table,
+                                            msginfo->subject);
+               }                                           
        }
 }
 
@@ -4061,6 +4151,8 @@ static void summary_execute_copy(SummaryView *summaryview)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
 
        /* search copying messages and execute */
+       hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,
+               summaryview->msginfo_update_callback_id);
        gtk_ctree_pre_recursive(ctree, NULL, summary_execute_copy_func,
                                summaryview);
 
@@ -4071,6 +4163,9 @@ static void summary_execute_copy(SummaryView *summaryview)
                g_slist_free(summaryview->mlist);
                summaryview->mlist = NULL;
        }
+       summaryview->msginfo_update_callback_id =
+               hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, 
+                       summary_update_msg, (gpointer) summaryview);
 }
 
 static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -4101,9 +4196,15 @@ static void summary_execute_delete(SummaryView *summaryview)
 
        if (!summaryview->mlist) return;
 
+       hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,
+               summaryview->msginfo_update_callback_id);
+
        folder_item_remove_msgs(summaryview->folder_item,
                                summaryview->mlist);
 
+       summaryview->msginfo_update_callback_id =
+               hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, 
+                       summary_update_msg, (gpointer) summaryview);
        for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next)
                procmsg_msginfo_free((MsgInfo *)cur->data);
 
@@ -4121,7 +4222,7 @@ static void summary_execute_delete_func(GtkCTree *ctree, GtkCTreeNode *node,
 
        if (msginfo && MSG_IS_DELETED(msginfo->flags)) {
                summaryview->mlist =
-                       g_slist_append(summaryview->mlist, msginfo);
+                       g_slist_prepend(summaryview->mlist, msginfo);
                gtk_ctree_node_set_row_data(ctree, node, NULL);
 
                if (msginfo->msgid && *msginfo->msgid &&
@@ -4188,7 +4289,7 @@ void summary_thread_build(SummaryView *summaryview)
                                 msginfo->subject);
                }
 
-               if (parent && parent != node) {
+               if (parent && parent != node && parent != GTK_CTREE_ROW(node)->parent) {
                        gtk_ctree_move(ctree, node, parent, NULL);
                }
 
@@ -4242,7 +4343,7 @@ static void summary_unthread_for_exec(SummaryView *summaryview)
 
        for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
             node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               summary_unthread_for_exec_func(ctree, node, NULL);
+               summary_unthread_for_exec_func(ctree, node, summaryview);
        }
 
        END_LONG_OPERATION(summaryview);
@@ -4257,7 +4358,7 @@ static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
        GtkCTreeNode *top_parent;
        GtkCTreeNode *child;
        GtkCTreeNode *sibling;
-
+       SummaryView * summaryview = (SummaryView *)data;
        msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
 
        if (!msginfo ||
@@ -4267,19 +4368,41 @@ static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
        child = GTK_CTREE_ROW(node)->children;
        if (!child) return;
 
+       if (node == summaryview->selected)
+               summaryview->selected = NULL;
+       if (node == summaryview->displayed)
+               summaryview->displayed = NULL;
+
        for (top_parent = node;
             GTK_CTREE_ROW(top_parent)->parent != NULL;
             top_parent = GTK_CTREE_ROW(top_parent)->parent)
                ;
        sibling = GTK_CTREE_ROW(top_parent)->sibling;
 
+       GTK_SCTREE(ctree)->sorting = TRUE;
        while (child != NULL) {
                GtkCTreeNode *next_child;
-
+               MsgInfo *cinfo = GTKUT_CTREE_NODE_GET_ROW_DATA(child);
+               
                next_child = GTK_CTREE_ROW(child)->sibling;
-               gtk_ctree_move(ctree, child, NULL, sibling);
+               
+               if (!MSG_IS_MOVE(cinfo->flags) && !MSG_IS_DELETED(cinfo->flags)) {
+                       gtk_ctree_move(ctree, child, 
+                               NULL, 
+                               sibling); 
+               } else {
+                       if (child == summaryview->displayed) {
+                               messageview_clear(summaryview->messageview);
+                               summaryview->displayed = NULL;
+                       }
+                       if (child == summaryview->selected) {
+                               messageview_clear(summaryview->messageview);
+                               summaryview->selected = NULL;
+                       }
+               }
                child = next_child;
        }
+       GTK_SCTREE(ctree)->sorting = FALSE;
 }
 
 void summary_expand_threads(SummaryView *summaryview)
@@ -4387,7 +4510,7 @@ static void summary_filter_func(MsgInfo *msginfo)
        if (hooks_invoke(MAIL_MANUAL_FILTERING_HOOKLIST, &mail_filtering_data))
                return;
 
-       filter_message_by_msginfo(filtering_rules, msginfo);
+       filter_message_by_msginfo(filtering_rules, msginfo, NULL);
 }
 
 void summary_msginfo_filter_open(FolderItem * item, MsgInfo *msginfo,
@@ -4402,16 +4525,19 @@ void summary_msginfo_filter_open(FolderItem * item, MsgInfo *msginfo,
                if (item == NULL)
                        prefs_filtering_open(&pre_global_processing,
                                             _("Processing rules to apply before folder rules"),
-                                            header, key);
+                                            MANUAL_ANCHOR_PROCESSING,
+                                            header, key, FALSE);
                else
                        prefs_filtering_open(&item->prefs->processing,
                                             _("Processing configuration"),
-                                            header, key);
+                                            MANUAL_ANCHOR_PROCESSING,
+                                            header, key, FALSE);
        }
        else {
                prefs_filtering_open(&filtering_rules,
-                                    _("Filtering configuration"),
-                                      header, key);
+                               _("Filtering configuration"),
+                               MANUAL_ANCHOR_FILTERING,
+                               header, key, TRUE);
        }
        
        g_free(header);
@@ -4494,6 +4620,7 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        }
 
        gtk_ctree_node_set_row_style(ctree, node, style);
+       gtk_style_unref(style);
 }
 
 static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *row, guint labelcolor)
@@ -4506,6 +4633,7 @@ static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *r
 
        summary_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, 
                                        MSG_CLABEL_FLAG_MASK, 0);
+       summary_set_row_marks(summaryview, row);
 }
 
 void summary_set_colorlabel(SummaryView *summaryview, guint labelcolor,
@@ -5179,10 +5307,10 @@ GSList *summary_get_selection(SummaryView *summaryview)
 
        for ( ; sel != NULL; sel = sel->next)
                msginfo_list = 
-                       g_slist_append(msginfo_list, 
+                       g_slist_prepend(msginfo_list, 
                                       gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree),
                                                                   GTK_CTREE_NODE(sel->data)));
-       return msginfo_list;
+       return g_slist_reverse(msginfo_list);
 }
 
 static void summary_reply_cb(SummaryView *summaryview, guint action,
@@ -5240,6 +5368,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
 
        node = GTK_CTREE_NODE(GTK_CLIST(summaryview->ctree)->row_list);
 
+       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
        if (prefs_common.bold_unread) {
                while (node) {
                        GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
@@ -5248,6 +5377,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
                        node = next;
                }
        }
+       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
        END_TIMING();
 }
 
@@ -5451,7 +5581,6 @@ static gint func_name(GtkCList *clist,                                     \
 {                                                                       \
        MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data;                 \
        MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data;                 \
-                                                                        \
        if (!msginfo1 || !msginfo2)                                      \
                return -1;                                               \
                                                                         \
@@ -5880,6 +6009,9 @@ static gboolean summary_update_msg(gpointer source, gpointer data)
        g_return_val_if_fail(msginfo_update != NULL, TRUE);
        g_return_val_if_fail(summaryview != NULL, FALSE);
 
+       if (msginfo_update->msginfo->folder != summaryview->folder_item)
+               return FALSE;
+
        if (msginfo_update->flags & MSGINFO_UPDATE_FLAGS) {
                node = gtk_ctree_find_by_row_data(
                                GTK_CTREE(summaryview->ctree), NULL,