2006-09-04 [colin] 2.4.0cvs143
[claws.git] / src / summaryview.c
index 28db0fc6ee280d3b6e428eaaf88984d230b6bba2..ccbb6aec033f26dfee33914a7b882a51cf3a87ce 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
@@ -106,6 +107,10 @@ static GdkPixmap *markxpm;
 static GdkBitmap *markxpmmask;
 static GdkPixmap *deletedxpm;
 static GdkBitmap *deletedxpmmask;
+static GdkPixmap *movedxpm;
+static GdkBitmap *movedxpmmask;
+static GdkPixmap *copiedxpm;
+static GdkBitmap *copiedxpmmask;
 
 static GdkPixmap *newxpm;
 static GdkBitmap *newxpmmask;
@@ -140,14 +145,14 @@ static void summary_set_marks_func        (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
                                         gpointer                data);
 
-void summary_set_menu_sensitive        (SummaryView            *summaryview);
+void  summary_set_menu_sensitive       (SummaryView            *summaryview);
+guint summary_get_msgnum               (SummaryView            *summaryview,
+                                        GtkCTreeNode           *node);
+
 
 static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                                             guint action);
 
-static guint summary_get_msgnum                (SummaryView            *summaryview,
-                                        GtkCTreeNode           *node);
-
 static GtkCTreeNode *summary_find_prev_msg
                                        (SummaryView            *summaryview,
                                         GtkCTreeNode           *current_node);
@@ -179,8 +184,7 @@ static void summary_set_ctree_from_list     (SummaryView            *summaryview,
                                         GSList                 *mlist);
 static void summary_set_header         (SummaryView            *summaryview,
                                         gchar                  *text[],
-                                        MsgInfo                *msginfo,
-                                        gboolean               *free_from);
+                                        MsgInfo                *msginfo);
 static void summary_display_msg                (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
 static void summary_display_msg_full   (SummaryView            *summaryview,
@@ -237,9 +241,6 @@ static void summary_unthread_for_exec_func  (GtkCTree       *ctree,
 void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
                              GSList * mlist);
 
-#if 0
-void summary_processing(SummaryView *summaryview, GSList * mlist);
-#endif
 static void summary_filter_func                (MsgInfo *msginfo);
 
 static void summary_colorlabel_menu_item_activate_cb
@@ -248,7 +249,8 @@ static void summary_colorlabel_menu_item_activate_cb
 static void summary_colorlabel_menu_item_activate_item_cb
                                          (GtkMenuItem  *label_menu_item,
                                           gpointer      data);
-static void summary_colorlabel_menu_create(SummaryView *summaryview);
+static void summary_colorlabel_menu_create(SummaryView *summaryview,
+                                          gboolean  refresh);
 
 static GtkWidget *summary_ctree_create (SummaryView    *summaryview);
 
@@ -395,8 +397,6 @@ static gint summary_cmp_by_locked   (GtkCList               *clist,
                                         gconstpointer           ptr1, 
                                         gconstpointer           ptr2);
 
-static void news_flag_crosspost                (MsgInfo *msginfo);
-
 static void quicksearch_execute_cb     (QuickSearch    *quicksearch,
                                         gpointer        data);
 static void tog_searchbar_cb           (GtkWidget      *w,
@@ -473,8 +473,8 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/_View"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_View/Open in new _window"),
                                        "<control><alt>N", summary_open_msg,    0, NULL},
-       {N_("/_View/_Source"),          "<control>U", summary_view_source, 0, NULL},
-       {N_("/_View/All _header"),      "<control>H", summary_show_all_header_cb, 0, "<ToggleItem>"},
+       {N_("/_View/Message _source"),  "<control>U", summary_view_source, 0, NULL},
+       {N_("/_View/All _headers"),     "<control>H", summary_show_all_header_cb, 0, "<ToggleItem>"},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/_Save as..."),            "<control>S", summary_save_as,   0, NULL},
        {N_("/_Print..."),              "<control>P", summary_print,   0, NULL},
@@ -494,19 +494,28 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        "",             /* S_COL_LOCKED  */
 };
 
-#define START_LONG_OPERATION(summaryview) {                    \
+#define START_LONG_OPERATION(summaryview,force_freeze) {       \
        summary_lock(summaryview);                              \
        main_window_cursor_wait(summaryview->mainwin);          \
-       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));        \
+       if (force_freeze || sc_g_list_bigger(GTK_CLIST(summaryview->ctree)->selection, 1)) {\
+               froze = TRUE;                                           \
+               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();                                           \
        folder_item_update_thaw();                              \
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));          \
+       if (froze)                                              \
+               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)
@@ -729,6 +738,10 @@ void summary_init(SummaryView *summaryview)
                         &clipgpgsignedxpm, &clipgpgsignedxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_SPAM,
                         &spamxpm, &spamxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_MOVED,
+                        &movedxpm, &movedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_COPIED,
+                        &copiedxpm, &copiedxpmmask);
 
        summary_set_fonts(summaryview);
 
@@ -752,79 +765,21 @@ void summary_init(SummaryView *summaryview)
 
        summary_clear_list(summaryview);
        summary_set_column_titles(summaryview);
-       summary_colorlabel_menu_create(summaryview);
+       summary_colorlabel_menu_create(summaryview, FALSE);
+       main_create_mailing_list_menu (summaryview->mainwin, NULL);     
        summary_set_menu_sensitive(summaryview);
 
 }
 
-#if 0
-GtkCTreeNode * summary_find_next_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
-
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_NEXT(current_node);
-       else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-
-       for (; node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
-       }
-
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
-
-GtkCTreeNode * summary_find_prev_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
-
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_PREV(current_node);
-       else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-
-       for (; node != NULL; node = GTK_CTREE_NODE_PREV(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
-       }
-
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
-#endif
-
 #define CURRENTLY_DISPLAYED(m) \
 ( (m->msgnum == displayed_msgnum) \
   && (!g_ascii_strcasecmp(m->folder->name,item->name)) )
 
+#define FOLDER_SHOWS_TO_HDR(i) \
+( folder_has_parent_of_type(i, F_OUTBOX) \
+  ||  folder_has_parent_of_type(i, F_DRAFT) \
+  ||  folder_has_parent_of_type(i, F_QUEUE) )
+  
 static void summary_switch_from_to(SummaryView *summaryview, FolderItem *item)
 {
        gboolean show_from = FALSE, show_to = FALSE;
@@ -835,9 +790,7 @@ static void summary_switch_from_to(SummaryView *summaryview, FolderItem *item)
        
        if (!item)
                return;
-       if (folder_has_parent_of_type(item, F_OUTBOX)
-       ||  folder_has_parent_of_type(item, F_DRAFT)
-       ||  folder_has_parent_of_type(item, F_QUEUE))
+       if(FOLDER_SHOWS_TO_HDR(item))
                show_to = TRUE;
        else
                show_from = TRUE;
@@ -885,6 +838,18 @@ 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);
@@ -902,22 +867,27 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (!summaryview->mainwin)
                return FALSE;
-
+START_TIMING("--------- summary_show");
+       summaryview->last_displayed = NULL;
        summary_switch_from_to(summaryview, item);
 
        inc_lock();
        summary_lock(summaryview);
 
+       is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
+
+       if (!is_refresh)
+               main_create_mailing_list_menu (summaryview->mainwin, NULL);
+
        if (!prefs_common.summary_quicksearch_sticky
         && !prefs_common.summary_quicksearch_recurse
-        && !quicksearch_is_running(summaryview->quicksearch)) {
+        && !quicksearch_is_running(summaryview->quicksearch)
+        && !is_refresh) {
                quicksearch_set(summaryview->quicksearch, prefs_common.summary_quicksearch_type, "");
        }
 
        /* STATUSBAR_POP(summaryview->mainwin); */
 
-       is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
-
        if (is_refresh) {
                selected_msgnum = summary_get_msgnum(summaryview,
                                                     summaryview->selected);
@@ -944,6 +914,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                } else {
                        summary_unlock(summaryview);
                        inc_unlock();
+                       END_TIMING();
                        return FALSE;
                }
                if (changed || !quicksearch_is_active(summaryview->quicksearch))
@@ -957,7 +928,11 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        buf = NULL;
        if (!item || !item->path || !folder_item_parent(item) || item->no_select) {
                g_free(buf);
-               debug_print("empty folder\n\n");
+               debug_print("empty folder (%p %s %p %d)\n\n",
+                               item, 
+                               item?item->path:"NULL",
+                               item?folder_item_parent(item):0x0,
+                               item?item->no_select:FALSE);
                summary_set_hide_read_msgs_menu(summaryview, FALSE);
                summary_clear_all(summaryview);
                summaryview->folder_item = item;
@@ -972,7 +947,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                              summaryview->folderview,
                                              summaryview->folder_item);
                        main_window_cursor_normal(summaryview->mainwin);
-               }                       
+               }       
+               END_TIMING();           
                return TRUE;
        }
        g_free(buf);
