2007-02-21 [wwp] 2.7.2cvs59
[claws.git] / src / summaryview.c
index 36af8a32355ff2596492f0cfd4bdb9fabf41c021..f6c1adebcfd83f40ba4218f232660af1d9426b11 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -107,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;
@@ -180,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,
@@ -227,8 +230,6 @@ static void summary_execute_delete_func     (GtkCTree               *ctree,
                                         gpointer                data);
 
 static void summary_thread_init                (SummaryView            *summaryview);
-static void summary_ignore_thread      (SummaryView            *summaryview);
-static void summary_unignore_thread     (SummaryView            *summaryview);
 
 static void summary_unthread_for_exec          (SummaryView    *summaryview);
 static void summary_unthread_for_exec_func     (GtkCTree       *ctree,
@@ -394,8 +395,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,
@@ -405,11 +404,12 @@ static void summary_find_answers  (SummaryView    *summaryview,
                                         MsgInfo        *msg);
 
 static gboolean summary_update_msg     (gpointer source, gpointer data);
+static gboolean summary_update_folder_item_name(gpointer source, gpointer data);
 
 GtkTargetEntry summary_drag_types[2] =
 {
        {"text/uri-list", 0, TARGET_MAIL_URI_LIST},
-       {"sylpheed-claws/internal", GTK_TARGET_SAME_APP, TARGET_DUMMY}
+       {"claws-mail/internal", GTK_TARGET_SAME_APP, TARGET_DUMMY}
 };
 
 static GtkItemFactoryEntry summary_popup_entries[] =
@@ -420,16 +420,16 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/Repl_y to/_sender"),      NULL, summary_reply_cb, COMPOSE_REPLY_TO_SENDER, NULL},
        {N_("/Repl_y to/mailing _list"),
                                        "<control>L", summary_reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_Forward"),               "<control><alt>F", summary_reply_cb, COMPOSE_FORWARD_INLINE, NULL},
        {N_("/For_ward as attachment"), NULL, summary_reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL},
        {N_("/Redirect"),               NULL, summary_reply_cb, COMPOSE_REDIRECT, NULL},
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/M_ove..."),               "<control>O", summary_move_to,  0, NULL},
        {N_("/_Copy..."),               "<shift><control>O", summary_copy_to,   0, NULL},
        {N_("/Move to _trash"),         "<control>D", summary_delete_trash,     0, NULL},
        {N_("/_Delete..."),             NULL, summary_delete, 0, NULL},
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_Mark"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_Mark/_Mark"),            NULL, summary_mark,     0, NULL},
        {N_("/_Mark/_Unmark"),          NULL, summary_unmark,   0, NULL},
@@ -447,7 +447,7 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/_Mark/Unlock"),           NULL, summary_msgs_unlock, 0, NULL},
        {N_("/Color la_bel"),           NULL, NULL,             0, NULL},
 
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/Add sender to address boo_k"),
                                        NULL, summary_add_address_cb, 0, NULL},
        {N_("/Create f_ilter rule"),    NULL, NULL,             0, "<Branch>"},
@@ -468,13 +468,13 @@ static GtkItemFactoryEntry summary_popup_entries[] =
                                        NULL, summary_create_processing_cb, FILTER_BY_TO, NULL},
        {N_("/Create processing rule/by _Subject"),
                                        NULL, summary_create_processing_cb, FILTER_BY_SUBJECT, NULL},
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {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_("/---"),                    NULL, NULL,             0, "<Separator>"},
+       {N_("/_View/Message _source"),  "<control>U", summary_view_source, 0, NULL},
+       {N_("/_View/All _headers"),     "<control>H", summary_show_all_header_cb, 0, "<ToggleItem>"},
+       {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_Save as..."),            "<control>S", summary_save_as,   0, NULL},
        {N_("/_Print..."),              "<control>P", summary_print,   0, NULL},
 };  /* see also list in menu_connect_identical_items() in menu.c if this changes */
@@ -493,10 +493,39 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        "",             /* S_COL_LOCKED  */
 };
 
-#define START_LONG_OPERATION(summaryview) {                    \
+void summary_freeze(SummaryView *summaryview)
+{
+       if (summaryview)
+               gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
+}
+
+void summary_thaw(SummaryView *summaryview)
+{
+       if (summaryview)
+               gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+}
+
+void summary_grab_focus(SummaryView *summaryview)
+{
+       if (summaryview)
+               gtk_widget_grab_focus(summaryview->ctree);
+}
+
+GtkWidget *summary_get_main_widget(SummaryView *summaryview)
+{
+       if (summaryview)
+               return summaryview->ctree;
+       else
+               return NULL;
+}
+
+#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;                                           \
+               summary_freeze(summaryview);    \
+       }                                                       \
        folder_item_update_freeze();                            \
        inc_lock();                                             \
        hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,          \
@@ -505,7 +534,8 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
 #define END_LONG_OPERATION(summaryview) {                      \
        inc_unlock();                                           \
        folder_item_update_thaw();                              \
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));          \
+       if (froze)                                              \
+               summary_thaw(summaryview);      \
        main_window_cursor_normal(summaryview->mainwin);        \
        summary_unlock(summaryview);                            \
        summaryview->msginfo_update_callback_id =               \
@@ -521,6 +551,9 @@ SummaryView *summary_create(void)
        GtkWidget *ctree;
        GtkWidget *hbox;
        GtkWidget *hbox_l;
+       GtkWidget *stat_box;
+       GtkWidget *stat_box2;
+       GtkWidget *stat_vbox;
        GtkWidget *statlabel_folder;
        GtkWidget *statlabel_select;
        GtkWidget *statlabel_msgs;
@@ -544,6 +577,15 @@ SummaryView *summary_create(void)
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_widget_show(hbox);
 
+       stat_vbox = gtk_vbox_new(FALSE, 0);
+       gtk_widget_show(stat_vbox);
+
+       stat_box = gtk_hbox_new(FALSE, 0);
+       gtk_widget_show(stat_box);
+       
+       stat_box2 = gtk_hbox_new(FALSE, 0);
+       gtk_widget_show(stat_box2);
+       
        search_tip = gtk_tooltips_new();
        toggle_search = gtk_toggle_button_new();
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_search),
@@ -556,9 +598,13 @@ SummaryView *summary_create(void)
        
        gtk_box_pack_start(GTK_BOX(hbox), toggle_search, FALSE, FALSE, 2);      
 
+       gtk_box_pack_start(GTK_BOX(hbox), stat_vbox, TRUE, TRUE, 0);    
+       gtk_box_pack_start(GTK_BOX(stat_vbox), stat_box, TRUE, TRUE, 0);        
+       gtk_box_pack_start(GTK_BOX(stat_vbox), stat_box2, TRUE, TRUE, 0);       
+
        hbox_l = gtk_hbox_new(FALSE, 0);
        gtk_widget_show(hbox_l);
-       gtk_box_pack_start(GTK_BOX(hbox), hbox_l, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(stat_box), hbox_l, TRUE, TRUE, 0);
  
        statlabel_folder = gtk_label_new("");
        gtk_widget_show(statlabel_folder);