@@ -1026,11 +1002,17 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
                GSList *not_killed;
-
+               START_TIMING("quicksearch");
+               gint num = 0, total = summaryview->folder_item->total_msgs;
+               statusbar_print_all(_("Searching in %s... \n"), 
+                       summaryview->folder_item->path ? 
+                       summaryview->folder_item->path : "(null)");
                not_killed = NULL;
                for (cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
 
+                       statusbar_progress_all(num++,total, 50);
+
                        if (!msginfo->hidden && quicksearch_match(summaryview->quicksearch, msginfo))
                                not_killed = g_slist_prepend(not_killed, msginfo);
                        else
@@ -1040,18 +1022,10 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                break;
                        }
                }
+               statusbar_progress_all(0,0,0);
+               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));
@@ -1060,13 +1034,16 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                        summary_unlock(summaryview);
                        inc_unlock();
                        summary_show(summaryview, summaryview->folder_item);
+                       END_TIMING();
                        return FALSE;
                }
                g_slist_free(mlist);
                mlist = not_killed;
+               END_TIMING();
        }
 
        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;
@@ -1078,6 +1055,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                }
                g_slist_free(mlist);
                mlist = not_killed;
+               END_TIMING();
        }
 
        STATUSBAR_POP(summaryview->mainwin);
@@ -1088,7 +1066,15 @@ 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->last_displayed = summaryview->displayed;
                summaryview->displayed =
                        summary_find_msg_by_msgnum(summaryview,
                                                   displayed_msgnum);
@@ -1113,19 +1099,65 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                }
        } else {
                switch (prefs_common.select_on_entry) {
-                       case SELECTONENTRY_NEW:
+                       case SELECTONENTRY_MNU:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               break;
+                       case SELECTONENTRY_MUN:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               break;
+                       case SELECTONENTRY_NMU:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               break;
+                       case SELECTONENTRY_NUM:
                                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_NEW, FALSE);
                                if (node == NULL)
                                        node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
                                break;
-                       case SELECTONENTRY_UNREAD:
+                       case SELECTONENTRY_UNM:
                                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_UNREAD, FALSE);
                                if (node == NULL)
                                        node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               break;
+                       case SELECTONENTRY_UMN:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
                                break;
                        default:
                                node = NULL;
@@ -1155,7 +1187,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        main_window_cursor_normal(summaryview->mainwin);
        summary_unlock(summaryview);
        inc_unlock();
-
+       END_TIMING();
        return TRUE;
 }
 
@@ -1313,15 +1345,15 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
                gchar *const entry;
                SensitiveCond cond;
        } entry[] = {
-               {"/Reply"                       , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to"                    , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/all"                , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/sender"             , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/mailing list"       , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
+               {"/Reply"                       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/all"                , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/sender"             , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/mailing list"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
 
                {"/Forward"                     , M_HAVE_ACCOUNT|M_TARGET_EXIST},
                {"/Forward as attachment"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
-               {"/Redirect"                    , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
+               {"/Redirect"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
 
                {"/Move..."                     , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
                {"/Copy..."                     , M_TARGET_EXIST|M_EXEC},
@@ -1346,8 +1378,8 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
 
                {"/View"                        , M_SINGLE_TARGET_EXIST},
                {"/View/Open in new window"     , M_SINGLE_TARGET_EXIST},
-               {"/View/Source"                 , M_SINGLE_TARGET_EXIST},
-               {"/View/All header            , M_SINGLE_TARGET_EXIST},
+               {"/View/Message source"         , M_SINGLE_TARGET_EXIST},
+               {"/View/All headers"            , M_SINGLE_TARGET_EXIST},
                {"/Save as..."                  , M_TARGET_EXIST},
                {"/Print..."                    , M_TARGET_EXIST},
                {NULL, 0}
@@ -1364,7 +1396,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
 
 
        summary_lock(summaryview);
-       menuitem = gtk_item_factory_get_widget(ifactory, "/View/All header");
+       menuitem = gtk_item_factory_get_widget(ifactory, "/View/All headers");
        if (summaryview->messageview 
        &&  summaryview->messageview->mimeview
        &&  summaryview->messageview->mimeview->textview)
@@ -1462,7 +1494,7 @@ void summary_select_next_unread(SummaryView *summaryview)
                        }
 
                        if (val == G_ALERTALTERNATE) {
-                               folderview_select_next_unread(summaryview->folderview);
+                               folderview_select_next_unread(summaryview->folderview, TRUE);
                                return;
                        } 
                        else
@@ -1599,27 +1631,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)
@@ -1672,6 +1733,22 @@ void summary_select_next_labeled(SummaryView *summaryview)
                summary_select_node(summaryview, node, TRUE, FALSE);
 }
 
+void summary_select_last_read(SummaryView *summaryview)
+{
+       if (summaryview->last_displayed)
+               summary_select_node(summaryview, summaryview->last_displayed, TRUE, FALSE);
+}
+
+void summary_select_parent(SummaryView *summaryview)
+{
+       GtkCTreeNode *node = NULL;
+
+       if (summaryview->selected)
+               node = GTK_CTREE_ROW(summaryview->selected)->parent;
+       if (node)
+               summary_select_node(summaryview, node, TRUE, FALSE);
+}
+
 void summary_select_by_msgnum(SummaryView *summaryview, guint msgnum)
 {
        GtkCTreeNode *node;
@@ -1696,26 +1773,19 @@ 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)
                return;
        if (node) {
                gtkut_ctree_expand_parent_all(ctree, node);
                if (do_refresh) {
+                       summary_lock(summaryview);
                        GTK_EVENTS_FLUSH();
+                       summary_unlock(summaryview);
                        gtk_widget_grab_focus(GTK_WIDGET(ctree));
-                       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)
                        summaryview->displayed = NULL;
                summaryview->display_msg = display_msg;
@@ -1725,7 +1795,7 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
        }
 }
 
-static guint summary_get_msgnum(SummaryView *summaryview, GtkCTreeNode *node)
+guint summary_get_msgnum(SummaryView *summaryview, GtkCTreeNode *node)
 {
        GtkCTree *ctree =NULL;
        MsgInfo *msginfo;
@@ -1736,7 +1806,10 @@ static guint summary_get_msgnum(SummaryView *summaryview, GtkCTreeNode *node)
        if (!node)
                return 0;
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
-       return msginfo->msgnum;
+       if (msginfo)
+               return msginfo->msgnum;
+       else 
+               return -1;
 }
 
 static GtkCTreeNode *summary_find_prev_msg(SummaryView *summaryview,
@@ -1773,7 +1846,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;
@@ -1955,10 +2029,6 @@ static void summary_set_marks_func(GtkCTree *ctree, GtkCTreeNode *node,
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
 
-       if (msginfo->folder && msginfo->folder->folder &&
-           msginfo->folder->folder->klass->type == F_NEWS)
-               news_flag_crosspost(msginfo);
-
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted++;
 
@@ -2007,6 +2077,7 @@ static void summary_status_show(SummaryView *summaryview)
                gtk_label_set_text(GTK_LABEL(summaryview->statlabel_folder), "");
                gtk_label_set_text(GTK_LABEL(summaryview->statlabel_select), "");
                gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs),   "");
+               toolbar_main_set_sensitive(summaryview->mainwin);
                return;
        }
 
@@ -2015,12 +2086,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++;
-                       
                }
        }
        
@@ -2031,9 +2099,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))
@@ -2103,11 +2169,13 @@ static void summary_status_show(SummaryView *summaryview)
                                      to_human_readable(n_size));
        gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
        g_free(str);
+       toolbar_main_set_sensitive(summaryview->mainwin);
 }
 
 static void summary_set_column_titles(SummaryView *summaryview)
 {
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
+       FolderItem *item = summaryview->folder_item;
        GtkWidget *hbox;
        GtkWidget *label;
        GtkWidget *arrow;
@@ -2143,6 +2211,9 @@ static void summary_set_column_titles(SummaryView *summaryview)
                case S_COL_TO:
                case S_COL_DATE:
                case S_COL_NUMBER:
+                       if(type == S_COL_FROM && item != NULL &&
+                                       FOLDER_SHOWS_TO_HDR(item))
+                               type = S_COL_TO;
                        if (prefs_common.trans_hdr)
                                title = gettext(col_label[type]);
                        else
@@ -2213,8 +2284,7 @@ void summary_reflect_prefs(void)
        if (last_font && !strcmp(last_font, NORMAL_FONT))
                update_font = FALSE;
 
-       if (last_font)
-               g_free(last_font);
+       g_free(last_font);
        
        last_font = g_strdup(NORMAL_FONT);
 
@@ -2234,6 +2304,7 @@ void summary_sort(SummaryView *summaryview,
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
        GtkCListCompareFunc cmp_func = NULL;
+       START_TIMING("summary_sort");
        g_signal_handlers_block_by_func(G_OBJECT(summaryview->ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
        gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
@@ -2304,7 +2375,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);
@@ -2319,6 +2389,7 @@ unlock:
        gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
        g_signal_handlers_unblock_by_func(G_OBJECT(summaryview->ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
+       END_TIMING();
 }
 
 gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
@@ -2330,29 +2401,28 @@ 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 = FALSE;
        
-       summary_set_header(summaryview, text, msginfo, &free_from);
+       summary_set_header(summaryview, text, msginfo);
 
        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) \
-       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 */
-
-       if (free_from) {
-               g_free(text[col_pos[S_COL_FROM]]);
-               text[col_pos[S_COL_FROM]] = NULL;
-       }
+                               NULL, NULL, NULL, NULL, FALSE, summaryview->threaded && !summaryview->thread_collapsed);
+#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);
 
 #undef SET_TEXT
 
@@ -2392,42 +2462,37 @@ 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;
-
+               START_TIMING("summaryview_set_ctree_from_list(1)");
                root = procmsg_get_thread_tree(mlist);
 
                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];
-               gboolean free_from = FALSE;
-               gint *col_pos = summaryview->col_pos;
-
+               START_TIMING("summaryview_set_ctree_from_list(2)");
                cur = mlist;
                for (; mlist != NULL; mlist = mlist->next) {
                        msginfo = (MsgInfo *)mlist->data;
 
-                       summary_set_header(summaryview, text, msginfo, &free_from);
+                       summary_set_header(summaryview, text, msginfo);
 
                        node = gtk_sctree_insert_node
                                (ctree, NULL, node, text, 2,
                                 NULL, NULL, NULL, NULL,
                                 FALSE, FALSE);
-                       if (free_from) {
-                               g_free(text[col_pos[S_COL_FROM]]);
-                               text[col_pos[S_COL_FROM]] = NULL;
-                       }
+
                        GTKUT_CTREE_NODE_SET_ROW_DATA(node, msginfo);
                        summary_set_marks_func(ctree, node, summaryview);
 
@@ -2440,6 +2505,7 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                                             node);
                }
                mlist = cur;
+               END_TIMING();
        }
 
        if (prefs_common.enable_hscrollbar &&
@@ -2470,12 +2536,14 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
 
        if (prefs_common.bold_unread) {
+               START_TIMING("summaryview_set_ctree_from_list(3)");
                while (node) {
                        GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
                        if (GTK_CTREE_ROW(node)->children)
                                summary_set_row_marks(summaryview, node);
                        node = next;
                }
+               END_TIMING();
        }
 
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
@@ -2493,7 +2561,8 @@ static gchar *summary_complete_address(const gchar *addr)
 
        Xstrdup_a(email_addr, addr, return NULL);
        extract_address(email_addr);
-       g_return_val_if_fail(*email_addr, NULL);
+       if (!*email_addr)
+               return NULL;
 
        /*
         * completion stuff must be already initialized
@@ -2509,7 +2578,7 @@ static gchar *summary_complete_address(const gchar *addr)
 }
 
 static void summary_set_header(SummaryView *summaryview, gchar *text[],
-                              MsgInfo *msginfo, gboolean *free_from)
+                              MsgInfo *msginfo)
 {
        static gchar date_modified[80];
        static gchar col_score[11];
@@ -2526,20 +2595,35 @@ 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]] = "";
+
+       /* slow! */
+       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]] = "";
+
+       /* slow! */
+       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;
@@ -2560,10 +2644,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 : 
@@ -2575,12 +2666,11 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        text[col_pos[S_COL_TO]] = to_text;
        if (!should_swap) {
                text[col_pos[S_COL_FROM]] = from_text;
-               *free_from = FALSE;
        } else {
-               gchar *tmp = NULL;
-               tmp = g_strconcat("-->", to_text, NULL);
+               gchar tmp[BUFFSIZE];
+               snprintf(tmp, BUFFSIZE-1, "--> %s", to_text);
+               tmp[BUFFSIZE-1]='\0';
                text[col_pos[S_COL_FROM]] = tmp;
-               *free_from = TRUE;
        }
        
        if (summaryview->simplify_subject_preg != NULL)
@@ -2699,7 +2789,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);
        }
 }