@@ -581,7 +627,7 @@ SummaryView *summary_create(void)
        
        statlabel_msgs = gtk_label_new("");
        gtk_widget_show(statlabel_msgs);
-       gtk_box_pack_end(GTK_BOX(hbox), statlabel_msgs, FALSE, FALSE, 4);
+       gtk_box_pack_end(GTK_BOX(stat_box), statlabel_msgs, FALSE, FALSE, 4);
 
        hbox_spc = gtk_hbox_new(FALSE, 0);
        gtk_widget_show(hbox_spc);
@@ -607,6 +653,7 @@ SummaryView *summary_create(void)
        gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
 
        /* status label */
+       gtk_widget_show_all(stat_vbox);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
        /* quick search */
@@ -630,6 +677,9 @@ SummaryView *summary_create(void)
        summaryview->ctree = ctree;
        summaryview->hbox = hbox;
        summaryview->hbox_l = hbox_l;
+       summaryview->hbox_spc = hbox_spc;
+       summaryview->stat_box = stat_box;
+       summaryview->stat_box2 = stat_box2;
        summaryview->statlabel_folder = statlabel_folder;
        summaryview->statlabel_select = statlabel_select;
        summaryview->statlabel_msgs = statlabel_msgs;
@@ -641,6 +691,10 @@ SummaryView *summary_create(void)
        summaryview->lock_count = 0;
        summaryview->msginfo_update_callback_id =
                hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview);
+       summaryview->folder_item_update_callback_id =
+               hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
+                               summary_update_folder_item_name,
+                               (gpointer) summaryview);
 
        summaryview->target_list = gtk_target_list_new(summary_drag_types, 2);
 
@@ -659,9 +713,48 @@ SummaryView *summary_create(void)
        else
                quicksearch_hide(quicksearch);
        
+       if (prefs_common.layout_mode == WIDE_MSGLIST_LAYOUT)
+               gtk_widget_hide(summaryview->toggle_eventbox);
+
        return summaryview;
 }
 
+void summary_relayout(SummaryView *summaryview)
+{
+       gtk_widget_realize(summaryview->stat_box);
+
+       gtk_widget_ref(summaryview->hbox_l);
+       gtk_widget_ref(summaryview->statlabel_msgs);
+       
+       gtkut_container_remove(GTK_CONTAINER(summaryview->hbox_l->parent), summaryview->hbox_l);
+       gtkut_container_remove(GTK_CONTAINER(summaryview->statlabel_msgs->parent), summaryview->statlabel_msgs);
+
+       switch (prefs_common.layout_mode) {
+       case NORMAL_LAYOUT:
+       case WIDE_LAYOUT:
+       case WIDE_MSGLIST_LAYOUT:
+               gtk_box_pack_start(GTK_BOX(summaryview->stat_box), summaryview->hbox_l, TRUE, TRUE, 0);
+               gtk_box_pack_end(GTK_BOX(summaryview->stat_box), summaryview->statlabel_msgs, FALSE, FALSE, 4);
+               gtk_widget_show_all(summaryview->stat_box);
+               gtk_widget_show_all(summaryview->stat_box2);
+               if (prefs_common.layout_mode == WIDE_MSGLIST_LAYOUT)
+                       gtk_widget_hide(summaryview->toggle_eventbox);
+               else
+                       gtk_widget_show(summaryview->toggle_eventbox);
+               break;
+       case VERTICAL_LAYOUT:
+               gtk_box_pack_start(GTK_BOX(summaryview->stat_box), summaryview->hbox_l, TRUE, TRUE, 0);
+               gtk_box_pack_start(GTK_BOX(summaryview->stat_box2), summaryview->statlabel_msgs, FALSE, FALSE, 4);
+               gtk_widget_show_all(summaryview->stat_box);
+               gtk_widget_show_all(summaryview->stat_box2);
+               gtk_widget_show(summaryview->toggle_eventbox);
+               break;
+       }
+       gtk_widget_unref(summaryview->hbox_l);
+       gtk_widget_unref(summaryview->statlabel_msgs);
+       quicksearch_relayout(summaryview->quicksearch);
+}
+
 static void summary_set_fonts(SummaryView *summaryview)
 {
        PangoFontDescription *font_desc;
@@ -733,6 +826,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);
 
@@ -781,7 +878,7 @@ static void summary_switch_from_to(SummaryView *summaryview, FolderItem *item)
        
        if (!item)
                return;
-       if(FOLDER_SHOWS_TO_HDR(item))
+       if (FOLDER_SHOWS_TO_HDR(item))
                show_to = TRUE;
        else
                show_from = TRUE;
@@ -840,10 +937,41 @@ static gboolean summaryview_quicksearch_recurse(gpointer data)
        main_window_cursor_normal(summaryview->mainwin);
        return FALSE;
 }
+
+static gboolean summary_check_consistency(FolderItem *item, GSList *mlist)
+{
+       int u = 0, n = 0, m = 0, t = 0;
+       GSList *cur;
+       START_TIMING("");
+       for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
+               MsgInfo * msginfo = (MsgInfo *) cur->data;
+               t++;
+               if (MSG_IS_NEW(msginfo->flags))
+                       n++;
+               if (MSG_IS_UNREAD(msginfo->flags))
+                       u++;
+               if (MSG_IS_MARKED(msginfo->flags))
+                       m++;            
+       }
+       if (t != item->total_msgs
+       ||  n != item->new_msgs
+       ||  u != item->unread_msgs
+       ||  m != item->marked_msgs
+       ||  (m == 0 && item->unreadmarked_msgs != 0)
+       ||  item->unreadmarked_msgs < 0) {
+               debug_print("Inconsistency\n");
+               folder_item_scan_full(item, FALSE);
+               END_TIMING();
+               return FALSE;
+       } 
+       END_TIMING();
+       return TRUE;
+}
+
 gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
+       GtkCTreeNode *node = NULL;
        GSList *mlist = NULL;
        gchar *buf;
        gboolean is_refresh;
@@ -857,7 +985,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (!summaryview->mainwin)
                return FALSE;
-
+       START_TIMING("");
        summaryview->last_displayed = NULL;
        summary_switch_from_to(summaryview, item);
 
@@ -904,13 +1032,14 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                } else {
                        summary_unlock(summaryview);
                        inc_unlock();
+                       END_TIMING();
                        return FALSE;
                }
                if (changed || !quicksearch_is_active(summaryview->quicksearch))
                        folder_update_op_count();
        }
        
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       summary_freeze(summaryview);
 
        summary_clear_list(summaryview);
 
@@ -925,7 +1054,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                summary_set_hide_read_msgs_menu(summaryview, FALSE);
                summary_clear_all(summaryview);
                summaryview->folder_item = item;
-               gtk_clist_thaw(GTK_CLIST(ctree));
+               summary_thaw(summaryview);
                summary_unlock(summaryview);
                inc_unlock();
                if (item && quicksearch_is_running(summaryview->quicksearch)) {
@@ -936,7 +1065,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);
@@ -956,6 +1086,12 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        mlist = folder_item_get_msg_list(item);
 