@@ -2732,14 +2821,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;
@@ -2750,6 +2838,8 @@ static void summary_display_msg_full(SummaryView *summaryview,
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        
+       g_return_if_fail(msginfo);
+
        if (new_window) {
                MessageView *msgview;
 
@@ -2759,7 +2849,7 @@ static void summary_display_msg_full(SummaryView *summaryview,
                MessageView *msgview;
 
                msgview = summaryview->messageview;
-
+               summaryview->last_displayed = summaryview->displayed;
                summaryview->displayed = row;
                if (!messageview_is_visible(msgview)) {
                        main_window_toggle_message_view(summaryview->mainwin);
@@ -2768,7 +2858,8 @@ static void summary_display_msg_full(SummaryView *summaryview,
                val = messageview_show(msgview, msginfo, all_headers);
                if (GTK_CLIST(msgview->mimeview->ctree)->row_list == NULL)
                        gtk_widget_grab_focus(summaryview->ctree);
-               gtkut_ctree_node_move_if_on_the_edge(ctree, row);
+               gtkut_ctree_node_move_if_on_the_edge(ctree, row,
+                       GTK_CLIST(summaryview->ctree)->focus_row);
        }
 
        if (val == 0 && MSG_IS_UNREAD(msginfo->flags)) {
@@ -2789,6 +2880,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,
@@ -2842,16 +2934,14 @@ void summary_reedit(SummaryView *summaryview)
 
        if (!summaryview->selected) return;
        if (!summaryview->folder_item) return;
-       if (!folder_has_parent_of_type(summaryview->folder_item, F_OUTBOX)
-       &&  !folder_has_parent_of_type(summaryview->folder_item, F_DRAFT)
-       &&  !folder_has_parent_of_type(summaryview->folder_item, F_QUEUE))
+       if (!FOLDER_SHOWS_TO_HDR(summaryview->folder_item))
                return;
 
        msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree),
                                              summaryview->selected);
        if (!msginfo) return;
 
-       compose_reedit(msginfo);
+       compose_reedit(msginfo, FALSE);
 }
 
 gboolean summary_step(SummaryView *summaryview, GtkScrollType type)
@@ -2954,6 +3044,9 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_IGNORE_THREAD(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          ignorethreadxpm, ignorethreadxpmmask);
+       } else if (MSG_IS_SPAM(flags)) {
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
+                                         spamxpm, spamxpmmask);
        } else if (MSG_IS_NEW(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          newxpm, newxpmmask);
@@ -2989,14 +3082,12 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                }
                        gtk_ctree_node_set_foreground
                                (ctree, row, &summaryview->color_dim);
-       } else if (MSG_IS_SPAM(flags)) {
-               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MARK],
-                                         spamxpm, spamxpmmask);
        } else if (MSG_IS_MARKED(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MARK],
                                          markxpm, markxpmmask);
        } else if (MSG_IS_MOVE(flags)) {
-               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], "o");
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MARK],
+                                         movedxpm, movedxpmmask);
                if (style)
                        style = bold_marked_style;
                else {
@@ -3005,7 +3096,8 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                        gtk_ctree_node_set_foreground
                                (ctree, row, &summaryview->color_marked);
        } else if (MSG_IS_COPY(flags)) {
-               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], "O");
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MARK],
+                                         copiedxpm, copiedxpmmask);
                if (style)
                        style = bold_marked_style;
                else {
@@ -3013,15 +3105,6 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                }
                        gtk_ctree_node_set_foreground
                                (ctree, row, &summaryview->color_marked);
-#if 0
-       } else if ((global_scoring ||
-                 summaryview->folder_item->prefs->scoring) &&
-                (msginfo->score >= summaryview->important_score) &&
-                (MSG_IS_MARKED(msginfo->flags) || MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))) {
-               gtk_ctree_node_set_text(ctree, row, S_COL_MARK, "!");
-               gtk_ctree_node_set_foreground(ctree, row,
-                                             &summaryview->color_important);
-#endif
        } else {
                gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], "");
        }
@@ -3067,6 +3150,7 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags))
@@ -3075,7 +3159,8 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summary_set_row_marks(summaryview, row);
        debug_print("Message %s/%d is marked\n", msginfo->folder->path, msginfo->msgnum);
 }
@@ -3087,6 +3172,7 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags)) {
@@ -3098,7 +3184,8 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
                changed = TRUE;
        }
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is locked\n", msginfo->msgnum);
@@ -3110,6 +3197,7 @@ static void summary_unlock_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (!MSG_IS_LOCKED(msginfo->flags))
                return;
        procmsg_msginfo_set_to_folder(msginfo, NULL);
@@ -3122,8 +3210,9 @@ void summary_mark(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_mark_row(summaryview, GTK_CTREE_NODE(cur->data));
@@ -3140,6 +3229,7 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        if(!(MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)))
                return;
@@ -3150,12 +3240,14 @@ 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;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_mark_row_as_read(summaryview,
@@ -3170,8 +3262,9 @@ void summary_msgs_lock(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_lock_row(summaryview,
                                         GTK_CTREE_NODE(cur->data));
@@ -3184,8 +3277,9 @@ void summary_msgs_unlock(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_unlock_row(summaryview,
                                   GTK_CTREE_NODE(cur->data));
@@ -3198,8 +3292,22 @@ void summary_mark_all_read(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node;
+       AlertValue val;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       if (prefs_common.ask_mark_all_read) {
+               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_ALERTDEFAULT);
+
+               if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
+                       return;
+               else if (val & G_ALERTDISABLE)
+                       prefs_common.ask_mark_all_read = FALSE;
+       }
+       
+       START_LONG_OPERATION(summaryview, TRUE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); node != NULL;
             node = gtkut_ctree_node_next(ctree, node))
@@ -3223,20 +3331,25 @@ void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *wid
        GSList *msgs = NULL;
        gboolean immediate_exec = prefs_common.immediate_exec;
        gboolean moved = FALSE;
+       gboolean froze = FALSE;
+
        prefs_common.immediate_exec = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
 
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
                GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
                MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
-               msgs = g_slist_prepend(msgs, msginfo);
+               if (msginfo)
+                       msgs = g_slist_prepend(msgs, msginfo);
        }
        
        if (procmsg_spam_learner_learn(NULL, msgs, is_spam) == 0) {
                for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
                        GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
                        MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
+                       if (!msginfo)
+                               continue;
                        if (is_spam) {
                                summary_msginfo_change_flags(msginfo, MSG_SPAM, 0, MSG_NEW|MSG_UNREAD, 0);
                                if (procmsg_spam_get_folder() != summaryview->folder_item) {
@@ -3246,13 +3359,12 @@ 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"));
        }
 
-       g_slist_free(msgs);
-       
        prefs_common.immediate_exec = immediate_exec;
 
        END_LONG_OPERATION(summaryview);
@@ -3261,6 +3373,14 @@ void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *wid
                summary_execute(summaryview);
        }
 
+       if (!moved && msgs) {
+               MsgInfo *msginfo = (MsgInfo *)msgs->data;
+               toolbar_set_learn_button
+                       (summaryview->mainwin->toolbar,
+                        MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
+       }
+       g_slist_free(msgs);
+       
        summary_status_show(summaryview);       
 }
 
@@ -3272,6 +3392,7 @@ static void summary_mark_row_as_unread(SummaryView *summaryview,
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags)) {
                procmsg_msginfo_set_to_folder(msginfo, NULL);
                summary_msginfo_unset_flags(msginfo, MSG_DELETED, 0);
@@ -3289,8 +3410,9 @@ void summary_mark_as_unread(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; 
                cur = cur->next)
@@ -3357,6 +3479,7 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        if (MSG_IS_LOCKED(msginfo->flags)) return;
 
@@ -3368,7 +3491,8 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summaryview->deleted++;
 
        if (!prefs_common.immediate_exec && 
@@ -3416,6 +3540,7 @@ void summary_delete(SummaryView *summaryview)
        GtkCTreeNode *node;
        AlertValue aval;
        MsgInfo *msginfo;
+       gboolean froze = FALSE;
 
        if (!item) return;
 
@@ -3423,16 +3548,18 @@ 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) {
                GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
                msginfo = gtk_ctree_node_get_row_data(ctree, row);
-               if (msginfo->total_size != 0 && 
+               if (msginfo && msginfo->total_size != 0 && 
                    msginfo->size != (off_t)msginfo->total_size)
                        partial_mark_for_delete(msginfo);
        }
@@ -3441,7 +3568,7 @@ void summary_delete(SummaryView *summaryview)
 
        /* next code sets current row focus right. We need to find a row
         * that is not deleted. */
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
                sel_last = GTK_CTREE_NODE(cur->data);
@@ -3495,6 +3622,7 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags))
@@ -3503,7 +3631,8 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summary_set_row_marks(summaryview, row);
 
        debug_print("Message %s/%d is unmarked\n",
@@ -3514,8 +3643,9 @@ void summary_unmark(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_unmark_row(summaryview, GTK_CTREE_NODE(cur->data));
@@ -3534,6 +3664,7 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        g_return_if_fail(to_folder != NULL);
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_LOCKED(msginfo->flags))
                return;
 
@@ -3544,7 +3675,8 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                summaryview->copied--;
        }
        if (!MSG_IS_MOVE(msginfo->flags)) {
-               summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, MSG_COPY);
+               summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, 
+                       MSG_COPY | MSG_MOVE_DONE);
                summaryview->moved++;
        } else {
                summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_COPY);
@@ -3561,6 +3693,8 @@ 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;
+       gboolean froze = FALSE;
 
        if (!to_folder) return;
        if (!summaryview->folder_item ||
@@ -3573,13 +3707,14 @@ void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
                return;
        }
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE); 
 
        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;
@@ -3587,6 +3722,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);
        }
        
@@ -3620,6 +3759,7 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        g_return_if_fail(to_folder != NULL);
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        procmsg_msginfo_set_to_folder(msginfo, to_folder);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
@@ -3628,7 +3768,8 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        }
        
        if (!MSG_IS_COPY(msginfo->flags)) {
-               summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, MSG_MOVE);
+               summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, 
+                       MSG_MOVE | MSG_MOVE_DONE);
                summaryview->copied++;
        } else {
                summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE);
@@ -3644,6 +3785,7 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
 void summary_copy_selected_to(SummaryView *summaryview, FolderItem *to_folder)
 {
        GList *cur;
+       gboolean froze = FALSE;
 
        if (!to_folder) return;
        if (!summaryview->folder_item) return;
@@ -3656,7 +3798,7 @@ void summary_copy_selected_to(SummaryView *summaryview, FolderItem *to_folder)
                return;
        }
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
 
        for (cur = GTK_CLIST(summaryview->ctree)->selection;
             cur != NULL && cur->data != NULL; cur = cur->next)
@@ -3902,6 +4044,8 @@ gboolean summary_execute(SummaryView *summaryview)
 
        gtk_clist_freeze(clist);
 
+       main_window_cursor_wait(summaryview->mainwin);
+
        if (summaryview->threaded)
                summary_unthread_for_exec(summaryview);
 
@@ -3920,8 +4064,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 &&
@@ -3933,27 +4087,25 @@ gboolean summary_execute(SummaryView *summaryview)
                                        (summaryview, node);
                }
 
-               gtk_ctree_remove_node(ctree, node);
+               gtk_sctree_remove_node((GtkSCTree *)ctree, node);
        }
 
        folder_item_update_thaw();
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
 
        if (new_selected) {
                summary_unlock(summaryview);
                gtk_sctree_select
-                       (GTK_SCTREE(ctree),
-                        new_selected);
+                       (GTK_SCTREE(ctree), new_selected);
                summary_lock(summaryview);
        }
 
        if (summaryview->threaded) {
-               gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
                summary_thread_build(summaryview);
                summary_thread_init(summaryview);
-               gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
        }
 
+       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+
        summaryview->selected = clist->selection ?
                GTK_CTREE_NODE(clist->selection->data) : NULL;
 
@@ -3970,7 +4122,9 @@ gboolean summary_execute(SummaryView *summaryview)
        gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        summary_unlock(summaryview);
-       
+
+       main_window_cursor_normal(summaryview->mainwin);
+
        if (move_val < 0) 
                summary_show(summaryview, summaryview->folder_item);
        return TRUE;
@@ -3986,14 +4140,20 @@ 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);
                g_slist_free(summaryview->mlist);
                summaryview->mlist = NULL;
+               return val;
        }
-       return val;
+       return 0;
 }
 
 static void summary_execute_move_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -4014,6 +4174,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);
+               }                                           
        }
 }
 
@@ -4022,6 +4188,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);
 
@@ -4032,6 +4200,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,
@@ -4062,9 +4233,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);
 
@@ -4082,7 +4259,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 &&
@@ -4149,7 +4326,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);
                }
 
@@ -4176,7 +4353,7 @@ static void summary_thread_init(SummaryView *summaryview)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
        GtkCTreeNode *next;
-
+       START_TIMING("summary_thread_init");
        if (!summaryview->thread_collapsed) {
                g_signal_handlers_block_by_func(G_OBJECT(ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
@@ -4189,66 +4366,21 @@ static void summary_thread_init(SummaryView *summaryview)
                g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
        } 
-}
-
-void summary_unthread(SummaryView *summaryview)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       GtkCTreeNode *child;
-       GtkCTreeNode *sibling;
-       GtkCTreeNode *next_child;
-
-       summary_lock(summaryview);
-
-       debug_print("Unthreading...");
-       STATUSBAR_PUSH(summaryview->mainwin, _("Unthreading..."));
-       main_window_cursor_wait(summaryview->mainwin);
-       
-       g_signal_handlers_block_by_func(G_OBJECT(ctree),
-                                       summary_tree_collapsed, summaryview);
-       gtk_clist_freeze(GTK_CLIST(ctree));
-
-       for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-            node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               child = GTK_CTREE_ROW(node)->children;
-               sibling = GTK_CTREE_ROW(node)->sibling;
-
-               while (child != NULL) {
-                       next_child = GTK_CTREE_ROW(child)->sibling;
-                       gtk_ctree_move(ctree, child, NULL, sibling);
-                       child = next_child;
-               }
-       }
-
-       /* CLAWS: and sort it */
-       gtk_sctree_sort_recursive(ctree, NULL); 
-
-       gtk_clist_thaw(GTK_CLIST(ctree));
-       g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
-                                          G_CALLBACK(summary_tree_collapsed), summaryview);
-
-       debug_print("done.\n");
-       STATUSBAR_POP(summaryview->mainwin);
-       main_window_cursor_normal(summaryview->mainwin);
-
-       summaryview->threaded = FALSE;
-
-       summary_unlock(summaryview);
+       END_TIMING();
 }
 
 static void summary_unthread_for_exec(SummaryView *summaryview)
 {
        GtkCTreeNode *node;
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       gboolean froze = FALSE;
 
        debug_print("Unthreading for execution...");
 
-       START_LONG_OPERATION(summaryview);
-
+       START_LONG_OPERATION(summaryview, TRUE);
        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);