+       if (!summary_check_consistency(item, mlist)) {
+               debug_print("reloading due to inconsistency\n");
+               procmsg_msg_list_free(mlist);
+               mlist = folder_item_get_msg_list(item);
+       }
+
        if (summaryview->folder_item->hide_read_msgs &&
            quicksearch_is_active(summaryview->quicksearch) == FALSE) {
                GSList *not_killed;
@@ -990,41 +1126,48 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
                GSList *not_killed;
+               gint interval = quicksearch_is_fast(summaryview->quicksearch) ? 5000:100;
+               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;
+               folder_item_update_freeze();
                for (cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
 
-                       statusbar_progress_all(num++,total, 50);
+                       statusbar_progress_all(num++,total, interval);
 
                        if (!msginfo->hidden && quicksearch_match(summaryview->quicksearch, msginfo))
                                not_killed = g_slist_prepend(not_killed, msginfo);
                        else
                                procmsg_msginfo_free(msginfo);
-                       GTK_EVENTS_FLUSH();
+                       if (num % interval == 0)
+                               GTK_EVENTS_FLUSH();
                        if (!quicksearch_is_active(summaryview->quicksearch)) {
                                break;
                        }
                }
+               folder_item_update_thaw();
                statusbar_progress_all(0,0,0);
                statusbar_pop_all();
                
                hidden_removed = TRUE;
                if (!quicksearch_is_active(summaryview->quicksearch)) {
                        debug_print("search cancelled!\n");
-                       gtk_clist_thaw(GTK_CLIST(ctree));
+                       summary_thaw(summaryview);
                        STATUSBAR_POP(summaryview->mainwin);
                        main_window_cursor_normal(summaryview->mainwin);
                        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) {
@@ -1059,28 +1202,39 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        }
 
        if (is_refresh) {
-               summaryview->last_displayed = summaryview->displayed;
-               summaryview->displayed =
-                       summary_find_msg_by_msgnum(summaryview,
-                                                  displayed_msgnum);
-               if (!summaryview->displayed)
-                       messageview_clear(summaryview->messageview);
-               summary_unlock(summaryview);
-               summary_select_by_msgnum(summaryview, selected_msgnum);
-               summary_lock(summaryview);
-               if (!summaryview->selected) {
-                       /* no selected message - select first unread
-                          message, but do not display it */
-                       node = summary_find_next_flagged_msg(summaryview, NULL,
-                                                            MSG_UNREAD, FALSE);
-                       if (node == NULL && GTK_CLIST(ctree)->row_list != NULL)
+               if (!quicksearch_is_in_typing(summaryview->quicksearch)) {
+                       summaryview->last_displayed = summaryview->displayed;
+                       summaryview->displayed =
+                               summary_find_msg_by_msgnum(summaryview,
+                                                          displayed_msgnum);
+                       if (!summaryview->displayed)
+                               messageview_clear(summaryview->messageview);
+                       summary_unlock(summaryview);
+                       summary_select_by_msgnum(summaryview, selected_msgnum);
+                       summary_lock(summaryview);
+                       if (!summaryview->selected) {
+                               /* no selected message - select first unread
+                                  message, but do not display it */
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               if (node == NULL && GTK_CLIST(ctree)->row_list != NULL)
+                                       node = gtk_ctree_node_nth
+                                               (ctree,
+                                                item->sort_type == SORT_DESCENDING
+                                                ? 0 : GTK_CLIST(ctree)->rows - 1);
+                               summary_unlock(summaryview);
+                               summary_select_node(summaryview, node, FALSE, TRUE);
+                               summary_lock(summaryview);
+                       }
+               } else {
+                       /* just select first/last */
+                       if (GTK_CLIST(ctree)->row_list != NULL)
                                node = gtk_ctree_node_nth
                                        (ctree,
                                         item->sort_type == SORT_DESCENDING
                                         ? 0 : GTK_CLIST(ctree)->rows - 1);
-                       summary_unlock(summaryview);
-                       summary_select_node(summaryview, node, FALSE, TRUE);
-                       summary_lock(summaryview);
+                       gtk_sctree_select(GTK_SCTREE(ctree), node);
+                       gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0);
                }
        } else {
                switch (prefs_common.select_on_entry) {
@@ -1165,14 +1319,14 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        summary_set_menu_sensitive(summaryview);
        toolbar_main_set_sensitive(summaryview->mainwin);
        
-       gtk_clist_thaw(GTK_CLIST(ctree));
+       summary_thaw(summaryview);
        debug_print("\n");
        STATUSBAR_PUSH(summaryview->mainwin, _("Done."));
        STATUSBAR_POP(summaryview->mainwin);
        main_window_cursor_normal(summaryview->mainwin);
        summary_unlock(summaryview);
        inc_unlock();
-
+       END_TIMING();
        return TRUE;
 }
 
@@ -1184,7 +1338,7 @@ void summary_clear_list(SummaryView *summaryview)
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
        gint optimal_width;
 
-       gtk_clist_freeze(clist);
+       summary_freeze(summaryview);
 
        gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree),
                                NULL, summary_free_msginfo_func, NULL);
@@ -1220,7 +1374,7 @@ void summary_clear_list(SummaryView *summaryview)
                         optimal_width);
        }
 
-       gtk_clist_thaw(clist);
+       summary_thaw(summaryview);
 }
 
 void summary_clear_all(SummaryView *summaryview)
@@ -1298,26 +1452,6 @@ GSList *summary_get_selected_msg_list(SummaryView *summaryview)
        return mlist;
 }
 
-GSList *summary_get_msg_list(SummaryView *summaryview)
-{
-       GSList *mlist = NULL;
-       GtkCTree *ctree;
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-
-       ctree = GTK_CTREE(summaryview->ctree);
-
-       for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-            node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
-               msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
-               mlist = g_slist_prepend(mlist, msginfo);
-       }
-
-       mlist = g_slist_reverse(mlist);
-
-       return mlist;
-}
-
 void summary_set_menu_sensitive(SummaryView *summaryview)
 {
        GtkItemFactory *ifactory = summaryview->popupfactory;
@@ -1351,6 +1485,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
                {"/Mark/Mark as unread"         , M_TARGET_EXIST},
                {"/Mark/Mark all read"          , M_TARGET_EXIST},
                {"/Mark/Ignore thread"          , M_TARGET_EXIST},
+               {"/Mark/Unignore thread"        , M_TARGET_EXIST},
                {"/Mark/Lock"                   , M_TARGET_EXIST},
                {"/Mark/Unlock"                 , M_TARGET_EXIST},
                {"/Mark/Mark as spam"           , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
@@ -1363,8 +1498,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}
@@ -1381,7 +1516,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)
@@ -1479,7 +1614,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
@@ -1726,7 +1861,7 @@ void summary_select_last_read(SummaryView *summaryview)
 
 void summary_select_parent(SummaryView *summaryview)
 {
-       GtkCTreeNode *node;
+       GtkCTreeNode *node = NULL;
 
        if (summaryview->selected)
                node = GTK_CTREE_ROW(summaryview->selected)->parent;
@@ -1742,6 +1877,34 @@ void summary_select_by_msgnum(SummaryView *summaryview, guint msgnum)
        summary_select_node(summaryview, node, FALSE, TRUE);
 }
 
+typedef struct _PostponedSelectData
+{
+       GtkCTree *ctree;
+       GtkCTreeNode *row;
+       GtkCTreeNode *node;
+       GtkScrollType type;
+       gint column;
+       SummaryView *summaryview;
+       gboolean display_msg;
+       gboolean do_refresh;
+} PostponedSelectData;
+
+static gboolean summary_select_retry(void *data)
+{
+       PostponedSelectData *psdata = (PostponedSelectData *)data;
+       debug_print("trying again\n");
+       if (psdata->row)
+               summary_selected(psdata->ctree, psdata->row,
+                           psdata->column, psdata->summaryview);
+       else if (psdata->node)
+               summary_select_node(psdata->summaryview, psdata->node,
+                           psdata->display_msg, psdata->do_refresh);
+       else
+               summary_step(psdata->summaryview, psdata->type);
+       g_free(psdata);
+       return FALSE;
+}
+
 /**
  * summary_select_node:
  * @summaryview: Summary view.
@@ -1758,8 +1921,28 @@ 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))
+       
+       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 = NULL;
+               data->node = node;
+               data->summaryview = summaryview;
+               data->display_msg = display_msg;
+               data->do_refresh = do_refresh;
+               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)) {
                return;
+       }
        if (!summaryview->folder_item)
                return;
        if (node) {
@@ -1769,18 +1952,8 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
                        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;
@@ -1960,7 +2133,7 @@ void summary_attract_by_subject(SummaryView *summaryview)
                       _("Attracting messages by subject..."));
 
        main_window_cursor_wait(summaryview->mainwin);
-       gtk_clist_freeze(clist);
+       summary_freeze(summaryview);
 
        subject_table = g_hash_table_new(attract_hash_func,
                                         attract_compare_func);
@@ -1999,7 +2172,7 @@ void summary_attract_by_subject(SummaryView *summaryview)
 
        gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
-       gtk_clist_thaw(clist);
+       summary_thaw(summaryview);
 
        debug_print("done.\n");
        STATUSBAR_POP(summaryview->mainwin);
@@ -2024,10 +2197,6 @@ static void summary_set_marks_func(GtkCTree *ctree, GtkCTreeNode *node,
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
 
-       if (msginfo && msginfo->folder && msginfo->folder->folder &&
-           msginfo->folder->folder->klass->type == F_NEWS)
-               news_flag_crosspost(msginfo);
-
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted++;
 
@@ -2076,6 +2245,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;
        }
 
@@ -2167,6 +2337,7 @@ 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)
@@ -2209,7 +2380,8 @@ static void summary_set_column_titles(SummaryView *summaryview)
                case S_COL_DATE:
                case S_COL_NUMBER:
                        if(type == S_COL_FROM && item != NULL &&
-                                       FOLDER_SHOWS_TO_HDR(item))
+                                       FOLDER_SHOWS_TO_HDR(item) &&
+                                       !summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
                                type = S_COL_TO;
                        if (prefs_common.trans_hdr)
                                title = gettext(col_label[type]);
@@ -2224,19 +2396,23 @@ static void summary_set_column_titles(SummaryView *summaryview)
                        label = gtk_image_new_from_pixmap(clipxpm, clipxpmmask);
                        gtk_widget_show(label);
                        gtk_clist_set_column_widget(clist, pos, label);
+                       gtk_sctree_set_column_tooltip(GTK_SCTREE(clist), pos, _("Attachment"));
                        continue;
                } else if (type == S_COL_MARK) {
                        label = gtk_image_new_from_pixmap(markxpm, markxpmmask);
                        gtk_widget_show(label);
                        gtk_clist_set_column_widget(clist, pos, label);
+                       gtk_sctree_set_column_tooltip(GTK_SCTREE(clist), pos, _("Mark"));
                        continue;
                } else if (type == S_COL_LOCKED) {
                        label = gtk_image_new_from_pixmap(lockedxpm, lockedxpmmask);
                        gtk_widget_show(label);
                        gtk_clist_set_column_widget(clist, pos, label);
+                       gtk_sctree_set_column_tooltip(GTK_SCTREE(clist), pos, _("Locked"));
                        continue;
                } else if (type == S_COL_STATUS) {
                        gtk_clist_set_column_title(clist, pos, title);
+                       gtk_sctree_set_column_tooltip(GTK_SCTREE(clist), pos, _("Status"));
                        continue;
                }
 
@@ -2301,10 +2477,10 @@ 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");
+       START_TIMING("");
        g_signal_handlers_block_by_func(G_OBJECT(summaryview->ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
-       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
+       summary_freeze(summaryview);
 
        switch (sort_key) {
        case SORT_BY_MARK:
@@ -2368,7 +2544,6 @@ void summary_sort(SummaryView *summaryview,
 
                main_window_cursor_wait(summaryview->mainwin);
 
-                gtk_clist_freeze(clist);
                gtk_clist_set_compare_func(clist, cmp_func);
 
                gtk_clist_set_sort_type(clist, (GtkSortType)sort_type);
@@ -2377,19 +2552,18 @@ void summary_sort(SummaryView *summaryview,
                gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
                main_window_cursor_normal(summaryview->mainwin);
-                gtk_clist_thaw(clist);
 
                debug_print("done.\n");
                STATUSBAR_POP(summaryview->mainwin);
        }
 unlock:
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+       summary_thaw(summaryview);
        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,
+static gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
                                   GtkCTreeNode *cnode, gpointer data)
 {
        SummaryView *summaryview = (SummaryView *)data;
@@ -2398,9 +2572,8 @@ 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, summaryview->threaded && !summaryview->thread_collapsed);
@@ -2422,11 +2595,6 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        if (summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
                SET_TEXT(S_COL_TO);
 
-       if (free_from) {
-               g_free(text[col_pos[S_COL_FROM]]);
-               text[col_pos[S_COL_FROM]] = NULL;
-       }
-
 #undef SET_TEXT
 
        GTKUT_CTREE_NODE_SET_ROW_DATA(cnode, msginfo);
@@ -2445,13 +2613,13 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        MsgInfo *msginfo;
        GtkCTreeNode *node = NULL;
        GHashTable *msgid_table;
-       GHashTable *subject_table;
+       GHashTable *subject_table = NULL;
        GSList * cur;
-       START_TIMING("summary_set_ctree_from_list");
+       START_TIMING("");
        
        if (!mlist) return;
 
-       debug_print("\tSetting summary from message data...");
+       debug_print("\tSetting summary from message data...\n");
        STATUSBAR_PUSH(summaryview->mainwin,
                       _("Setting summary from message data..."));
        gdk_flush();
@@ -2461,15 +2629,20 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
 
        msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
        summaryview->msgid_table = msgid_table;
-       subject_table = g_hash_table_new(g_str_hash, g_str_equal);
-       summaryview->subject_table = subject_table;
+
+       if (prefs_common.thread_by_subject) {
+               subject_table = g_hash_table_new(g_str_hash, g_str_equal);
+               summaryview->subject_table = subject_table;
+       } else {
+               summaryview->subject_table = NULL;
+       }
 
        if (prefs_common.use_addr_book)
                start_address_completion(NULL);
        
        if (summaryview->threaded) {
                GNode *root, *gnode;
-               START_TIMING("summaryview_set_ctree_from_list(1)");
+               START_TIMING("threaded");
                root = procmsg_get_thread_tree(mlist);
 
                for (gnode = root->children; gnode != NULL;
@@ -2484,23 +2657,18 @@ static void summary_set_ctree_from_list(SummaryView *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)");
+               START_TIMING("unthreaded");
                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);
 
@@ -2508,7 +2676,8 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                                g_hash_table_insert(msgid_table,
                                                    msginfo->msgid, node);
 
-                       subject_table_insert(subject_table,
+                       if (prefs_common.thread_by_subject)
+                               subject_table_insert(subject_table,
                                             msginfo->subject,
                                             node);
                }
@@ -2535,7 +2704,8 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        if (debug_get_mode()) {
                debug_print("\tmsgid hash table size = %d\n",
                            g_hash_table_size(msgid_table));
-               debug_print("\tsubject hash table size = %d\n",
+               if (prefs_common.thread_by_subject)
+                       debug_print("\tsubject hash table size = %d\n",
                            g_hash_table_size(subject_table));
        }
 
@@ -2544,7 +2714,7 @@ 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)");
+               START_TIMING("bold_unread");
                while (node) {
                        GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
                        if (GTK_CTREE_ROW(node)->children)
@@ -2586,7 +2756,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];
@@ -2608,6 +2778,7 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        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
@@ -2618,6 +2789,7 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        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,
@@ -2672,12 +2844,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)
@@ -2803,7 +2974,6 @@ static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo,
 typedef struct  {
        MsgInfo *msginfo;
        SummaryView *summaryview;
-       GtkCTreeNode *row;
 } MarkAsReadData;
 
 static int msginfo_mark_as_read_timeout(void *data)
@@ -2814,7 +2984,7 @@ static int msginfo_mark_as_read_timeout(void *data)
        
        if (mdata->msginfo == summary_get_selected_msg(mdata->summaryview))
                msginfo_mark_as_read(mdata->summaryview, mdata->msginfo,
-                                    mdata->row); 
+                                    mdata->summaryview->selected); 
 
        g_free(mdata);
 
@@ -2828,7 +2998,7 @@ static void summary_display_msg_full(SummaryView *summaryview,
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        MsgInfo *msginfo;
        gint val;
-       START_TIMING("summary_display_msg_full");
+       START_TIMING("");
        if (!new_window) {
                if (summaryview->displayed == row)
                        return;
@@ -2865,7 +3035,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)) {
@@ -2873,8 +3044,7 @@ static void summary_display_msg_full(SummaryView *summaryview,
                        MarkAsReadData *data = g_new0(MarkAsReadData, 1);
                        data->summaryview = summaryview;
                        data->msginfo = msginfo;
-                       data->row = row;
-                       gtk_timeout_add(prefs_common.mark_as_read_delay * 1000,
+                       g_timeout_add(prefs_common.mark_as_read_delay * 1000,
                                msginfo_mark_as_read_timeout, data);
                } else if (new_window || !prefs_common.mark_as_read_on_new_window) {
                        msginfo_mark_as_read(summaryview, msginfo, row);
@@ -2915,9 +3085,8 @@ void summary_open_msg(SummaryView *summaryview)
        
        /* CLAWS: if separate message view, don't open a new window
         * but rather use the current separated message view */