@@ -4263,7 +4395,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 ||
@@ -4273,19 +4405,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)
@@ -4334,11 +4488,90 @@ void summary_collapse_threads(SummaryView *summaryview)
        gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
+void account_rules_radio_button_toggled_cb(GtkToggleButton *btn, gpointer data)
+{
+       prefs_common.apply_per_account_filtering_rules = GPOINTER_TO_INT(data);
+}
+
+gboolean summary_filter_get_mode(void)
+/* ask what to do w/ them: skip them, apply them regardless to the account,
+   use the current account */
+{
+       /* TODO: eventually also propose to use the current folder's default account,
+          if it is set */
+       /* TODO: eventually allow to select the account to use from a optmenu */
+
+       GtkWidget *vbox;
+       GtkWidget *account_rules_skip;
+       GtkWidget *account_rules_force;
+       GtkWidget *account_rules_user_current;
+       AlertValue val;
+
+       vbox = gtk_vbox_new (FALSE, 0);
+
+       account_rules_skip = gtk_radio_button_new_with_label
+                                                       (NULL, _("Skip these rules"));
+       account_rules_force = gtk_radio_button_new_with_label_from_widget
+                                                       (GTK_RADIO_BUTTON(account_rules_skip),
+                                                       _("Apply these rules regardless of the account they belong to"));
+       account_rules_user_current = gtk_radio_button_new_with_label_from_widget
+                                                       (GTK_RADIO_BUTTON(account_rules_skip),
+                                                       _("Use current account for these rules"));
+       gtk_box_pack_start (GTK_BOX (vbox), account_rules_skip, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (vbox), account_rules_force, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (vbox), account_rules_user_current, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(account_rules_skip), "toggled",
+                       G_CALLBACK(account_rules_radio_button_toggled_cb),
+                       GINT_TO_POINTER(FILTERING_ACCOUNT_RULES_SKIP));
+       g_signal_connect(G_OBJECT(account_rules_force), "toggled",
+                       G_CALLBACK(account_rules_radio_button_toggled_cb),
+                       GINT_TO_POINTER(FILTERING_ACCOUNT_RULES_FORCE));
+       g_signal_connect(G_OBJECT(account_rules_user_current), "toggled",
+                       G_CALLBACK(account_rules_radio_button_toggled_cb),
+                       GINT_TO_POINTER(FILTERING_ACCOUNT_RULES_USE_CURRENT));
+       switch (prefs_common.apply_per_account_filtering_rules) {
+       case FILTERING_ACCOUNT_RULES_SKIP:
+               gtk_toggle_button_set_active(
+                               GTK_TOGGLE_BUTTON(account_rules_skip), TRUE);
+               break;
+       case FILTERING_ACCOUNT_RULES_FORCE:
+               gtk_toggle_button_set_active(
+                               GTK_TOGGLE_BUTTON(account_rules_force), TRUE);
+               break;
+       case FILTERING_ACCOUNT_RULES_USE_CURRENT:
+               gtk_toggle_button_set_active(
+                               GTK_TOGGLE_BUTTON(account_rules_user_current), TRUE);
+               break;
+       }
+
+       val = alertpanel_with_widget(
+                       _("Filtering"),
+                       _("There are some filtering rules that belong to an account.\n"
+                         "Please choose what to do with these rules:"),
+                       _("_Filter"), _("_Cancel"), NULL, TRUE, vbox);
+       if ((val & ~G_ALERTDISABLE) != G_ALERTDEFAULT) {
+               return FALSE;
+       } else if (val & G_ALERTDISABLE)
+               prefs_common.ask_apply_per_account_filtering_rules = FALSE;
+
+       return TRUE;
+}
+
 void summary_filter(SummaryView *summaryview, gboolean selected_only)
 {
        GSList *mlist = NULL, *cur_list;
        summary_lock(summaryview);
 
+       /* are there any per-account filtering rules? */
+       if (prefs_common.ask_apply_per_account_filtering_rules == TRUE &&
+               filtering_peek_per_account_rules(filtering_rules)) {
+
+               if (summary_filter_get_mode() == FALSE) {
+                       summary_unlock(summaryview);
+                       return;
+               }
+       }
+
        folder_item_update_freeze();
        
        debug_print("filtering...");
@@ -4393,7 +4626,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,
@@ -4408,16 +4641,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);
@@ -4472,6 +4708,7 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        gint color_index;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
+       g_return_if_fail(msginfo);
 
        color_index = labelcolor == 0 ? -1 : (gint)labelcolor - 1;
        ctree_style = gtk_widget_get_style(GTK_WIDGET(ctree));
@@ -4499,6 +4736,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)
@@ -4507,9 +4745,11 @@ static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *r
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        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,
@@ -4517,9 +4757,9 @@ void summary_set_colorlabel(SummaryView *summaryview, guint labelcolor,
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
-
+       START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_set_row_colorlabel(summaryview,
                                           GTK_CTREE_NODE(cur->data), labelcolor);
@@ -4542,6 +4782,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
        if (!sel) return;
 
        menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       
        g_return_if_fail(menu != NULL);
 
        Xalloca(items, (N_COLOR_LABELS + 1) * sizeof(GtkWidget *), return);
@@ -4586,7 +4827,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                          GINT_TO_POINTER(0));
 }
 