-       summary_display_msg_full(summaryview, summaryview->selected,
-                                prefs_common.sep_msg ? FALSE : TRUE, 
-                                FALSE);
+       summary_display_msg_full(summaryview, summaryview->selected, 
+                                TRUE, FALSE);
 }
 
 void summary_view_source(SummaryView * summaryview)
@@ -2955,7 +3124,25 @@ gboolean summary_step(SummaryView *summaryview, GtkScrollType type)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node;
 
-       if (summary_is_locked(summaryview)) return 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 = NULL;
+               data->node = NULL;
+               data->type = type;
+               data->summaryview = summaryview;
+               debug_print("postponing open of message till end of load\n");
+               g_timeout_add(100, summary_select_retry, data);
+               return FALSE;
+       }
+       if (summary_is_locked(summaryview))
+               return FALSE;
        if (type == GTK_SCROLL_STEP_FORWARD) {
                node = gtkut_ctree_node_next(ctree, summaryview->selected);
                if (node)
@@ -3092,7 +3279,8 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                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 {
@@ -3101,7 +3289,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 {
@@ -3163,7 +3352,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);
 }
@@ -3187,7 +3377,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);
@@ -3212,8 +3403,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));
@@ -3241,13 +3433,13 @@ 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,
@@ -3262,8 +3454,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));
@@ -3276,8 +3469,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));
@@ -3291,6 +3485,7 @@ void summary_mark_all_read(SummaryView *summaryview)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node;
        AlertValue val;
+       gboolean froze = FALSE;
 
        if (prefs_common.ask_mark_all_read) {
                val = alertpanel_full(_("Mark all as read"),
@@ -3304,7 +3499,7 @@ void summary_mark_all_read(SummaryView *summaryview)
                        prefs_common.ask_mark_all_read = FALSE;
        }
        
-       START_LONG_OPERATION(summaryview);
+       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))
@@ -3328,9 +3523,11 @@ 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);
@@ -3347,21 +3544,22 @@ void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *wid
                                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) {
-                                       summary_move_row_to(summaryview, row, procmsg_spam_get_folder());
+                               if (procmsg_spam_get_folder(msginfo) != summaryview->folder_item) {
+                                       summary_move_row_to(summaryview, row,
+                                                       procmsg_spam_get_folder(msginfo));
                                        moved = TRUE;
                                }
                        } else {
                                summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
                        }
+                       summaryview->display_msg = prefs_common.always_show_msg;
+       
                        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);
@@ -3370,6 +3568,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);       
 }
 
@@ -3399,8 +3605,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)
@@ -3479,7 +3686,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 && 
@@ -3493,7 +3701,6 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
 void summary_cancel(SummaryView *summaryview)
 {
        MsgInfo * msginfo;
-       GtkCList *clist = GTK_CLIST(summaryview->ctree);
 
        msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree),
                                              summaryview->selected);
@@ -3508,12 +3715,12 @@ void summary_cancel(SummaryView *summaryview)
 
        summary_lock(summaryview);
 
-       gtk_clist_freeze(clist);
+       summary_freeze(summaryview);
 
        summary_update_status(summaryview);
        summary_status_show(summaryview);
 
-       gtk_clist_thaw(clist);
+       summary_thaw(summaryview);
 
        summary_unlock(summaryview);
 }
@@ -3527,6 +3734,7 @@ void summary_delete(SummaryView *summaryview)
        GtkCTreeNode *node;
        AlertValue aval;
        MsgInfo *msginfo;
+       gboolean froze = FALSE;
 
        if (!item) return;
 
@@ -3554,7 +3762,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);
@@ -3617,7 +3825,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",
@@ -3628,8 +3837,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));
@@ -3659,7 +3869,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);
@@ -3677,6 +3888,8 @@ 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 ||
            FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS) return;
@@ -3688,7 +3901,7 @@ 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) {
@@ -3749,7 +3962,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);
@@ -3765,6 +3979,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;
@@ -3777,7 +3992,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)
@@ -3837,16 +4052,18 @@ void summary_unselect_all(SummaryView *summaryview)
        summary_status_show(summaryview);
 }
 
-void summary_select_thread(SummaryView *summaryview)
+void summary_select_thread(SummaryView *summaryview, gboolean delete_thread)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node = summaryview->selected;
+       gboolean froze = FALSE;
 
        if (!node) return;
 
        while (GTK_CTREE_ROW(node)->parent != NULL)
                node = GTK_CTREE_ROW(node)->parent;
 
+       START_LONG_OPERATION(summaryview, FALSE);
        if (node != summaryview->selected)
                summary_select_node
                        (summaryview, node,
@@ -3854,7 +4071,14 @@ void summary_select_thread(SummaryView *summaryview)
                         FALSE);
 
        gtk_ctree_select_recursive(ctree, node);
+       END_LONG_OPERATION(summaryview);
 
+       if (delete_thread) {
+               if (FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS)
+                       summary_delete(summaryview);
+               else
+                       summary_delete_trash(summaryview);
+       }
        summary_status_show(summaryview);
 }
 
@@ -3906,10 +4130,10 @@ void summary_save_as(SummaryView *summaryview)
 
        if ( aval==0 ) { /* append */
                if (append_file(src, dest, TRUE) < 0) 
-                       alertpanel_error(_("Can't save the file '%s'."), tmp);
+                       alertpanel_error(_("Couldn't save the file '%s'."), tmp);
        } else { /* overwrite */
                if (copy_file(src, dest, TRUE) < 0)
-                       alertpanel_error(_("Can't save the file '%s'."), tmp);
+                       alertpanel_error(_("Couldn't save the file '%s'."), tmp);
        }
        g_free(src);
        
@@ -3924,7 +4148,7 @@ void summary_save_as(SummaryView *summaryview)
                        if (!msginfo) break;
                        src = procmsg_get_message_file(msginfo);
                        if (append_file(src, dest, TRUE) < 0)
-                               alertpanel_error(_("Can't save the file '%s'."), tmp);
+                               alertpanel_error(_("Couldn't save the file '%s'."), tmp);
                }
                g_free(src);
        }
@@ -3932,21 +4156,6 @@ void summary_save_as(SummaryView *summaryview)
        g_free(tmp);
 }
 
-#ifdef USE_GNOMEPRINT
-static void print_mimeview(MimeView *mimeview) 
-{
-       if (!mimeview 
-       ||  !mimeview->textview
-       ||  !mimeview->textview->text)
-               alertpanel_warning(_("Cannot print: the message doesn't "
-                                    "contain text."));
-       else {
-               gtk_widget_realize(mimeview->textview->text);
-               gedit_print(GTK_TEXT_VIEW(mimeview->textview->text));
-       }
-}
-#endif
-
 void summary_print(SummaryView *summaryview)
 {
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
@@ -3987,23 +4196,18 @@ void summary_print(SummaryView *summaryview)
             cur != NULL && cur->data != NULL; 
             cur = cur->next) {
                GtkCTreeNode *node = GTK_CTREE_NODE(cur->data);
-               if (node != summaryview->displayed) {
-                       MessageView *tmpview = messageview_create(
-                                               summaryview->mainwin);
-                       MsgInfo *msginfo = gtk_ctree_node_get_row_data(
-                                               GTK_CTREE(summaryview->ctree),
-                                               node);
-
-                       messageview_init(tmpview);
-                       tmpview->all_headers = summaryview->messageview->all_headers;
-                       if (msginfo && messageview_show(tmpview, msginfo, 
-                               tmpview->all_headers) >= 0) {
-                                       print_mimeview(tmpview->mimeview);
-                       }
-                       messageview_destroy(tmpview);
-               } else {
-                       print_mimeview(summaryview->messageview->mimeview);
-               }
+               MsgInfo *msginfo = gtk_ctree_node_get_row_data(
+                                       GTK_CTREE(summaryview->ctree),
+                                       node);
+               gint sel_start = -1, sel_end = -1, partnum = 0;
+               
+               if (node == summaryview->displayed) {
+                       partnum = mimeview_get_selected_part_num(summaryview->messageview->mimeview);
+                       textview_get_selection_offsets(summaryview->messageview->mimeview->textview,
+                               &sel_start, &sel_end);
+               } 
+               messageview_print(msginfo, summaryview->messageview->all_headers,
+                       sel_start, sel_end, partnum);
        }
 #endif
 }
@@ -4021,7 +4225,7 @@ gboolean summary_execute(SummaryView *summaryview)
        if (summary_is_locked(summaryview)) return FALSE;
        summary_lock(summaryview);
 
-       gtk_clist_freeze(clist);
+       summary_freeze(summaryview);
 
        main_window_cursor_wait(summaryview->mainwin);
 
@@ -4070,23 +4274,21 @@ gboolean summary_execute(SummaryView *summaryview)
        }
 
        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));
        }
 
+       summary_thaw(summaryview);
+
        summaryview->selected = clist->selection ?
                GTK_CTREE_NODE(clist->selection->data) : NULL;
 