-static void summary_colorlabel_menu_create(SummaryView *summaryview)
+static void summary_colorlabel_menu_create(SummaryView *summaryview, gboolean refresh)
 {
        GtkWidget *label_menuitem;
        GtkWidget *menu;
@@ -4615,13 +4856,19 @@ static void summary_colorlabel_menu_create(SummaryView *summaryview)
        g_object_set_data(G_OBJECT(item), "summaryview", summaryview);
        gtk_widget_show(item);
 
+       gtk_widget_add_accelerator(item, "activate", 
+                                  summaryview->popupfactory->accel_group, 
+                                  GDK_0, GDK_CONTROL_MASK,
+                                  GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
+
        item = gtk_menu_item_new();
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        gtk_widget_show(item);
 
        /* create pixmap/label menu items */
        for (i = 0; i < N_COLOR_LABELS; i++) {
-               item = colorlabel_create_check_color_menu_item(i);
+               item = colorlabel_create_check_color_menu_item(
+                       i, refresh, SUMMARY_COLORMENU);
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                g_signal_connect(G_OBJECT(item), "activate",
                                 G_CALLBACK(summary_colorlabel_menu_item_activate_cb),
@@ -4636,6 +4883,16 @@ static void summary_colorlabel_menu_create(SummaryView *summaryview)
        summaryview->colorlabel_menu = menu;
 }
 
+static gboolean summary_popup_menu(GtkWidget *widget, gpointer data)
+{
+       SummaryView *summaryview = (SummaryView *)data;
+       summaryview->display_msg = messageview_is_visible(summaryview->messageview);
+
+       gtk_menu_popup(GTK_MENU(summaryview->popupmenu), NULL, NULL,
+                      NULL, NULL, 0, gtk_get_current_event_time());
+       return TRUE;
+}
+
 static GtkWidget *summary_ctree_create(SummaryView *summaryview)
 {
        GtkWidget *ctree;
@@ -4696,14 +4953,17 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                                   prefs_common.summary_col_size[S_COL_NUMBER]);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_SCORE],
                                   prefs_common.summary_col_size[S_COL_SCORE]);
-       gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
-       gtk_ctree_set_expander_style(GTK_CTREE(ctree),
+
+       if (prefs_common.enable_dotted_lines) {
+               gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
+               gtk_ctree_set_expander_style(GTK_CTREE(ctree),
                                     GTK_CTREE_EXPANDER_SQUARE);
-#if 0
-       gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_NONE);
-       gtk_ctree_set_expander_style(GTK_CTREE(ctree),
+       } else {
+               gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_NONE);
+               gtk_ctree_set_expander_style(GTK_CTREE(ctree),
                                     GTK_CTREE_EXPANDER_TRIANGLE);
-#endif
+       }
+
        gtk_ctree_set_indent(GTK_CTREE(ctree), 12);
        g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
@@ -4743,6 +5003,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        g_signal_connect(G_OBJECT(ctree), "button_press_event",
                         G_CALLBACK(summary_button_pressed),
                         summaryview);
+       g_signal_connect(G_OBJECT(ctree), "popup-menu",
+                        G_CALLBACK(summary_popup_menu), summaryview);
        g_signal_connect(G_OBJECT(ctree), "button_release_event",
                         G_CALLBACK(summary_button_released),
                         summaryview);
@@ -4810,6 +5072,7 @@ void summary_set_column_order(SummaryView *summaryview)
        summary_select_by_msgnum(summaryview, selected_msgnum);
 
        summaryview->displayed = summary_find_msg_by_msgnum(summaryview, displayed_msgnum);
+       summaryview->last_displayed = summaryview->displayed;
        if (!summaryview->displayed)
                messageview_clear(summaryview->messageview);
        else
@@ -4854,9 +5117,9 @@ static gboolean summary_button_released(GtkWidget *ctree, GdkEventButton *event,
        return FALSE;
 }
 
-void summary_pass_key_press_event(SummaryView *summaryview, GdkEventKey *event)
+gboolean summary_pass_key_press_event(SummaryView *summaryview, GdkEventKey *event)
 {
-       summary_key_pressed(summaryview->ctree, event, summaryview);
+       return summary_key_pressed(summaryview->ctree, event, summaryview);
 }
 
 #define BREAK_ON_MODIFIER_KEY() \
@@ -4888,27 +5151,6 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        case GDK_Escape:
                gtk_widget_grab_focus(summaryview->folderview->ctree);
                return TRUE;
-       case GDK_Up:
-       case GDK_Down:
-               if ((node = summaryview->selected) != NULL) {
-                       GtkCTreeNode *next = NULL;
-                       do {
-                               next = (event->keyval == GDK_Down)
-                                       ? gtkut_ctree_node_next(ctree, next ? next:node)
-                                       : gtkut_ctree_node_prev(ctree, next ? next:node);
-                       } while (next && !gtk_ctree_is_viewable(ctree, next));
-
-                       if (next) {
-                               gtk_sctree_select_with_state
-                                       (GTK_SCTREE(ctree), next, event->state);
-                               
-                               /* Deprecated - what are the non-deprecated equivalents? */
-                               if (gtk_ctree_node_is_visible(GTK_CTREE(ctree), next) != GTK_VISIBILITY_FULL)
-                                       gtk_ctree_node_moveto(GTK_CTREE(ctree), next, 0, 0, 0);
-                               summaryview->selected = next;
-                       }
-               }
-               return TRUE;
        case GDK_Home:
        case GDK_End:
                if ((node = summaryview->selected) != NULL) {
@@ -4949,7 +5191,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        switch (event->keyval) {
        case GDK_space:         /* Page down or go to the next */
                if (event->state & GDK_SHIFT_MASK) 
-                       textview_scroll_page(textview, TRUE);
+                       mimeview_scroll_page(messageview->mimeview, TRUE);
                else {
                        if (summaryview->displayed != summaryview->selected) {
                                summary_display_msg(summaryview,
@@ -4957,16 +5199,16 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                                break;
                        }
                        if (mod_pressed) {
-                               if (!textview_scroll_page(textview, TRUE))
+                               if (!mimeview_scroll_page(messageview->mimeview, TRUE))
                                        summary_select_prev_unread(summaryview);
                        } else {
-                               if (!textview_scroll_page(textview, FALSE))
+                               if (!mimeview_scroll_page(messageview->mimeview, FALSE))
                                        summary_select_next_unread(summaryview);
                        }                               
                }
                break;
        case GDK_BackSpace:     /* Page up */
-               textview_scroll_page(textview, TRUE);
+               mimeview_scroll_page(messageview->mimeview, TRUE);
                break;
        case GDK_Return:        /* Scroll up/down one line */
                if (summaryview->displayed != summaryview->selected) {
@@ -4974,7 +5216,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                                            summaryview->selected);
                        break;
                }
-               textview_scroll_one_line(textview, mod_pressed);
+               mimeview_scroll_one_line(messageview->mimeview, mod_pressed);
                break;
        case GDK_Delete:
                BREAK_ON_MODIFIER_KEY();
@@ -5027,9 +5269,7 @@ void summaryview_activate_quicksearch(SummaryView *summaryview)
 
 static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
 {
-       if (folder_has_parent_of_type(summaryview->folder_item, F_OUTBOX)
-       ||  folder_has_parent_of_type(summaryview->folder_item, F_DRAFT)
-       ||  folder_has_parent_of_type(summaryview->folder_item, F_QUEUE))
+       if (FOLDER_SHOWS_TO_HDR(summaryview->folder_item))
                summary_reedit(summaryview);
        else
                summary_open_msg(summaryview);
@@ -5068,12 +5308,46 @@ static void summary_unselected(GtkCTree *ctree, GtkCTreeNode *row,
        summary_status_show(summaryview);
 }
 
+typedef struct _PostponedSelectData
+{
+       GtkCTree *ctree;
+       GtkCTreeNode *row;
+       gint column;
+       SummaryView *summaryview;
+} PostponedSelectData;
+
+static gboolean summary_select_retry(void *data)
+{
+       PostponedSelectData *psdata = (PostponedSelectData *)data;
+       debug_print("trying again\n");
+       summary_selected(psdata->ctree, psdata->row,
+                           psdata->column, psdata->summaryview);
+       g_free(psdata);
+       return FALSE;
+}
+
 static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                             gint column, SummaryView *summaryview)
 {
        MsgInfo *msginfo;
        gboolean marked_unread = FALSE;
 
+       if (summary_is_locked(summaryview)
+       && !GTK_SCTREE(ctree)->selecting_range
+       && summaryview->messageview->mimeview
+       && summaryview->messageview->mimeview->type == MIMEVIEW_TEXT
+       && summaryview->messageview->mimeview->textview->loading) {
+               PostponedSelectData *data = g_new0(PostponedSelectData, 1);
+               summaryview->messageview->mimeview->textview->stop_loading = TRUE;
+               
+               data->ctree = ctree;
+               data->row = row;
+               data->column = column;
+               data->summaryview = summaryview;
+               debug_print("postponing open of message till end of load\n");
+               g_timeout_add(100, summary_select_retry, data);
+               return;
+       }
        if (summary_is_locked(summaryview)
        ||  GTK_SCTREE(ctree)->selecting_range) {
                return;
@@ -5094,6 +5368,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        g_return_if_fail(msginfo != NULL);
 
+       main_create_mailing_list_menu (summaryview->mainwin, msginfo);
        toolbar_set_learn_button
                (summaryview->mainwin->toolbar,
                 MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
@@ -5105,11 +5380,6 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                    !MSG_IS_COPY(msginfo->flags)) {
                        if (MSG_IS_MARKED(msginfo->flags)) {
                                summary_unmark_row(summaryview, row);
-                       } else if (MSG_IS_SPAM(msginfo->flags)) {
-                               if (procmsg_spam_learner_learn(msginfo, NULL, FALSE) == 0)
-                                       summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
-                               else
-                                       log_error(_("An error happened while learning.\n"));
                        } else {
                                summary_mark_row(summaryview, row);
                        }
@@ -5119,6 +5389,11 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                if (MSG_IS_UNREAD(msginfo->flags)) {
                        summary_mark_row_as_read(summaryview, row);
                        summary_status_show(summaryview);
+               } else if (MSG_IS_SPAM(msginfo->flags)) {
+                               if (procmsg_spam_learner_learn(msginfo, NULL, FALSE) == 0)
+                                       summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+                               else
+                                       log_error(_("An error happened while learning.\n"));
                } else if (!MSG_IS_REPLIED(msginfo->flags) &&
                         !MSG_IS_FORWARDED(msginfo->flags)) {
                        marked_unread = TRUE;
@@ -5191,10 +5466,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,
@@ -5252,6 +5527,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);
@@ -5260,6 +5536,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
                        node = next;
                }
        }
+       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
        END_TIMING();
 }
 
@@ -5463,7 +5740,6 @@ static gint func_name(GtkCList *clist,                                     \
 {                                                                       \
        MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data;                 \
        MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data;                 \
-                                                                        \
        if (!msginfo1 || !msginfo2)                                      \
                return -1;                                               \
                                                                         \
@@ -5596,44 +5872,13 @@ static gint summary_cmp_by_score(GtkCList *clist,
                return summary_cmp_by_date(clist, ptr1, ptr2);
 }
 
-static void news_flag_crosspost(MsgInfo *msginfo)
-{
-       GString *line;
-       gpointer key;
-       gpointer value;
-       Folder *mff;
-
-       g_return_if_fail(msginfo != NULL);
-       g_return_if_fail(msginfo->folder != NULL);
-       g_return_if_fail(msginfo->folder->folder != NULL);
-       mff = msginfo->folder->folder;
-       g_return_if_fail(mff->klass->type == F_NEWS);
-
-       if (mff->account->mark_crosspost_read) {
-               line = g_string_sized_new(128);
-               g_string_printf(line, "%s:%d", msginfo->folder->path, msginfo->msgnum);
-               debug_print("nfcp: checking <%s>", line->str);
-               if (mff->newsart && 
-                   g_hash_table_lookup_extended(mff->newsart, line->str, &key, &value)) {
-                       debug_print(" <%s>", (gchar *)value);
-                       if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
-                               summary_msginfo_change_flags(msginfo, 
-                                       mff->account->crosspost_col, 0, MSG_NEW | MSG_UNREAD, 0);
-                       }
-                       g_hash_table_remove(mff->newsart, key);
-                       g_free(key);
-               }
-               g_string_free(line, TRUE);
-               debug_print("\n");
-       }
-}
-
 static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data)
 {
        SummaryView *summaryview = (SummaryView *) data;
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        summary_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0);
 
@@ -5646,8 +5891,9 @@ static void summary_ignore_thread(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), 
                                        GTK_CTREE_FUNC(summary_ignore_thread_func), 
@@ -5664,6 +5910,7 @@ static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpo
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        summary_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0);
 
@@ -5676,8 +5923,9 @@ static void summary_unignore_thread(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
+       gboolean froze = FALSE;
 
-       START_LONG_OPERATION(summaryview);
+       START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), 
                                        GTK_CTREE_FUNC(summary_unignore_thread_func), 
@@ -5697,7 +5945,7 @@ static void summary_check_ignore_thread_func
        if (*found_ignore) return;
        else {
                msginfo = gtk_ctree_node_get_row_data(ctree, row);
-               *found_ignore = MSG_IS_IGNORE_THREAD(msginfo->flags);
+               *found_ignore = msginfo && MSG_IS_IGNORE_THREAD(msginfo->flags);
        }               
 }
 
@@ -5768,6 +6016,8 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_GPG_SIGNED, &gpgsignedxpm, &gpgsignedxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_CLIP_GPG_SIGNED, &clipgpgsignedxpm, &clipgpgsignedxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_SPAM, &spamxpm, &spamxpmmask);
+       stock_pixmap_gdk(ctree, STOCK_PIXMAP_MOVED, &movedxpm, &movedxpmmask);
+       stock_pixmap_gdk(ctree, STOCK_PIXMAP_COPIED, &copiedxpm, &copiedxpmmask);
 
        pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_DIR_OPEN);
        gtk_box_pack_start(GTK_BOX(summaryview->hbox), pixmap, FALSE, FALSE, 4);
@@ -5787,6 +6037,22 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        summary_set_column_titles(summaryview);
 }
 
+void summary_reflect_prefs_custom_colors(SummaryView *summaryview)
+{
+       GtkMenuShell *menu;
+       GList *cur;
+
+       /* re-create colorlabel submenu */
+       menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       g_return_if_fail(menu != NULL);
+
+       /* clear items. get item pointers. */
+       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+               gtk_menu_item_remove_submenu(GTK_MENU_ITEM(cur->data));
+       }
+       summary_colorlabel_menu_create(summaryview, TRUE);
+}
+
 /*
  * Harvest addresses for selected messages in summary view.
  */
@@ -5800,6 +6066,8 @@ void summary_harvest_address(SummaryView *summaryview)
        msgList = NULL;
        for( cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next ) {
                msginfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(cur->data) );
+               if (!msginfo)
+                       continue;
                msgList = g_list_append( msgList, GUINT_TO_POINTER( msginfo->msgnum ) );
        }
        addressbook_harvest( summaryview->folder_item, TRUE, msgList );
@@ -5850,15 +6118,6 @@ void summary_set_prefs_from_folderitem(SummaryView *summaryview, FolderItem *ite
        summaryview->thread_collapsed = item->thread_collapsed;
 
        /* Scoring */
-#if 0
-       if (global_scoring || item->prefs->scoring) {
-               summaryview->important_score = prefs_common.important_score;
-               if (item->prefs->important_score >
-                   summaryview->important_score)
-                       summaryview->important_score =
-                               item->prefs->important_score;
-       }
-#endif
 }
 
 void summary_save_prefs_to_folderitem(SummaryView *summaryview, FolderItem *item)
@@ -5881,6 +6140,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, 
@@ -5931,19 +6193,22 @@ static void summary_find_answers (SummaryView *summaryview, MsgInfo *msg)
                summary_select_node(summaryview, node, TRUE, TRUE);
 }
 
-void summaryview_export_mbox_list(SummaryView *summaryview)
+gint summaryview_export_mbox_list(SummaryView *summaryview)
+/* return values: -2 skipped, -1 error, 0 OK */
 {
        GSList *list = summary_get_selected_msg_list(summaryview);
        gchar *mbox = filesel_select_file_save(_("Export to mbox file"), NULL);
+       gint ret;
        
        if (mbox == NULL || list == NULL)
-               return;
+               return -1;
                
-       export_list_to_mbox(list, mbox);
+       ret = export_list_to_mbox(list, mbox);
        
        g_slist_free(list);
        g_free(mbox);
        
+       return ret;
 }
 
 void summaryview_lock(SummaryView *summaryview, FolderItem *item)