@@ -4155,7 +4357,8 @@ 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 && 
+               if (prefs_common.thread_by_subject &&
+                   msginfo->subject && *msginfo->subject && 
                    node == subject_table_lookup(summaryview->subject_table,
                                                 msginfo->subject)) {
                        subject_table_remove(summaryview->subject_table,
@@ -4249,7 +4452,8 @@ static void summary_execute_delete_func(GtkCTree *ctree, GtkCTreeNode *node,
                        g_hash_table_remove(summaryview->msgid_table,
                                            msginfo->msgid);
                }       
-               if (msginfo->subject && *msginfo->subject && 
+               if (prefs_common.thread_by_subject &&
+                   msginfo->subject && *msginfo->subject && 
                    node == subject_table_lookup(summaryview->subject_table,
                                                 msginfo->subject)) {
                        subject_table_remove(summaryview->subject_table,
@@ -4277,7 +4481,7 @@ void summary_thread_build(SummaryView *summaryview)
 
        g_signal_handlers_block_by_func(G_OBJECT(ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       summary_freeze(summaryview);
 
        node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
        while (node) {
@@ -4316,7 +4520,7 @@ void summary_thread_build(SummaryView *summaryview)
 
        gtkut_ctree_set_focus_row(ctree, summaryview->selected);
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
+       summary_thaw(summaryview);
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
                                         G_CALLBACK(summary_tree_expanded), summaryview);
 
@@ -4334,7 +4538,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");
+       START_TIMING("");
        if (!summaryview->thread_collapsed) {
                g_signal_handlers_block_by_func(G_OBJECT(ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
@@ -4354,11 +4558,11 @@ 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, summaryview);
@@ -4430,7 +4634,7 @@ void summary_expand_threads(SummaryView *summaryview)
 
        g_signal_handlers_block_by_func(G_OBJECT(ctree),
                                       G_CALLBACK(summary_tree_expanded), summaryview);
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       summary_freeze(summaryview);
 
        while (node) {
                if (GTK_CTREE_ROW(node)->children) {
@@ -4440,7 +4644,7 @@ void summary_expand_threads(SummaryView *summaryview)
                node = GTK_CTREE_NODE_NEXT(node);
        }
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
+       summary_thaw(summaryview);
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
                                         G_CALLBACK(summary_tree_expanded), summaryview);
 
@@ -4454,7 +4658,7 @@ void summary_collapse_threads(SummaryView *summaryview)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
 
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       summary_freeze(summaryview);
 
        while (node) {
                if (GTK_CTREE_ROW(node)->children)
@@ -4462,19 +4666,19 @@ void summary_collapse_threads(SummaryView *summaryview)
                node = GTK_CTREE_ROW(node)->sibling;
        }
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
+       summary_thaw(summaryview);
        
        summaryview->thread_collapsed = TRUE;
 
        gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
-void account_rules_radio_button_toggled_cb(GtkToggleButton *btn, gpointer data)
+static 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)
+static gboolean summary_filter_get_mode(void)
 /* ask what to do w/ them: skip them, apply them regardless to the account,
    use the current account */
 {
@@ -4486,7 +4690,6 @@ gboolean summary_filter_get_mode(void)
        GtkWidget *account_rules_skip;
        GtkWidget *account_rules_force;
        GtkWidget *account_rules_user_current;
-       GSList *group;
        AlertValue val;
 
        vbox = gtk_vbox_new (FALSE, 0);
@@ -4498,7 +4701,7 @@ gboolean summary_filter_get_mode(void)
                                                        _("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"));
+                                                       _("Apply these rules if they apply to the current account"));
        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);
@@ -4530,8 +4733,8 @@ gboolean summary_filter_get_mode(void)
                        _("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) {
+                       GTK_STOCK_CANCEL, _("+_Filter"), 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;
@@ -4560,7 +4763,7 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
        STATUSBAR_PUSH(summaryview->mainwin, _("Filtering..."));
        main_window_cursor_wait(summaryview->mainwin);
 
-       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
+       summary_freeze(summaryview);
 
        if (selected_only) {
                GList *cur;
@@ -4584,7 +4787,7 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
        }
        g_slist_free(mlist);
 
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+       summary_thaw(summaryview);
 
        folder_item_update_thaw();
        debug_print("done.\n");
@@ -4605,6 +4808,9 @@ static void summary_filter_func(MsgInfo *msginfo)
        MailFilteringData mail_filtering_data;
 
        mail_filtering_data.msginfo = msginfo;
+       mail_filtering_data.msglist = NULL;                     
+       mail_filtering_data.filtered = NULL;                    
+       mail_filtering_data.unfiltered = NULL;                  
        if (hooks_invoke(MAIL_MANUAL_FILTERING_HOOKLIST, &mail_filtering_data))
                return;
 
@@ -4712,9 +4918,9 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
                style->fg[GTK_STATE_NORMAL] = color;
                /* get the average of label color and selected fg color
                   for visibility */
-               style->fg[GTK_STATE_SELECTED].red   = (color.red   + ctree_style->fg[GTK_STATE_SELECTED].red  ) / 2;
-               style->fg[GTK_STATE_SELECTED].green = (color.green + ctree_style->fg[GTK_STATE_SELECTED].green) / 2;
-               style->fg[GTK_STATE_SELECTED].blue  = (color.blue  + ctree_style->fg[GTK_STATE_SELECTED].blue ) / 2;
+               style->fg[GTK_STATE_SELECTED].red   = (color.red   + 3*ctree_style->fg[GTK_STATE_SELECTED].red  ) / 4;
+               style->fg[GTK_STATE_SELECTED].green = (color.green + 3*ctree_style->fg[GTK_STATE_SELECTED].green) / 4;
+               style->fg[GTK_STATE_SELECTED].blue  = (color.blue  + 3*ctree_style->fg[GTK_STATE_SELECTED].blue ) / 4;
        }
 
        gtk_ctree_node_set_row_style(ctree, node, style);
@@ -4739,9 +4945,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);
@@ -4935,9 +5141,19 @@ 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);
+       } 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);
+       }
+
+       gtk_sctree_set_stripes(GTK_SCTREE(ctree), prefs_common.use_stripes_in_summaries);
+
        gtk_ctree_set_indent(GTK_CTREE(ctree), 12);
        g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
@@ -5109,12 +5325,63 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        GtkAdjustment *adj;
        gboolean mod_pressed;
 
-       if (summary_is_locked(summaryview)) return TRUE;
-       if (!event) return TRUE;
+       if (!event) 
+               return TRUE;
 
        if (quicksearch_has_focus(summaryview->quicksearch))
                return FALSE;
 
+       messageview = summaryview->messageview;
+       textview = messageview->mimeview->textview;
+
+       mod_pressed =
+               ((event->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK)) != 0);
+
+       if (summaryview->selected) {
+               gboolean handled = FALSE;
+               switch (event->keyval) {
+               case GDK_space:         /* Page down or go to the next */
+                       handled = TRUE;
+                       if (event->state & GDK_CONTROL_MASK) 
+                               event->state &= ~GDK_CONTROL_MASK;
+                       if (event->state & GDK_SHIFT_MASK) 
+                               mimeview_scroll_page(messageview->mimeview, TRUE);
+                       else {
+                               if (summaryview->displayed != summaryview->selected) {
+                                       summary_display_msg(summaryview,
+                                                           summaryview->selected);
+                                       break;
+                               }
+                               if (mod_pressed) {
+                                       if (!mimeview_scroll_page(messageview->mimeview, TRUE))
+                                               summary_select_prev_unread(summaryview);
+                               } else {
+                                       if (!mimeview_scroll_page(messageview->mimeview, FALSE))
+                                               summary_select_next_unread(summaryview);
+                               }                               
+                       }
+                       break;
+               case GDK_BackSpace:     /* Page up */
+                       handled = TRUE;
+                       mimeview_scroll_page(messageview->mimeview, TRUE);
+                       break;
+               case GDK_Return:        /* Scroll up/down one line */
+                       handled = TRUE;
+                       if (summaryview->displayed != summaryview->selected) {
+                               summary_display_msg(summaryview,
+                                                   summaryview->selected);
+                               break;
+                       }
+                       mimeview_scroll_one_line(messageview->mimeview, mod_pressed);
+                       break;
+               }
+               
+               if (handled)
+                       return FALSE;
+       }
+       if (summary_is_locked(summaryview)) 
+               return TRUE;
+
        switch (event->keyval) {
        case GDK_Left:          /* Move focus */
                adj = gtk_scrolled_window_get_hadjustment
@@ -5135,7 +5402,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                                                g_list_length(GTK_CLIST(ctree)->row_list)-1);
                        if (next) {
                                gtk_sctree_select_with_state
-                                       (GTK_SCTREE(ctree), next, event->state);
+                                       (GTK_SCTREE(ctree), next, (event->state & ~GDK_CONTROL_MASK) );
 
                                /* Deprecated - what are the non-deprecated equivalents? */
                                if (gtk_ctree_node_is_visible(GTK_CTREE(ctree), next) != GTK_VISIBILITY_FULL)
@@ -5156,42 +5423,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                        return TRUE;
        }
 
-       messageview = summaryview->messageview;
-       textview = messageview->mimeview->textview;
-
-       mod_pressed =
-               ((event->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK)) != 0);
-
        switch (event->keyval) {
-       case GDK_space:         /* Page down or go to the next */
-               if (event->state & GDK_SHIFT_MASK) 
-                       textview_scroll_page(textview, TRUE);
-               else {
-                       if (summaryview->displayed != summaryview->selected) {
-                               summary_display_msg(summaryview,
-                                                   summaryview->selected);
-                               break;
-                       }
-                       if (mod_pressed) {
-                               if (!textview_scroll_page(textview, TRUE))
-                                       summary_select_prev_unread(summaryview);
-                       } else {
-                               if (!textview_scroll_page(textview, FALSE))
-                                       summary_select_next_unread(summaryview);
-                       }                               
-               }
-               break;
-       case GDK_BackSpace:     /* Page up */
-               textview_scroll_page(textview, TRUE);
-               break;
-       case GDK_Return:        /* Scroll up/down one line */
-               if (summaryview->displayed != summaryview->selected) {
-                       summary_display_msg(summaryview,
-                                           summaryview->selected);
-                       break;
-               }
-               textview_scroll_one_line(textview, mod_pressed);
-               break;
        case GDK_Delete:
                BREAK_ON_MODIFIER_KEY();
                summary_delete_trash(summaryview);
@@ -5233,12 +5465,18 @@ static void tog_searchbar_cb(GtkWidget *w, gpointer data)
        }
 }
 
-void summaryview_activate_quicksearch(SummaryView *summaryview) 
+void summaryview_activate_quicksearch(SummaryView *summaryview, gboolean show
 {
+       prefs_common.show_searchbar = show;
        gtk_toggle_button_set_active(
                GTK_TOGGLE_BUTTON(summaryview->toggle_search), 
-               TRUE);
-       quicksearch_show(summaryview->quicksearch);
+               show);
+       if (show) {
+               quicksearch_show(summaryview->quicksearch);
+       } else {
+               quicksearch_hide(summaryview->quicksearch);
+               summary_grab_focus(summaryview);
+       }
 }
 
 static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
@@ -5288,6 +5526,23 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        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->node = NULL;
+               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;
@@ -5457,7 +5712,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
                                         FolderSortKey sort_key)
 {
        GtkCTreeNode *node = NULL;
-       START_TIMING("summary_sort_by_column_click");
+       START_TIMING("");
        if (summaryview->sort_key == sort_key)
                summary_sort(summaryview, sort_key,
                             summaryview->sort_type == SORT_ASCENDING
@@ -5467,7 +5722,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));
+       summary_freeze(summaryview);
        if (prefs_common.bold_unread) {
                while (node) {
                        GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
@@ -5476,7 +5731,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
                        node = next;
                }
        }
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+       summary_thaw(summaryview);
        END_TIMING();
 }
 
@@ -5689,7 +5944,8 @@ static gint func_name(GtkCList *clist,                                     \
 CMP_FUNC_DEF(summary_cmp_by_mark,
             MSG_IS_MARKED(msginfo1->flags) - MSG_IS_MARKED(msginfo2->flags))
 CMP_FUNC_DEF(summary_cmp_by_status,
-            MSG_IS_UNREAD(msginfo1->flags) - MSG_IS_UNREAD(msginfo2->flags))
+            (-(MSG_IS_SPAM(msginfo1->flags))+(MSG_IS_UNREAD(msginfo1->flags)<<1)+(MSG_IS_NEW(msginfo1->flags)<<2)) 
+            - (-(MSG_IS_SPAM(msginfo2->flags))+(MSG_IS_UNREAD(msginfo2->flags)<<1)+(MSG_IS_NEW(msginfo2->flags)<<2)) )
 CMP_FUNC_DEF(summary_cmp_by_mime,
             MSG_IS_WITH_ATTACHMENT(msginfo1->flags) - MSG_IS_WITH_ATTACHMENT(msginfo2->flags))
 CMP_FUNC_DEF(summary_cmp_by_label,
@@ -5812,38 +6068,6 @@ 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;
@@ -5859,12 +6083,13 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin
            msginfo->msgnum);
 }
 
-static void summary_ignore_thread(SummaryView *summaryview)
+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), 
@@ -5890,12 +6115,13 @@ static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpo
            msginfo->msgnum);
 }
 
-static void summary_unignore_thread(SummaryView *summaryview)
+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), 
@@ -5986,6 +6212,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);
@@ -6064,6 +6292,8 @@ static regex_t *summary_compile_simplify_regexp(gchar *simplify_subject_regexp)
 
 void summary_set_prefs_from_folderitem(SummaryView *summaryview, FolderItem *item)
 {
+       FolderSortKey sort_key;
+       FolderSortType sort_type;
        g_return_if_fail(summaryview != NULL);
        g_return_if_fail(item != NULL);
 
@@ -6078,8 +6308,13 @@ void summary_set_prefs_from_folderitem(SummaryView *summaryview, FolderItem *ite
                summaryview->simplify_subject_preg = summary_compile_simplify_regexp(item->prefs->simplify_subject_regexp);
 
        /* Sorting */
-       summaryview->sort_key = item->sort_key;
-       summaryview->sort_type = item->sort_type;
+       sort_key = item->sort_key;
+       sort_type = item->sort_type;
+
+       folder_get_sort_type(item->folder, &sort_key, &sort_type);
+
+       summaryview->sort_key = sort_key;
+       summaryview->sort_type = sort_type;
 
        /* Threading */
        summaryview->threaded = item->threaded;
@@ -6123,6 +6358,24 @@ static gboolean summary_update_msg(gpointer source, gpointer data)
        return FALSE;
 }
 
+static gboolean summary_update_folder_item_name(gpointer source, gpointer data)
+{
+       FolderItemUpdateData *hookdata = (FolderItemUpdateData *)source;
+       SummaryView *summaryview = (SummaryView *)data;
+
+       g_return_val_if_fail(hookdata != NULL, FALSE);
+       g_return_val_if_fail(hookdata->item != NULL, FALSE);
+       g_return_val_if_fail(summaryview != NULL, FALSE);
+
+       if (hookdata->update_flags & F_ITEM_UPDATE_NAME) {
+               gchar *name = folder_item_get_name(hookdata->item);
+               gtk_label_set_text(GTK_LABEL(summaryview->statlabel_folder), name);
+               g_free(name);
+       }
+
+       return FALSE;
+}
+
 /*!
  *\brief       change summaryview to display your answer(s) to a message
  *