2006-05-18 [colin] 2.2.0cvs33
[claws.git] / src / summaryview.c
index 0960971177ebc7631721aa150c7c5e2ca525489b..86a1576545eb4c23d2a637d69d4713b040bef6e4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #include "defs.h"
@@ -87,6 +87,7 @@
 #include "partial_download.h"
 #include "timing.h"
 #include "gedit-print.h"
+#include "log.h"
 
 #define SUMMARY_COL_MARK_WIDTH         10
 #define SUMMARY_COL_STATUS_WIDTH       13
@@ -118,6 +119,8 @@ static GdkPixmap *ignorethreadxpm;
 static GdkBitmap *ignorethreadxpmmask;
 static GdkPixmap *lockedxpm;
 static GdkBitmap *lockedxpmmask;
+static GdkPixmap *spamxpm;
+static GdkBitmap *spamxpmmask;
 
 static GdkPixmap *clipxpm;
 static GdkBitmap *clipxpmmask;
@@ -137,14 +140,14 @@ static void summary_set_marks_func        (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
                                         gpointer                data);
 
-static void summary_set_menu_sensitive (SummaryView            *summaryview);
+void  summary_set_menu_sensitive       (SummaryView            *summaryview);
+guint summary_get_msgnum               (SummaryView            *summaryview,
+                                        GtkCTreeNode           *node);
+
 
 static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                                             guint action);
 
-static guint summary_get_msgnum                (SummaryView            *summaryview,
-                                        GtkCTreeNode           *node);
-
 static GtkCTreeNode *summary_find_prev_msg
                                        (SummaryView            *summaryview,
                                         GtkCTreeNode           *current_node);
@@ -176,7 +179,8 @@ static void summary_set_ctree_from_list     (SummaryView            *summaryview,
                                         GSList                 *mlist);
 static void summary_set_header         (SummaryView            *summaryview,
                                         gchar                  *text[],
-                                        MsgInfo                *msginfo);
+                                        MsgInfo                *msginfo,
+                                        gboolean               *free_from);
 static void summary_display_msg                (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
 static void summary_display_msg_full   (SummaryView            *summaryview,
@@ -208,7 +212,7 @@ static void summary_copy_row_to             (SummaryView            *summaryview,
                                         GtkCTreeNode           *row,
                                         FolderItem             *to_folder);
 
-static void summary_execute_move       (SummaryView            *summaryview);
+static gint summary_execute_move       (SummaryView            *summaryview);
 static void summary_execute_move_func  (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
                                         gpointer                data);
@@ -233,12 +237,7 @@ static void summary_unthread_for_exec_func (GtkCTree       *ctree,
 void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
                              GSList * mlist);
 
-#if 0
-void summary_processing(SummaryView *summaryview, GSList * mlist);
-#endif
-static void summary_filter_func                (GtkCTree               *ctree,
-                                        GtkCTreeNode           *node,
-                                        gpointer                data);
+static void summary_filter_func                (MsgInfo *msginfo);
 
 static void summary_colorlabel_menu_item_activate_cb
                                          (GtkWidget    *widget,
@@ -246,7 +245,8 @@ static void summary_colorlabel_menu_item_activate_cb
 static void summary_colorlabel_menu_item_activate_item_cb
                                          (GtkMenuItem  *label_menu_item,
                                           gpointer      data);
-static void summary_colorlabel_menu_create(SummaryView *summaryview);
+static void summary_colorlabel_menu_create(SummaryView *summaryview,
+                                          gboolean  refresh);
 
 static GtkWidget *summary_ctree_create (SummaryView    *summaryview);
 
@@ -275,6 +275,10 @@ static void summary_selected               (GtkCTree               *ctree,
                                         GtkCTreeNode           *row,
                                         gint                    column,
                                         SummaryView            *summaryview);
+static void summary_unselected         (GtkCTree               *ctree,
+                                        GtkCTreeNode           *row,
+                                        gint                    column,
+                                        SummaryView            *summaryview);
 static void summary_col_resized                (GtkCList               *clist,
                                         gint                    column,
                                         gint                    width,
@@ -331,6 +335,20 @@ static void summary_drag_data_get       (GtkWidget        *widget,
                                         guint             info,
                                         guint             time,
                                         SummaryView      *summaryview);
+static void summary_drag_data_received(GtkWidget        *widget,
+                                       GdkDragContext   *drag_context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *data,
+                                       guint             info,
+                                       guint             time,
+                                       SummaryView       *summaryview);
+static gboolean summary_drag_motion_cb(GtkWidget      *widget,
+                                         GdkDragContext *context,
+                                         gint            x,
+                                         gint            y,
+                                         guint           time,
+                                         SummaryView    *summaryview);
 
 /* custom compare functions for sorting */
 
@@ -387,9 +405,10 @@ static void summary_find_answers   (SummaryView    *summaryview,
 
 static gboolean summary_update_msg     (gpointer source, gpointer data);
 
-GtkTargetEntry summary_drag_types[1] =
+GtkTargetEntry summary_drag_types[2] =
 {
-       {"text/plain", GTK_TARGET_SAME_APP, TARGET_DUMMY}
+       {"text/uri-list", 0, TARGET_MAIL_URI_LIST},
+       {"sylpheed-claws/internal", GTK_TARGET_SAME_APP, TARGET_DUMMY}
 };
 
 static GtkItemFactoryEntry summary_popup_entries[] =
@@ -400,16 +419,15 @@ 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_("/Follow-up and reply to"), NULL, summary_reply_cb, COMPOSE_FOLLOWUP_AND_REPLY_TO, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/_Forward"),               "<control><alt>F", summary_reply_cb, COMPOSE_FORWARD, NULL},
+       {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>"},
        {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_("/Cancel a news message"),  NULL, summary_cancel,   0, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/_Mark"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_Mark/_Mark"),            NULL, summary_mark,     0, NULL},
@@ -420,12 +438,14 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/_Mark/Mark all read"),    NULL, summary_mark_all_read, 0, NULL},
        {N_("/_Mark/Ignore thread"),    NULL, summary_ignore_thread, 0, NULL},
        {N_("/_Mark/Unignore thread"),  NULL, summary_unignore_thread, 0, NULL},
+       {N_("/_Mark/---"),              NULL, NULL, 0, "<Separator>"},
+       {N_("/_Mark/Mark as _spam"),    NULL, summary_mark_as_spam, 1, NULL},
+       {N_("/_Mark/Mark as _ham"),     NULL, summary_mark_as_spam, 0, NULL},
+       {N_("/_Mark/---"),              NULL, NULL, 0, "<Separator>"},
        {N_("/_Mark/Lock"),             NULL, summary_msgs_lock, 0, NULL},
        {N_("/_Mark/Unlock"),           NULL, summary_msgs_unlock, 0, NULL},
        {N_("/Color la_bel"),           NULL, NULL,             0, NULL},
 
-       {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/Re-_edit"),               NULL, summary_reedit,   0, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/Add sender to address boo_k"),
                                        NULL, summary_add_address_cb, 0, NULL},
@@ -453,10 +473,13 @@ static GtkItemFactoryEntry summary_popup_entries[] =
                                        "<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_("/_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 */
 
 static const gchar *const col_label[N_SUMMARY_COLS] = {
-       N_("M"),        /* S_COL_MARK    */
+       "",             /* S_COL_MARK    */
        N_("S"),        /* S_COL_STATUS  */
        "",             /* S_COL_MIME    */
        N_("Subject"),  /* S_COL_SUBJECT */
@@ -464,9 +487,9 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        N_("To"),       /* S_COL_TO      */
        N_("Date"),     /* S_COL_DATE    */
        N_("Size"),     /* S_COL_SIZE    */
-       N_("No."),      /* S_COL_NUMBER  */
+       N_("#"),        /* S_COL_NUMBER  */
        N_("Score"),    /* S_COL_SCORE   */
-       N_("L")         /* S_COL_LOCKED  */
+       "",             /* S_COL_LOCKED  */
 };
 
 #define START_LONG_OPERATION(summaryview) {                    \
@@ -523,7 +546,7 @@ SummaryView *summary_create(void)
 
        gtk_tooltips_set_tip(GTK_TOOLTIPS(search_tip),
                             toggle_search,
-                            _("Toggle quick-search bar"), NULL);
+                            _("Toggle quick search bar"), NULL);
        
        gtk_box_pack_start(GTK_BOX(hbox), toggle_search, FALSE, FALSE, 2);      
 
@@ -613,7 +636,7 @@ SummaryView *summary_create(void)
        summaryview->msginfo_update_callback_id =
                hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview);
 
-       summaryview->target_list = gtk_target_list_new(summary_drag_types, 1);
+       summaryview->target_list = gtk_target_list_new(summary_drag_types, 2);
 
        summaryview->quicksearch = quicksearch;
 
@@ -645,7 +668,7 @@ static void summary_set_fonts(SummaryView *summaryview)
        if (!bold_style) {
                bold_style = gtk_style_copy
                        (gtk_widget_get_style(summaryview->ctree));
-               font_desc = pango_font_description_from_string(BOLD_FONT);
+               font_desc = pango_font_description_from_string(NORMAL_FONT);
                if (font_desc) {
                        pango_font_description_free(bold_style->font_desc);
                        bold_style->font_desc = font_desc;
@@ -702,6 +725,8 @@ void summary_init(SummaryView *summaryview)
                         &gpgsignedxpm, &gpgsignedxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_CLIP_GPG_SIGNED,
                         &clipgpgsignedxpm, &clipgpgsignedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_SPAM,
+                        &spamxpm, &spamxpmmask);
 
        summary_set_fonts(summaryview);
 
@@ -725,78 +750,78 @@ void summary_init(SummaryView *summaryview)
 
        summary_clear_list(summaryview);
        summary_set_column_titles(summaryview);
-       summary_colorlabel_menu_create(summaryview);
+       summary_colorlabel_menu_create(summaryview, FALSE);
+       main_create_mailing_list_menu (summaryview->mainwin, NULL);     
        summary_set_menu_sensitive(summaryview);
 
 }
 
-#if 0
-GtkCTreeNode * summary_find_next_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
+#define CURRENTLY_DISPLAYED(m) \
+( (m->msgnum == displayed_msgnum) \
+  && (!g_ascii_strcasecmp(m->folder->name,item->name)) )
 
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_NEXT(current_node);
+#define FOLDER_SHOWS_TO_HDR(i) \
+( folder_has_parent_of_type(i, F_OUTBOX) \
+  ||  folder_has_parent_of_type(i, F_DRAFT) \
+  ||  folder_has_parent_of_type(i, F_QUEUE) )
+  
+static void summary_switch_from_to(SummaryView *summaryview, FolderItem *item)
+{
+       gboolean show_from = FALSE, show_to = FALSE;
+       gboolean showing_from = FALSE, showing_to = FALSE;
+       gint from_pos = 0, to_pos = 0;
+       SummaryColumnState *col_state = summaryview->col_state;
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       
+       if (!item)
+               return;
+       if(FOLDER_SHOWS_TO_HDR(item))
+               show_to = TRUE;
        else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
+               show_from = TRUE;
+       
+       from_pos = summaryview->col_pos[S_COL_FROM];
+       to_pos = summaryview->col_pos[S_COL_TO];
+       showing_from = col_state[from_pos].visible;
+       showing_to = col_state[to_pos].visible;
+       
+       if (showing_from && showing_to) {
+               debug_print("showing both\n");
+               return;
+       }
 
-       for (; node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
+       if (!showing_from && !showing_to) {
+               debug_print("showing none\n");
+               return;
        }
 
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
+       debug_print("showing %s %s, must show %s %s\n", 
+               showing_from?"From":"",
+               showing_to?"To":"",
+               show_from?"From":"",
+               show_to?"To":"");
 
-GtkCTreeNode * summary_find_prev_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
+       if (showing_from == show_from && showing_to == show_to)
+               return;
+       /* else we'll switch both */
 
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_PREV(current_node);
-       else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
+       debug_print("switching columns\n");
+       col_state[from_pos].type = S_COL_TO;
+       col_state[from_pos].visible = show_to;
 
-       for (; node != NULL; node = GTK_CTREE_NODE_PREV(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
-       }
+       col_state[to_pos].type = S_COL_FROM;
+       col_state[to_pos].visible = show_from;
 
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
-#endif
+       summaryview->col_pos[S_COL_TO] = from_pos;
+       summaryview->col_pos[S_COL_FROM] = to_pos;
 
-#define CURRENTLY_DISPLAYED(m) \
-( (m->msgnum == displayed_msgnum) \
-  && (!g_ascii_strcasecmp(m->folder->name,item->name)) )
+       gtk_clist_set_column_visibility
+               (GTK_CLIST(ctree), from_pos, col_state[from_pos].visible);
+       gtk_clist_set_column_visibility
+               (GTK_CLIST(ctree), to_pos, col_state[to_pos].visible);
+
+       summary_set_column_titles(summaryview);
+}
 
 gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 {
@@ -809,21 +834,32 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        guint displayed_msgnum = 0;
        GSList *cur;
         GSList *not_killed;
+       gboolean hidden_removed = FALSE;
 
        if (summary_is_locked(summaryview)) return FALSE;
 
+       if (!summaryview->mainwin)
+               return FALSE;
+
+       summary_switch_from_to(summaryview, item);
+
        inc_lock();
        summary_lock(summaryview);
 
+       is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
+
+       if (!is_refresh)
+               main_create_mailing_list_menu (summaryview->mainwin, NULL);
+
        if (!prefs_common.summary_quicksearch_sticky
         && !prefs_common.summary_quicksearch_recurse
-        && !quicksearch_is_running(summaryview->quicksearch)) {
+        && !quicksearch_is_running(summaryview->quicksearch)
+        && !is_refresh) {
                quicksearch_set(summaryview->quicksearch, prefs_common.summary_quicksearch_type, "");
        }
 
        /* STATUSBAR_POP(summaryview->mainwin); */
 
-       is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
        if (is_refresh) {
                selected_msgnum = summary_get_msgnum(summaryview,
                                                     summaryview->selected);
@@ -838,14 +874,14 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                gboolean changed = FALSE;
 
                val = alertpanel(_("Process mark"),
-                                _("Some marks are left. Process it?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, GTK_STOCK_CANCEL);
-               if (G_ALERTDEFAULT == val) {
+                                _("Some marks are left. Process them?"),
+                                GTK_STOCK_NO, GTK_STOCK_YES, GTK_STOCK_CANCEL);
+               if (G_ALERTALTERNATE == val) {
                        summary_unlock(summaryview);
                        summary_execute(summaryview);
                        summary_lock(summaryview);
                        changed = TRUE;
-               } else if (G_ALERTALTERNATE == val) {
+               } else if (G_ALERTDEFAULT == val) {
                        /* DO NOTHING */
                } else {
                        summary_unlock(summaryview);
@@ -859,7 +895,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        gtk_clist_freeze(GTK_CLIST(ctree));
 
        summary_clear_list(summaryview);
-       summary_set_column_titles(summaryview);
 
        buf = NULL;
        if (!item || !item->path || !folder_item_parent(item) || item->no_select) {
@@ -908,12 +943,23 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
                        
-                       if (MSG_IS_UNREAD(msginfo->flags) &&
-                           !MSG_IS_IGNORE_THREAD(msginfo->flags))
-                               not_killed = g_slist_prepend(not_killed, msginfo);
-                       else
-                               procmsg_msginfo_free(msginfo);
+                       if (!msginfo->hidden) {
+                               if (MSG_IS_UNREAD(msginfo->flags) &&
+                                   !MSG_IS_IGNORE_THREAD(msginfo->flags))
+                                       not_killed = g_slist_prepend(not_killed, msginfo);
+                               else if (MSG_IS_MARKED(msginfo->flags) ||
+                                        MSG_IS_LOCKED(msginfo->flags))
+                                       not_killed = g_slist_prepend(not_killed, msginfo);
+                               else if (is_refresh &&
+                                       (msginfo->msgnum == selected_msgnum ||
+                                        msginfo->msgnum == displayed_msgnum))
+                                       not_killed = g_slist_prepend(not_killed, msginfo);
+                               else
+                                       procmsg_msginfo_free(msginfo);
+                        } else
+                               procmsg_msginfo_free(msginfo);
                }
+               hidden_removed = TRUE;
                g_slist_free(mlist);
                mlist = not_killed;
        } else {
@@ -922,17 +968,29 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
                GSList *not_killed;
-               
+               gint num = 0, total = summaryview->folder_item->total_msgs;
+               statusbar_print_all(_("Searching in %s... \n"), 
+                       summaryview->folder_item->path ? 
+                       summaryview->folder_item->path : "(null)");
                not_killed = NULL;
                for (cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
 
-                       if (quicksearch_match(summaryview->quicksearch, msginfo))
+                       statusbar_progress_all(num++,total, 50);
+
+                       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 (!quicksearch_is_active(summaryview->quicksearch)) {
+                               break;
+                       }
                }
+               statusbar_progress_all(0,0,0);
+               statusbar_pop_all();
                
+               hidden_removed = TRUE;
                if (quicksearch_is_running(summaryview->quicksearch)) {
                        /* only scan subfolders when quicksearch changed,
                         * not when search is the same and folder changed */
@@ -943,43 +1001,34 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                              summaryview->folder_item);
                        main_window_cursor_normal(summaryview->mainwin);
                }
-               
+
+               if (!quicksearch_is_active(summaryview->quicksearch)) {
+                       debug_print("search cancelled!\n");
+                       gtk_clist_thaw(GTK_CLIST(ctree));
+                       STATUSBAR_POP(summaryview->mainwin);
+                       main_window_cursor_normal(summaryview->mainwin);
+                       summary_unlock(summaryview);
+                       inc_unlock();
+                       summary_show(summaryview, summaryview->folder_item);
+                       return FALSE;
+               }
                g_slist_free(mlist);
                mlist = not_killed;
        }
 
-#if 0  
-       if ((global_scoring || item->prefs->scoring)) {
-               GSList *not_killed;
-               gint kill_score;
-
-               not_killed = NULL;
-               kill_score = prefs_common.kill_score;
-               if (item->prefs->kill_score > kill_score)
-                       kill_score = item->prefs->kill_score;
-               for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
-                       MsgInfo * msginfo = (MsgInfo *) cur->data;
+       if (!hidden_removed) {
+               not_killed = NULL;
+               for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
+                       MsgInfo * msginfo = (MsgInfo *) cur->data;
 
-                       if (msginfo->score > kill_score)
-                               not_killed = g_slist_prepend(not_killed, msginfo);
-                       else
-                               procmsg_msginfo_free(msginfo);
-               }
+                       if (!msginfo->hidden)
+                               not_killed = g_slist_prepend(not_killed, msginfo);
+                       else
+                               procmsg_msginfo_free(msginfo);
+               }
                g_slist_free(mlist);
                mlist = not_killed;
        }
-#endif
-        not_killed = NULL;
-        for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
-                MsgInfo * msginfo = (MsgInfo *) cur->data;
-                
-                if (!msginfo->hidden)
-                        not_killed = g_slist_prepend(not_killed, msginfo);
-                else
-                        procmsg_msginfo_free(msginfo);
-        }
-        g_slist_free(mlist);
-        mlist = not_killed;
 
        STATUSBAR_POP(summaryview->mainwin);
 
@@ -989,8 +1038,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        g_slist_free(mlist);
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
-
        if (is_refresh) {
                summaryview->displayed =
                        summary_find_msg_by_msgnum(summaryview,
@@ -1016,16 +1063,62 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                }
        } else {
                switch (prefs_common.select_on_entry) {
-                       case SELECTONENTRY_NEW:
+                       case SELECTONENTRY_MNU:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               break;
+                       case SELECTONENTRY_MUN:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               break;
+                       case SELECTONENTRY_NMU:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               break;
+                       case SELECTONENTRY_NUM:
                                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_NEW, FALSE);
                                if (node == NULL)
                                        node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
+                               break;
+                       case SELECTONENTRY_UNM:
+                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_NEW, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
                                break;
-                       case SELECTONENTRY_UNREAD:
+                       case SELECTONENTRY_UMN:
                                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_UNREAD, FALSE);
+                               if (node == NULL)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                                                    MSG_MARKED, FALSE);
                                if (node == NULL)
                                        node = summary_find_next_flagged_msg(summaryview, NULL,
                                                                     MSG_NEW, FALSE);
@@ -1047,11 +1140,11 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                summary_lock(summaryview);
        }
 
-       summary_set_column_titles(summaryview);
        summary_status_show(summaryview);
        summary_set_menu_sensitive(summaryview);
        toolbar_main_set_sensitive(summaryview->mainwin);
-
+       
+       gtk_clist_thaw(GTK_CLIST(ctree));
        debug_print("\n");
        STATUSBAR_PUSH(summaryview->mainwin, _("Done."));
        STATUSBAR_POP(summaryview->mainwin);
@@ -1204,7 +1297,7 @@ GSList *summary_get_msg_list(SummaryView *summaryview)
        return mlist;
 }
 
-static void summary_set_menu_sensitive(SummaryView *summaryview)
+void summary_set_menu_sensitive(SummaryView *summaryview)
 {
        GtkItemFactory *ifactory = summaryview->popupfactory;
        SensitiveCond state;
@@ -1216,23 +1309,20 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
                gchar *const entry;
                SensitiveCond cond;
        } entry[] = {
-               {"/Reply"                       , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to"                    , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/all"                , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/sender"             , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Reply to/mailing list"       , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
-               {"/Follow-up and reply to"      , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST|M_NEWS},
+               {"/Reply"                       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/all"                , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/sender"             , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Reply to/mailing list"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
 
                {"/Forward"                     , M_HAVE_ACCOUNT|M_TARGET_EXIST},
-               {"/Redirect"                    , M_HAVE_ACCOUNT|M_SINGLE_TARGET_EXIST},
+               {"/Forward as attachment"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+               {"/Redirect"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
 
-               {"/Re-edit"                     , M_HAVE_ACCOUNT|M_ALLOW_REEDIT},
-
-               {"/Move..."                     , M_TARGET_EXIST|M_ALLOW_DELETE|M_UNLOCKED|M_NOT_NEWS},
-               {"/Copy..."                     , M_TARGET_EXIST|M_EXEC|M_UNLOCKED},
-               {"/Move to trash"               , M_TARGET_EXIST|M_ALLOW_DELETE|M_UNLOCKED|M_NOT_NEWS},
-               {"/Delete..."                   , M_TARGET_EXIST|M_ALLOW_DELETE|M_UNLOCKED|M_NOT_NEWS},
-               {"/Cancel a news message"       , M_TARGET_EXIST|M_ALLOW_DELETE|M_UNLOCKED|M_NEWS},
+               {"/Move..."                     , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
+               {"/Copy..."                     , M_TARGET_EXIST|M_EXEC},
+               {"/Move to trash"               , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
+               {"/Delete..."                   , M_TARGET_EXIST|M_ALLOW_DELETE},
 
                {"/Mark"                        , M_TARGET_EXIST},
                {"/Mark/Mark"                   , M_TARGET_EXIST},
@@ -1242,6 +1332,8 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
                {"/Mark/Ignore 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},
+               {"/Mark/Mark as ham"            , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
                {"/Color label"                 , M_TARGET_EXIST},
 
                {"/Add sender to address book"  , M_SINGLE_TARGET_EXIST},
@@ -1252,13 +1344,8 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
                {"/View/Open in new window"     , M_SINGLE_TARGET_EXIST},
                {"/View/Source"                 , M_SINGLE_TARGET_EXIST},
                {"/View/All header"             , M_SINGLE_TARGET_EXIST},
-#if 0
-               {"/Save as..."                  , M_TARGET_EXIST|M_UNLOCKED},
-               {"/Print..."                    , M_TARGET_EXIST|M_UNLOCKED},
-
-               {"/Select thread"               , M_SINGLE_TARGET_EXIST},
-               {"/Select all"                  , M_TARGET_EXIST},
-#endif
+               {"/Save as..."                  , M_TARGET_EXIST},
+               {"/Print..."                    , M_TARGET_EXIST},
                {NULL, 0}
        };
 
@@ -1274,9 +1361,12 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
 
        summary_lock(summaryview);
        menuitem = gtk_item_factory_get_widget(ifactory, "/View/All header");
-       gtk_check_menu_item_set_active
-               (GTK_CHECK_MENU_ITEM(menuitem),
-                summaryview->messageview->mimeview->textview->show_all_headers);
+       if (summaryview->messageview 
+       &&  summaryview->messageview->mimeview
+       &&  summaryview->messageview->mimeview->textview)
+               gtk_check_menu_item_set_active
+                       (GTK_CHECK_MENU_ITEM(menuitem),
+                        summaryview->messageview->mimeview->textview->show_all_headers);
        summary_unlock(summaryview);
 }
 
@@ -1294,7 +1384,7 @@ void summary_select_prev_unread(SummaryView *summaryview)
        node = summary_find_prev_flagged_msg
                (summaryview, summaryview->selected, MSG_UNREAD, skip_cur);
 
-       if (!node) {
+       if (!node || node == summaryview->selected) {
                AlertValue val = 0;
 
                switch (prefs_common.next_unread_msg_dialog) {
@@ -1302,19 +1392,19 @@ void summary_select_prev_unread(SummaryView *summaryview)
                                val = alertpanel(_("No more unread messages"),
                                                 _("No unread message found. "
                                                   "Search from the end?"),
-                                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                               val = G_ALERTDEFAULT;
+                               val = G_ALERTALTERNATE;
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_NO:
-                               val = !G_ALERTDEFAULT;
+                               val = !G_ALERTALTERNATE;
                                break;
                        default:
                                debug_print(
                                        _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                }
-               if (val != G_ALERTDEFAULT) return;
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_UNREAD, FALSE);
        }
@@ -1328,7 +1418,6 @@ void summary_select_prev_unread(SummaryView *summaryview)
 void summary_select_next_unread(SummaryView *summaryview)
 {
        GtkCTreeNode *node = summaryview->selected;
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        gboolean skip_cur = FALSE;
        
        if (summaryview->displayed 
@@ -1347,7 +1436,7 @@ void summary_select_next_unread(SummaryView *summaryview)
        else {
                node = summary_find_next_flagged_msg
                        (summaryview, NULL, MSG_UNREAD, FALSE);
-               if (node == NULL) {
+               if (node == NULL || node == summaryview->selected) {
                        AlertValue val = 0;
 
                        switch (prefs_common.next_unread_msg_dialog) {
@@ -1355,10 +1444,10 @@ void summary_select_next_unread(SummaryView *summaryview)
                                        val = alertpanel(_("No more unread messages"),
                                                         _("No unread message found. "
                                                           "Go to next folder?"),
-                                                        GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+                                                        GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_YES:
-                                       val = G_ALERTDEFAULT;
+                                       val = G_ALERTALTERNATE;
                                        break;
                                case NEXTUNREADMSGDIALOG_ASSUME_NO:
                                        val = G_ALERTOTHER;
@@ -1368,9 +1457,7 @@ void summary_select_next_unread(SummaryView *summaryview)
                                                _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
                        }
 
-                       if (val == G_ALERTDEFAULT) {
-                               g_signal_stop_emission_by_name(G_OBJECT(ctree),
-                                                        "key_press_event");
+                       if (val == G_ALERTALTERNATE) {
                                folderview_select_next_unread(summaryview->folderview);
                                return;
                        } 
@@ -1385,18 +1472,38 @@ void summary_select_next_unread(SummaryView *summaryview)
 void summary_select_prev_new(SummaryView *summaryview)
 {
        GtkCTreeNode *node;
+       gboolean skip_cur = FALSE;
+
+       if (summaryview->displayed 
+       &&  summaryview->selected == summaryview->displayed) {
+               debug_print("skipping current\n");
+               skip_cur = TRUE;
+       }
 
        node = summary_find_prev_flagged_msg
-               (summaryview, summaryview->selected, MSG_NEW, FALSE);
+               (summaryview, summaryview->selected, MSG_NEW, skip_cur);
 
-       if (!node) {
-               AlertValue val;
+       if (!node || node == summaryview->selected) {
+               AlertValue val = 0;
 
-               val = alertpanel(_("No more new messages"),
-                                _("No new message found. "
-                                  "Search from the end?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+               switch (prefs_common.next_unread_msg_dialog) {
+                       case NEXTUNREADMSGDIALOG_ALWAYS:
+                               val = alertpanel(_("No more new messages"),
+                                                _("No new message found. "
+                                                  "Search from the end?"),
+                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                               break;
+                       case NEXTUNREADMSGDIALOG_ASSUME_YES:
+                               val = G_ALERTALTERNATE;
+                               break;
+                       case NEXTUNREADMSGDIALOG_ASSUME_NO:
+                               val = !G_ALERTALTERNATE;
+                               break;
+                       default:
+                               debug_print(
+                                       _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
+               }
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_NEW, FALSE);
        }
@@ -1410,29 +1517,55 @@ void summary_select_prev_new(SummaryView *summaryview)
 void summary_select_next_new(SummaryView *summaryview)
 {
        GtkCTreeNode *node = summaryview->selected;
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-
-       while ((node = summary_find_next_flagged_msg
-               (summaryview, node, MSG_NEW, FALSE)) == NULL) {
-               AlertValue val;
-
-               val = alertpanel(_("No more new messages"),
-                                _("No new message found. "
-                                  "Go to next folder?"),
-                                GTK_STOCK_YES, _("_Search again"),
-                                GTK_STOCK_NO);
-               if (val == G_ALERTDEFAULT) {
-                       g_signal_stop_emission_by_name(G_OBJECT(ctree),"key_press_event");
-                       folderview_select_next_unread(summaryview->folderview);
-                       return;
-               } else if (val == G_ALERTALTERNATE)
-                       node = NULL;
-               else
-                       return;
+       gboolean skip_cur = FALSE;
+       
+       if (summaryview->displayed 
+       &&  summaryview->selected == summaryview->displayed) {
+               debug_print("skipping cur (%p %p)\n",
+                       summaryview->displayed, summaryview->selected);
+               skip_cur = TRUE;
        }
 
+
+       node = summary_find_next_flagged_msg
+               (summaryview, node, MSG_NEW, skip_cur);
+       
        if (node)
                summary_select_node(summaryview, node, TRUE, FALSE);
+       else {
+               node = summary_find_next_flagged_msg
+                       (summaryview, NULL, MSG_NEW, FALSE);
+               if (node == NULL || node == summaryview->selected) {
+                       AlertValue val = 0;
+
+                       switch (prefs_common.next_unread_msg_dialog) {
+                               case NEXTUNREADMSGDIALOG_ALWAYS:
+                                       val = alertpanel(_("No more new messages"),
+                                                        _("No new message found. "
+                                                          "Go to next folder?"),
+                                                        GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                       break;
+                               case NEXTUNREADMSGDIALOG_ASSUME_YES:
+                                       val = G_ALERTALTERNATE;
+                                       break;
+                               case NEXTUNREADMSGDIALOG_ASSUME_NO:
+                                       val = G_ALERTOTHER;
+                                       break;
+                               default:
+                                       debug_print(
+                                               _("Internal error: unexpected value for prefs_common.next_unread_msg_dialog\n"));
+                       }
+
+                       if (val == G_ALERTALTERNATE) {
+                               folderview_select_next_new(summaryview->folderview);
+                               return;
+                       } 
+                       else
+                               return;
+               } else
+                       summary_select_node(summaryview, node, TRUE, FALSE);
+
+       }
 }
 
 void summary_select_prev_marked(SummaryView *summaryview)
@@ -1448,8 +1581,8 @@ void summary_select_prev_marked(SummaryView *summaryview)
                val = alertpanel(_("No more marked messages"),
                                 _("No marked message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_MARKED, TRUE);
        }
@@ -1473,8 +1606,8 @@ void summary_select_next_marked(SummaryView *summaryview)
                val = alertpanel(_("No more marked messages"),
                                 _("No marked message found. "
                                   "Search from the beginning?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                     MSG_MARKED, TRUE);
        }
@@ -1498,8 +1631,8 @@ void summary_select_prev_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_CLABEL_FLAG_MASK, TRUE);
        }
@@ -1523,8 +1656,8 @@ void summary_select_next_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the beginning?"),
-                                GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-               if (val != G_ALERTDEFAULT) return;
+                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+               if (val != G_ALERTALTERNATE) return;
                node = summary_find_next_flagged_msg(summaryview, NULL,
                                                     MSG_CLABEL_FLAG_MASK, TRUE);
        }
@@ -1560,12 +1693,27 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
 
+       if (summary_is_locked(summaryview))
+               return;
+       if (!summaryview->folder_item)
+               return;
        if (node) {
                gtkut_ctree_expand_parent_all(ctree, node);
                if (do_refresh) {
+                       summary_lock(summaryview);
                        GTK_EVENTS_FLUSH();
+                       summary_unlock(summaryview);
                        gtk_widget_grab_focus(GTK_WIDGET(ctree));
-                       gtk_ctree_node_moveto(ctree, node, -1, 0.5, 0);
+                       if (GTK_CTREE_ROW(node) == NULL) {
+                               g_warning("crash avoidance hack 1\n");
+                               return;
+                       }
+                       if (((GtkCListRow *)(GTK_CTREE_ROW(node)))->state < GTK_STATE_NORMAL
+                       ||  ((GtkCListRow *)(GTK_CTREE_ROW(node)))->state > GTK_STATE_INSENSITIVE) {
+                               g_warning("crash avoidance hack 2\n");
+                               return;
+                       }
+                       gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0);
                }
                summary_unselect_all(summaryview);
                if (display_msg && summaryview->displayed == node)
@@ -1577,15 +1725,21 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node,
        }
 }
 
-static guint summary_get_msgnum(SummaryView *summaryview, GtkCTreeNode *node)
+guint summary_get_msgnum(SummaryView *summaryview, GtkCTreeNode *node)
 {
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GtkCTree *ctree =NULL;
        MsgInfo *msginfo;
 
+       if (!summaryview)
+               return 0;
+       ctree = GTK_CTREE(summaryview->ctree);
        if (!node)
                return 0;
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
-       return msginfo->msgnum;
+       if (msginfo)
+               return msginfo->msgnum;
+       else 
+               return -1;
 }
 
 static GtkCTreeNode *summary_find_prev_msg(SummaryView *summaryview,
@@ -1674,8 +1828,9 @@ static GtkCTreeNode *summary_find_next_flagged_msg(SummaryView *summaryview,
                msginfo = gtk_ctree_node_get_row_data(ctree, node);
                /* Find msg with matching flags but ignore messages with
                   ignore flags, if searching for new or unread messages */
-               if (!(((flags & (MSG_NEW | MSG_UNREAD)) != 0) && MSG_IS_IGNORE_THREAD(msginfo->flags)) && 
-                       (msginfo && (msginfo->flags.perm_flags & flags) != 0))
+               if ((msginfo && (msginfo->flags.perm_flags & flags) != 0) &&
+                   !(((flags & (MSG_NEW | MSG_UNREAD)) != 0) && MSG_IS_IGNORE_THREAD(msginfo->flags)) 
+                       )
                        break;
        }
 
@@ -1776,7 +1931,7 @@ void summary_attract_by_subject(SummaryView *summaryview)
 
        g_hash_table_destroy(subject_table);
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        gtk_clist_thaw(clist);
 
@@ -1803,14 +1958,10 @@ static void summary_set_marks_func(GtkCTree *ctree, GtkCTreeNode *node,
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
 
-       if (msginfo->folder && msginfo->folder->folder &&
+       if (msginfo && msginfo->folder && msginfo->folder->folder &&
            msginfo->folder->folder->klass->type == F_NEWS)
                news_flag_crosspost(msginfo);
 
-       if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)
-       && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked++;
-
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted++;
 
@@ -1832,9 +1983,6 @@ static void summary_update_status(SummaryView *summaryview)
             node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
                msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
 
-               if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)
-               && procmsg_msg_has_marked_parent(msginfo))
-                       summaryview->unreadmarked++;
                if (MSG_IS_DELETED(msginfo->flags))
                        summaryview->deleted++;
                if (MSG_IS_MOVE(msginfo->flags))
@@ -1853,8 +2001,8 @@ static void summary_status_show(SummaryView *summaryview)
        gchar *spc;
        gchar *itstr;
        GList *rowlist, *cur;
-       guint n_selected = 0;
-       off_t sel_size = 0;
+       guint n_selected = 0, n_new = 0, n_unread = 0, n_total = 0;
+       off_t sel_size = 0, n_size = 0;
        MsgInfo *msginfo;
        gchar *name;
        
@@ -1875,7 +2023,33 @@ static void summary_status_show(SummaryView *summaryview)
                else {
                        sel_size += msginfo->size;
                        n_selected++;
+                       
+               }
+       }
+       
+       if (summaryview->folder_item->hide_read_msgs 
+       || quicksearch_is_active(summaryview->quicksearch)) {
+               rowlist = GTK_CLIST(summaryview->ctree)->row_list;
+               for (cur = rowlist; cur != NULL && cur->data != NULL; cur = cur->next) {
+                       msginfo = gtk_ctree_node_get_row_data
+                               (GTK_CTREE(summaryview->ctree),
+                                GTK_CTREE_NODE(cur));
+                       if (!msginfo)
+                               g_warning("summary_status_show(): msginfo == NULL\n");
+                       else {
+                               n_size += msginfo->size;
+                               n_total++;
+                               if (MSG_IS_NEW(msginfo->flags))
+                                       n_new++;
+                               if (MSG_IS_UNREAD(msginfo->flags))
+                                       n_unread++;
+                       }
                }
+       } else {
+               n_new = summaryview->folder_item->new_msgs;
+               n_unread = summaryview->folder_item->unread_msgs;
+               n_total = summaryview->folder_item->total_msgs;
+               n_size = summaryview->total_size;
        }
 
        name = folder_item_get_name(summaryview->folder_item);
@@ -1928,10 +2102,8 @@ static void summary_status_show(SummaryView *summaryview)
 
        str = g_strdup_printf(_("%d new, %d unread, %d total (%s)"),
 
-                                     summaryview->folder_item->new_msgs,
-                                     summaryview->folder_item->unread_msgs,
-                                     summaryview->folder_item->total_msgs,
-                                     to_human_readable(summaryview->total_size));
+                                     n_new, n_unread, n_total,
+                                     to_human_readable(n_size));
        gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
        g_free(str);
 }
@@ -1939,13 +2111,13 @@ static void summary_status_show(SummaryView *summaryview)
 static void summary_set_column_titles(SummaryView *summaryview)
 {
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
+       FolderItem *item = summaryview->folder_item;
        GtkWidget *hbox;
        GtkWidget *label;
        GtkWidget *arrow;
        gint pos;
        const gchar *title;
        SummaryColumnType type;
-       gboolean single_char;
        GtkJustification justify;
 
        static FolderSortKey sort_by[N_SUMMARY_COLS] = {
@@ -1966,7 +2138,6 @@ static void summary_set_column_titles(SummaryView *summaryview)
                type = summaryview->col_state[pos].type;
 
                /* CLAWS: mime and unread are single char headers */
-               single_char = (type == S_COL_MIME || type == S_COL_STATUS);
                justify = (type == S_COL_NUMBER || type == S_COL_SIZE)
                        ? GTK_JUSTIFY_RIGHT : GTK_JUSTIFY_LEFT;
 
@@ -1976,16 +2147,14 @@ static void summary_set_column_titles(SummaryView *summaryview)
                case S_COL_TO:
                case S_COL_DATE:
                case S_COL_NUMBER:
+                       if(type == S_COL_FROM && item != NULL &&
+                                       FOLDER_SHOWS_TO_HDR(item))
+                               type = S_COL_TO;
                        if (prefs_common.trans_hdr)
                                title = gettext(col_label[type]);
                        else
                                title = col_label[type];
                        break;
-               /* CLAWS: dummies for mark and locked headers */        
-               case S_COL_MARK:        
-               case S_COL_LOCKED:
-                       title = "";
-                       break;
                default:
                        title = gettext(col_label[type]);
                }
@@ -1995,23 +2164,24 @@ static void summary_set_column_titles(SummaryView *summaryview)
                        gtk_widget_show(label);
                        gtk_clist_set_column_widget(clist, pos, label);
                        continue;
-               }
-               if (single_char) {
+               } 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);
+                       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);
+                       continue;
+               } else if (type == S_COL_STATUS) {
                        gtk_clist_set_column_title(clist, pos, title);
                        continue;
                }
 
-               /* CLAWS: changed so that locked and mark headers
-                * show a pixmap instead of single character */
                hbox  = gtk_hbox_new(FALSE, 4);
-               
-               if (type == S_COL_LOCKED)
-                       label = gtk_pixmap_new(lockedxpm, lockedxpmmask);
-               else if (type == S_COL_MARK) 
-                       label = gtk_pixmap_new(markxpm, markxpmmask);
-               else 
-                       label = gtk_label_new(title);
-               
+               label = gtk_label_new(title);
+
                if (justify == GTK_JUSTIFY_RIGHT)
                        gtk_box_pack_end(GTK_BOX(hbox), label,
                                         FALSE, FALSE, 0);
@@ -2039,10 +2209,27 @@ static void summary_set_column_titles(SummaryView *summaryview)
 
 void summary_reflect_prefs(void)
 {
-       SummaryView *summaryview = mainwindow_get_mainwindow()->summaryview;
-       bold_style = bold_marked_style = bold_deleted_style = 
-               small_style = small_marked_style = small_deleted_style = NULL;
-       summary_set_fonts(summaryview);
+       static gchar *last_font = NULL;
+       gboolean update_font = TRUE;
+       SummaryView *summaryview = NULL;
+
+       if (!mainwindow_get_mainwindow())
+               return;
+       summaryview = mainwindow_get_mainwindow()->summaryview;
+
+       if (last_font && !strcmp(last_font, NORMAL_FONT))
+               update_font = FALSE;
+
+       g_free(last_font);
+       
+       last_font = g_strdup(NORMAL_FONT);
+
+       if (update_font) {      
+               bold_style = bold_marked_style = bold_deleted_style = 
+                       small_style = small_marked_style = small_deleted_style = NULL;
+               summary_set_fonts(summaryview);
+       }
+
        summary_set_column_titles(summaryview);
        summary_show(summaryview, summaryview->folder_item);
 }
@@ -2126,7 +2313,7 @@ void summary_sort(SummaryView *summaryview,
 
                gtk_sctree_sort_recursive(ctree, NULL);
 
-               gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+               gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
                main_window_cursor_normal(summaryview->mainwin);
                 gtk_clist_thaw(clist);
@@ -2149,10 +2336,11 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        gint *col_pos = summaryview->col_pos;
        const gchar *msgid = msginfo->msgid;
        GHashTable *msgid_table = summaryview->msgid_table;
+       gboolean free_from = FALSE;
+       
+       summary_set_header(summaryview, text, msginfo, &free_from);
 
-       summary_set_header(summaryview, text, msginfo);
-
-       gtk_ctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
+       gtk_sctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
                                NULL, NULL, NULL, NULL, FALSE,
                                gnode->parent->parent ? TRUE : FALSE);
 #define SET_TEXT(col) \
@@ -2165,7 +2353,12 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        SET_TEXT(S_COL_DATE);
        SET_TEXT(S_COL_FROM);
        SET_TEXT(S_COL_TO);
-       SET_TEXT(S_COL_SUBJECT);
+       /* SET_TEXT(S_COL_SUBJECT);  already set by node info */
+
+       if (free_from) {
+               g_free(text[col_pos[S_COL_FROM]]);
+               text[col_pos[S_COL_FROM]] = NULL;
+       }
 
 #undef SET_TEXT
 
@@ -2207,11 +2400,6 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        if (prefs_common.use_addr_book)
                start_address_completion();
        
-       for (cur = mlist ; cur != NULL && cur->data != NULL; cur = cur->next) {
-               msginfo = (MsgInfo *)cur->data;
-               msginfo->threadscore = msginfo->score;
-       }
-
        if (summaryview->threaded) {
                GNode *root, *gnode;
 
@@ -2229,15 +2417,23 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                summary_thread_init(summaryview);
        } else {
                gchar *text[N_SUMMARY_COLS];
+               gboolean free_from = FALSE;
+               gint *col_pos = summaryview->col_pos;
+
                cur = mlist;
                for (; mlist != NULL; mlist = mlist->next) {
                        msginfo = (MsgInfo *)mlist->data;
 
-                       summary_set_header(summaryview, text, msginfo);
+                       summary_set_header(summaryview, text, msginfo, &free_from);
 
-                       node = gtk_ctree_insert_node
+                       node = gtk_sctree_insert_node
                                (ctree, NULL, node, text, 2,
-                                NULL, NULL, NULL, NULL, FALSE, FALSE);
+                                NULL, NULL, NULL, NULL,
+                                FALSE, FALSE);
+                       if (free_from) {
+                               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);
 
@@ -2279,11 +2475,13 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
 
        node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
 
-       while (prefs_common.bold_unread && node) {
-               GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
-               if (GTK_CTREE_ROW(node)->children)
-                       summary_set_row_marks(summaryview, node);
-               node = next;
+       if (prefs_common.bold_unread) {
+               while (node) {
+                       GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
+                       if (GTK_CTREE_ROW(node)->children)
+                               summary_set_row_marks(summaryview, node);
+                       node = next;
+               }
        }
 
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
@@ -2301,7 +2499,8 @@ static gchar *summary_complete_address(const gchar *addr)
 
        Xstrdup_a(email_addr, addr, return NULL);
        extract_address(email_addr);
-       g_return_val_if_fail(*email_addr, NULL);
+       if (!*email_addr)
+               return NULL;
 
        /*
         * completion stuff must be already initialized
@@ -2317,18 +2516,23 @@ static gchar *summary_complete_address(const gchar *addr)
 }
 
 static void summary_set_header(SummaryView *summaryview, gchar *text[],
-                              MsgInfo *msginfo)
+                              MsgInfo *msginfo, gboolean *free_from)
 {
        static gchar date_modified[80];
        static gchar col_score[11];
        static gchar buf[BUFFSIZE];
        gint *col_pos = summaryview->col_pos;
-       FolderType ftype = F_UNKNOWN;
-
-       text[col_pos[S_COL_MARK]]   = NULL;
-       text[col_pos[S_COL_STATUS]] = NULL;
-       text[col_pos[S_COL_MIME]]   = NULL;
-       text[col_pos[S_COL_LOCKED]] = NULL;
+       gchar *from_text = NULL, *to_text = NULL;
+       gboolean should_swap = FALSE;
+
+       text[col_pos[S_COL_FROM]]   = "";
+       text[col_pos[S_COL_TO]]     = "";
+       text[col_pos[S_COL_SUBJECT]]= "";
+       text[col_pos[S_COL_MARK]]   = "";
+       text[col_pos[S_COL_STATUS]] = "";
+       text[col_pos[S_COL_MIME]]   = "";
+       text[col_pos[S_COL_LOCKED]] = "";
+       text[col_pos[S_COL_DATE]]   = "";
        text[col_pos[S_COL_NUMBER]] = itos(msginfo->msgnum);
        text[col_pos[S_COL_SIZE]]   = to_human_readable(msginfo->size);
        text[col_pos[S_COL_SCORE]]  = itos_buf(col_score, msginfo->score);
@@ -2343,22 +2547,49 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        else
                text[col_pos[S_COL_DATE]] = _("(No Date)");
 
+       if (prefs_common.swap_from && msginfo->from && msginfo->to
+       &&  !summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible) {
+               gchar *addr = NULL;
+               
+               addr = g_strdup(msginfo->from);
+
+               if (addr) {
+                       extract_address(addr);
+                       if (account_find_from_address(addr)) {
+                               should_swap = TRUE;
+                       }
+                       g_free(addr);
+               }
+       }
+
        if (!prefs_common.use_addr_book) {
-               text[col_pos[S_COL_FROM]] = msginfo->fromname ? 
-                                               msginfo->fromname :
-                                               _("(No From)");
+               from_text = msginfo->fromname ? 
+                               msginfo->fromname :
+                               _("(No From)");
        } else {
-               gchar *tmp = summary_complete_address(msginfo->fromname);
-               text[col_pos[S_COL_FROM]] = tmp ? tmp : (msginfo->fromname ?
-                                                        msginfo->fromname: 
-                                                               _("(No From)"));
+               gchar *tmp = summary_complete_address(msginfo->from);
+               from_text = tmp ? tmp : (msginfo->fromname ?
+                                        msginfo->fromname: 
+                                               _("(No From)"));
+       }
+       
+       to_text = msginfo->to ? msginfo->to : 
+                  (msginfo->cc ? msginfo->cc :
+                    (msginfo->newsgroups ? msginfo->newsgroups : _("(No Recipient)")
+                    )
+                  );
+
+       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);
+               text[col_pos[S_COL_FROM]] = tmp;
+               *free_from = TRUE;
        }
-       text[col_pos[S_COL_TO]] = msginfo->to ? msginfo->to : 
-               _("(No Recipient)");
        
-       if (msginfo->folder && msginfo->folder->folder)
-               ftype = msginfo->folder->folder->klass->type; 
-               
        if (summaryview->simplify_subject_preg != NULL)
                text[col_pos[S_COL_SUBJECT]] = msginfo->subject ? 
                        string_remove_match(buf, BUFFSIZE, msginfo->subject, 
@@ -2369,9 +2600,99 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
                        _("(No Subject)");
 }
 
-static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row)
+static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row)
+{
+       summary_display_msg_full(summaryview, row, FALSE, FALSE);
+}
+
+static gboolean defer_change(gpointer data);
+typedef struct _ChangeData {
+       MsgInfo *info;
+       gint op; /* 0, 1, 2 for unset, set, change */
+       MsgPermFlags set_flags;
+       MsgTmpFlags  set_tmp_flags;
+       MsgPermFlags unset_flags;
+       MsgTmpFlags  unset_tmp_flags;
+} ChangeData;
+
+static void summary_msginfo_unset_flags(MsgInfo *msginfo, MsgPermFlags flags, MsgTmpFlags tmp_flags)
+{
+       if (!msginfo->folder || !msginfo->folder->processing_pending) {
+               debug_print("flags: doing unset now\n");
+               procmsg_msginfo_unset_flags(msginfo, flags, tmp_flags);
+       } else {
+               ChangeData *unset_data = g_new0(ChangeData, 1);
+               unset_data->info = msginfo;
+               unset_data->op = 0;
+               unset_data->unset_flags = flags;
+               unset_data->unset_tmp_flags = tmp_flags;
+               debug_print("flags: deferring unset\n");
+               g_timeout_add(100, defer_change, unset_data);
+       }
+}
+
+static void summary_msginfo_set_flags(MsgInfo *msginfo, MsgPermFlags flags, MsgTmpFlags tmp_flags)
+{
+       if (!msginfo->folder || !msginfo->folder->processing_pending) {
+               debug_print("flags: doing set now\n");
+               procmsg_msginfo_set_flags(msginfo, flags, tmp_flags);
+       } else {
+               ChangeData *set_data = g_new0(ChangeData, 1);
+               set_data->info = msginfo;
+               set_data->op = 1;
+               set_data->set_flags = flags;
+               set_data->set_tmp_flags = tmp_flags;
+               debug_print("flags: deferring set\n");
+               g_timeout_add(100, defer_change, set_data);
+       }
+}
+
+static void summary_msginfo_change_flags(MsgInfo *msginfo, 
+               MsgPermFlags add_flags, MsgTmpFlags add_tmp_flags,
+               MsgPermFlags rem_flags, MsgTmpFlags rem_tmp_flags)
 {
-       summary_display_msg_full(summaryview, row, FALSE, FALSE);
+       if (!msginfo->folder || !msginfo->folder->processing_pending) {
+               debug_print("flags: doing change now\n");
+               procmsg_msginfo_change_flags(msginfo, add_flags, add_tmp_flags,
+                       rem_flags, rem_tmp_flags);
+       } else {
+               ChangeData *change_data = g_new0(ChangeData, 1);
+               change_data->info = msginfo;
+               change_data->op = 2;
+               change_data->set_flags = add_flags;
+               change_data->set_tmp_flags = add_tmp_flags;
+               change_data->unset_flags = rem_flags;
+               change_data->unset_tmp_flags = rem_tmp_flags;
+               debug_print("flags: deferring change\n");
+               g_timeout_add(100, defer_change, change_data);
+       }
+}
+
+gboolean defer_change(gpointer data)
+{
+       ChangeData *chg = (ChangeData *)data;
+       if (chg->info->folder && chg->info->folder->processing_pending) {
+               debug_print("flags: trying later\n");
+               return TRUE; /* try again */
+       } else {
+               debug_print("flags: finally doing it\n");
+               switch(chg->op) {
+               case 0:
+                       procmsg_msginfo_unset_flags(chg->info, chg->unset_flags, chg->unset_tmp_flags);
+                       break;
+               case 1:
+                       procmsg_msginfo_set_flags(chg->info, chg->set_flags, chg->set_tmp_flags);
+                       break;
+               case 2:
+                       procmsg_msginfo_change_flags(chg->info, chg->set_flags, chg->set_tmp_flags,
+                               chg->unset_flags, chg->unset_tmp_flags);
+                       break;
+               default:
+                       g_warning("shouldn't happen\n");
+               }
+               g_free(chg);
+       }
+       return FALSE;
 }
 
 static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo,
@@ -2381,11 +2702,8 @@ static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo,
        g_return_if_fail(msginfo != NULL);
        g_return_if_fail(row != NULL);
 
-       if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags) 
-       && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked--;
        if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
-               procmsg_msginfo_unset_flags
+               summary_msginfo_unset_flags
                        (msginfo, MSG_NEW | MSG_UNREAD, 0);
                summary_set_row_marks(summaryview, row);
                gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
@@ -2438,6 +2756,8 @@ static void summary_display_msg_full(SummaryView *summaryview,
        GTK_EVENTS_FLUSH();
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       
+       g_return_if_fail(msginfo);
 
        if (new_window) {
                MessageView *msgview;
@@ -2531,9 +2851,7 @@ void summary_reedit(SummaryView *summaryview)
 
        if (!summaryview->selected) return;
        if (!summaryview->folder_item) return;
-       if (!folder_has_parent_of_type(summaryview->folder_item, F_OUTBOX)
-       &&  !folder_has_parent_of_type(summaryview->folder_item, F_DRAFT)
-       &&  !folder_has_parent_of_type(summaryview->folder_item, F_QUEUE))
+       if (!FOLDER_SHOWS_TO_HDR(summaryview->folder_item))
                return;
 
        msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree),
@@ -2643,6 +2961,9 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_IGNORE_THREAD(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          ignorethreadxpm, ignorethreadxpmmask);
+       } else if (MSG_IS_SPAM(flags)) {
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
+                                         spamxpm, spamxpmmask);
        } else if (MSG_IS_NEW(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          newxpm, newxpmmask);
@@ -2657,7 +2978,7 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                                          forwardedxpm, forwardedxpmmask);
        } else {
                gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_STATUS],
-                                       NULL);
+                                       "");
        }
 
        if (prefs_common.bold_unread &&
@@ -2699,17 +3020,8 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                }
                        gtk_ctree_node_set_foreground
                                (ctree, row, &summaryview->color_marked);
-#if 0
-       } else if ((global_scoring ||
-                 summaryview->folder_item->prefs->scoring) &&
-                (msginfo->score >= summaryview->important_score) &&
-                (MSG_IS_MARKED(msginfo->flags) || MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))) {
-               gtk_ctree_node_set_text(ctree, row, S_COL_MARK, "!");
-               gtk_ctree_node_set_foreground(ctree, row,
-                                             &summaryview->color_important);
-#endif
        } else {
-               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], NULL);
+               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], "");
        }
 
        if (MSG_IS_LOCKED(flags)) {
@@ -2717,7 +3029,7 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                                          lockedxpm, lockedxpmmask);
        }
        else {
-               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_LOCKED], NULL);
+               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_LOCKED], "");
        }
 
        if (MSG_IS_WITH_ATTACHMENT(flags) && MSG_IS_SIGNED(flags)) {
@@ -2736,7 +3048,7 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MIME],
                                          clipxpm, clipxpmmask);
        } else {
-               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MIME], NULL);
+               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MIME], "");
        }
        if (!style)
                style = small_style;
@@ -2747,22 +3059,13 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                summary_set_colorlabel_color(ctree, row, MSG_GET_COLORLABEL_VALUE(flags));
 }
 
-void summary_set_marks_selected(SummaryView *summaryview)
-{
-       GList *cur;
-       summary_lock(summaryview);
-       for (cur = GTK_CLIST(summaryview->ctree)->selection; cur != NULL && cur->data != NULL;
-            cur = cur->next)
-               summary_set_row_marks(summaryview, GTK_CTREE_NODE(cur->data));
-       summary_unlock(summaryview);
-}
-
 static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags))
@@ -2771,7 +3074,7 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_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);
        summary_set_row_marks(summaryview, row);
        debug_print("Message %s/%d is marked\n", msginfo->folder->path, msginfo->msgnum);
 }
@@ -2783,6 +3086,7 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags)) {
@@ -2794,7 +3098,7 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
                changed = TRUE;
        }
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_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);
        
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is locked\n", msginfo->msgnum);
@@ -2806,10 +3110,11 @@ static void summary_unlock_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (!MSG_IS_LOCKED(msginfo->flags))
                return;
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_msginfo_unset_flags(msginfo, MSG_LOCKED, 0);
+       summary_msginfo_unset_flags(msginfo, MSG_LOCKED, 0);
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is unlocked\n", msginfo->msgnum);
 }
@@ -2836,15 +3141,12 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
        if(!(MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)))
                return;
 
-       if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)
-       && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked--;
-
-       procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
+       summary_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is marked as read\n",
                msginfo->msgnum);
@@ -2898,7 +3200,21 @@ void summary_mark_all_read(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCTreeNode *node;
+       AlertValue val;
 
+       if (prefs_common.ask_mark_all_read) {
+               val = alertpanel_full(_("Mark all as read"),
+                       _("Do you really want to mark all mails in this "
+                         "folder as read ?"), GTK_STOCK_NO, GTK_STOCK_YES, NULL,
+                         TRUE, NULL, ALERT_QUESTION, G_ALERTALTERNATE);
+
+               if (val == G_ALERTDEFAULT ||
+                   val == (G_ALERTDEFAULT|G_ALERTDISABLE))
+                       return;
+               else if (val == (G_ALERTALTERNATE|G_ALERTDISABLE))
+                       prefs_common.ask_mark_all_read = FALSE;
+       }
+       
        START_LONG_OPERATION(summaryview);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); node != NULL;
@@ -2915,6 +3231,59 @@ void summary_mark_all_read(SummaryView *summaryview)
        summary_status_show(summaryview);
 }
 
+void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *widget)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GList *cur;
+       gboolean is_spam = action;
+       GSList *msgs = NULL;
+       gboolean immediate_exec = prefs_common.immediate_exec;
+       gboolean moved = FALSE;
+       prefs_common.immediate_exec = FALSE;
+
+       START_LONG_OPERATION(summaryview);
+
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+               GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
+               MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
+               if (msginfo)
+                       msgs = g_slist_prepend(msgs, msginfo);
+       }
+       
+       if (procmsg_spam_learner_learn(NULL, msgs, is_spam) == 0) {
+               for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+                       GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
+                       MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
+                       if (!msginfo)
+                               continue;
+                       if (is_spam) {
+                               summary_msginfo_change_flags(msginfo, MSG_SPAM, 0, MSG_NEW|MSG_UNREAD, 0);
+                               if (procmsg_spam_get_folder() != summaryview->folder_item) {
+                                       summary_move_row_to(summaryview, row, procmsg_spam_get_folder());
+                                       moved = TRUE;
+                               }
+                       } else {
+                               summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+                       }
+               }
+       } else {
+               log_error(_("An error happened while learning.\n"));
+       }
+
+       g_slist_free(msgs);
+       
+       prefs_common.immediate_exec = immediate_exec;
+
+       END_LONG_OPERATION(summaryview);
+
+       if (prefs_common.immediate_exec && moved) {
+               summary_execute(summaryview);
+       }
+
+       summary_status_show(summaryview);       
+}
+
+
 static void summary_mark_row_as_unread(SummaryView *summaryview,
                                       GtkCTreeNode *row)
 {
@@ -2922,17 +3291,14 @@ static void summary_mark_row_as_unread(SummaryView *summaryview,
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags)) {
                procmsg_msginfo_set_to_folder(msginfo, NULL);
-               procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, 0);
+               summary_msginfo_unset_flags(msginfo, MSG_DELETED, 0);
                summaryview->deleted--;
        }
 
-       if (!MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)
-       && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked++;
-
-       procmsg_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
+       summary_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
        debug_print("Message %d is marked as unread\n",
                msginfo->msgnum);
 
@@ -2995,7 +3361,7 @@ static gboolean check_permission(SummaryView *summaryview, MsgInfo * msginfo)
                }
 
                if (!found) {
-                       alertpanel_error(_("You're not the author of the article\n"));
+                       alertpanel_error(_("You're not the author of the article.\n"));
                }
                
                return found;
@@ -3011,9 +3377,7 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
-
-       if (!check_permission(summaryview, msginfo))
-               return;
+       g_return_if_fail(msginfo);
 
        if (MSG_IS_LOCKED(msginfo->flags)) return;
 
@@ -3025,7 +3389,7 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_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);
        summaryview->deleted++;
 
        if (!prefs_common.immediate_exec && 
@@ -3078,19 +3442,18 @@ void summary_delete(SummaryView *summaryview)
 
        if (summary_is_locked(summaryview)) return;
 
-       if (!summaryview->folder_item ||
-           FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS) return;
+       if (!summaryview->folder_item) return;
 
        aval = alertpanel(_("Delete message(s)"),
                          _("Do you really want to delete selected message(s)?"),
-                         GTK_STOCK_YES, GTK_STOCK_NO, NULL);
-       if (aval != G_ALERTDEFAULT) return;
+                         GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
+       if (aval != G_ALERTALTERNATE) return;
 
        for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; 
             cur = cur->next) {
                GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
                msginfo = gtk_ctree_node_get_row_data(ctree, row);
-               if (msginfo->total_size != 0 && 
+               if (msginfo && msginfo->total_size != 0 && 
                    msginfo->size != (off_t)msginfo->total_size)
                        partial_mark_for_delete(msginfo);
        }
@@ -3099,16 +3462,14 @@ void summary_delete(SummaryView *summaryview)
 
        /* next code sets current row focus right. We need to find a row
         * that is not deleted. */
-       summary_lock(summaryview);
-       folder_item_update_freeze();
-       gtk_clist_freeze(GTK_CLIST(summaryview->ctree)); 
+       START_LONG_OPERATION(summaryview);
+       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);
                summary_delete_row(summaryview, sel_last);
        }
-       folder_item_update_thaw();
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
-       summary_unlock(summaryview);
+       folder_item_set_batch(summaryview->folder_item, FALSE);
+       END_LONG_OPERATION(summaryview);
 
        node = summary_find_next_msg(summaryview, sel_last);
        if (!node)
@@ -3123,6 +3484,7 @@ void summary_delete(SummaryView *summaryview)
                gtk_sctree_set_anchor_row(GTK_SCTREE(ctree), node);
        } else
                summary_status_show(summaryview);
+
                
        main_window_cursor_normal(summaryview->mainwin);
 }
@@ -3140,7 +3502,8 @@ void summary_delete_trash(SummaryView *summaryview)
        if (to_folder == NULL)
                to_folder = summaryview->folder_item->folder->trash;
        
-       if (to_folder == NULL || to_folder == summaryview->folder_item)
+       if (to_folder == NULL || to_folder == summaryview->folder_item
+           || folder_has_parent_of_type(summaryview->folder_item, F_TRASH))
                summary_delete(summaryview);
        else
                summary_move_selected_to(summaryview, to_folder);
@@ -3153,6 +3516,7 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags))
@@ -3161,7 +3525,7 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_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);
        summary_set_row_marks(summaryview, row);
 
        debug_print("Message %s/%d is unmarked\n",
@@ -3192,6 +3556,7 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        g_return_if_fail(to_folder != NULL);
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        if (MSG_IS_LOCKED(msginfo->flags))
                return;
 
@@ -3202,10 +3567,10 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                summaryview->copied--;
        }
        if (!MSG_IS_MOVE(msginfo->flags)) {
-               procmsg_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_MARKED | MSG_DELETED, MSG_COPY);
+               summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, MSG_COPY);
                summaryview->moved++;
        } else {
-               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_COPY);
+               summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_COPY);
        }
        
        if (!prefs_common.immediate_exec) {
@@ -3240,6 +3605,8 @@ void summary_move_selected_to(SummaryView *summaryview, FolderItem *to_folder)
 
        END_LONG_OPERATION(summaryview);
 
+       summaryview->display_msg = prefs_common.always_show_msg;
+       
        if (prefs_common.immediate_exec) {
                summary_execute(summaryview);
        } else {
@@ -3276,6 +3643,7 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        g_return_if_fail(to_folder != NULL);
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
        procmsg_msginfo_set_to_folder(msginfo, to_folder);
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
@@ -3284,10 +3652,10 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        }
        
        if (!MSG_IS_COPY(msginfo->flags)) {
-               procmsg_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_MARKED | MSG_DELETED, MSG_MOVE);
+               summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, MSG_MOVE);
                summaryview->copied++;
        } else {
-               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE);
+               summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE);
        }
        if (!prefs_common.immediate_exec) {
                summary_set_row_marks(summaryview, row);
@@ -3430,7 +3798,7 @@ void summary_save_as(SummaryView *summaryview)
        if (is_file_exist(dest)) {
                aval = alertpanel(_("Append or Overwrite"),
                                  _("Append or overwrite existing file?"),
-                                 _("Append"), _("Overwrite"),
+                                 _("_Append"), _("_Overwrite"),
                                  GTK_STOCK_CANCEL);
                if (aval != 0 && aval != 1)
                        return;
@@ -3455,7 +3823,7 @@ void summary_save_as(SummaryView *summaryview)
        if (GTK_CLIST(ctree)->selection->next) {
                GList *item;
                for (item = GTK_CLIST(ctree)->selection->next; item != NULL; item=item->next) {
-                       msginfo = gtk_ctree_node_get_row_data(ctree, (GtkCTreeNode*)item->data);
+                       msginfo = gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(item->data));
                        if (!msginfo) break;
                        src = procmsg_get_message_file(msginfo);
                        if (append_file(src, dest, TRUE) < 0)
@@ -3467,6 +3835,21 @@ 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);
@@ -3475,9 +3858,6 @@ void summary_print(SummaryView *summaryview)
        MsgInfo *msginfo;
        gchar *cmdline = NULL;
        gchar *p;
-#else
-       gboolean first = TRUE;
-       GList *tmplist;
 #endif
        GList *cur;
 
@@ -3495,36 +3875,39 @@ void summary_print(SummaryView *summaryview)
                g_free(cmdline);
                return;
        }
-       for (cur = clist->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+       for (cur = clist->selection; 
+            cur != NULL && cur->data != NULL; 
+            cur = cur->next) {
                msginfo = gtk_ctree_node_get_row_data
                        (ctree, GTK_CTREE_NODE(cur->data));
-               if (msginfo) procmsg_print_message(msginfo, cmdline);
+               if (msginfo) 
+                       procmsg_print_message(msginfo, cmdline);
        }
 
        g_free(cmdline);
-       
 #else
-       tmplist = g_list_copy(clist->selection);
-       summary_unselect_all(summaryview);
-       for (cur = tmplist; cur != NULL && cur->data != NULL; cur = cur->next) {
-               GtkCTreeNode *node = GTK_CTREE_NODE(cur->data);
-               summary_select_node(summaryview, node, TRUE, TRUE);
-               if (!summaryview->messageview->mimeview 
-               ||  !summaryview->messageview->mimeview->textview
-               ||  !summaryview->messageview->mimeview->textview->text)
-                       alertpanel_warning(_("Cannot print: the message doesn't "
-                                            "contain text."));
-               gedit_print(
-                       GTK_TEXT_VIEW(summaryview->messageview->mimeview
-                                       ->textview->text));
-       }
-       for (cur = tmplist; cur != NULL && cur->data != NULL; cur = cur->next) {
+       for (cur = clist->selection; 
+            cur != NULL && cur->data != NULL; 
+            cur = cur->next) {
                GtkCTreeNode *node = GTK_CTREE_NODE(cur->data);
-               gtk_sctree_select_with_state(
-                       GTK_SCTREE(clist), node, first ? 0:GDK_CONTROL_MASK);
-               first = FALSE;
+               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);
+               }
        }
-       g_list_free(tmplist);
 #endif
 }
 
@@ -3534,6 +3917,7 @@ gboolean summary_execute(SummaryView *summaryview)
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
        GtkCTreeNode *node, *next;
        GtkCTreeNode *new_selected = NULL;
+       gint move_val = -1;
 
        if (!summaryview->folder_item) return FALSE;
 
@@ -3542,11 +3926,13 @@ gboolean summary_execute(SummaryView *summaryview)
 
        gtk_clist_freeze(clist);
 
+       main_window_cursor_wait(summaryview->mainwin);
+
        if (summaryview->threaded)
                summary_unthread_for_exec(summaryview);
 
        folder_item_update_freeze();
-       summary_execute_move(summaryview);
+       move_val = summary_execute_move(summaryview);
        summary_execute_copy(summaryview);
        summary_execute_delete(summaryview);
        
@@ -3573,7 +3959,7 @@ gboolean summary_execute(SummaryView *summaryview)
                                        (summaryview, node);
                }
 
-               gtk_ctree_remove_node(ctree, node);
+               gtk_sctree_remove_node((GtkSCTree *)ctree, node);
        }
 
        folder_item_update_thaw();
@@ -3607,29 +3993,36 @@ gboolean summary_execute(SummaryView *summaryview)
        summary_update_status(summaryview);
        summary_status_show(summaryview);
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        summary_unlock(summaryview);
+
+       main_window_cursor_normal(summaryview->mainwin);
+
+       if (move_val < 0) 
+               summary_show(summaryview, summaryview->folder_item);
        return TRUE;
 }
 
-static void summary_execute_move(SummaryView *summaryview)
+static gint summary_execute_move(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GSList *cur;
-
+       gint val = -1;
        /* search moving messages and execute */
        gtk_ctree_pre_recursive(ctree, NULL, summary_execute_move_func,
                                summaryview);
 
        if (summaryview->mlist) {
-               procmsg_move_messages(summaryview->mlist);
+               val = procmsg_move_messages(summaryview->mlist);
 
                for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next)
                        procmsg_msginfo_free((MsgInfo *)cur->data);
                g_slist_free(summaryview->mlist);
                summaryview->mlist = NULL;
+               return val;
        }
+       return 0;
 }
 
 static void summary_execute_move_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -3682,7 +4075,7 @@ static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node,
                summaryview->mlist =
                        g_slist_prepend(summaryview->mlist, msginfo);
 
-               procmsg_msginfo_unset_flags(msginfo, 0, MSG_COPY);
+               summary_msginfo_unset_flags(msginfo, 0, MSG_COPY);
                summary_set_row_marks(summaryview, node);
        }
 }
@@ -3827,52 +4220,6 @@ static void summary_thread_init(SummaryView *summaryview)
        } 
 }
 
-void summary_unthread(SummaryView *summaryview)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       GtkCTreeNode *child;
-       GtkCTreeNode *sibling;
-       GtkCTreeNode *next_child;
-
-       summary_lock(summaryview);
-
-       debug_print("Unthreading...");
-       STATUSBAR_PUSH(summaryview->mainwin, _("Unthreading..."));
-       main_window_cursor_wait(summaryview->mainwin);
-       
-       g_signal_handlers_block_by_func(G_OBJECT(ctree),
-                                       summary_tree_collapsed, summaryview);
-       gtk_clist_freeze(GTK_CLIST(ctree));
-
-       for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-            node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               child = GTK_CTREE_ROW(node)->children;
-               sibling = GTK_CTREE_ROW(node)->sibling;
-
-               while (child != NULL) {
-                       next_child = GTK_CTREE_ROW(child)->sibling;
-                       gtk_ctree_move(ctree, child, NULL, sibling);
-                       child = next_child;
-               }
-       }
-
-       /* CLAWS: and sort it */
-       gtk_sctree_sort_recursive(ctree, NULL); 
-
-       gtk_clist_thaw(GTK_CLIST(ctree));
-       g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
-                                          G_CALLBACK(summary_tree_collapsed), summaryview);
-
-       debug_print("done.\n");
-       STATUSBAR_POP(summaryview->mainwin);
-       main_window_cursor_normal(summaryview->mainwin);
-
-       summaryview->threaded = FALSE;
-
-       summary_unlock(summaryview);
-}
-
 static void summary_unthread_for_exec(SummaryView *summaryview)
 {
        GtkCTreeNode *node;
@@ -3947,7 +4294,7 @@ void summary_expand_threads(SummaryView *summaryview)
 
        summaryview->thread_collapsed = FALSE;
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
 void summary_collapse_threads(SummaryView *summaryview)
@@ -3967,11 +4314,12 @@ void summary_collapse_threads(SummaryView *summaryview)
        
        summaryview->thread_collapsed = TRUE;
 
-       gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
+       gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 }
 
 void summary_filter(SummaryView *summaryview, gboolean selected_only)
 {
+       GSList *mlist = NULL, *cur_list;
        summary_lock(summaryview);
 
        folder_item_update_freeze();
@@ -3987,15 +4335,23 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
 
                for (cur = GTK_CLIST(summaryview->ctree)->selection;
                     cur != NULL && cur->data != NULL; cur = cur->next) {
-                       summary_filter_func(GTK_CTREE(summaryview->ctree),
-                                           GTK_CTREE_NODE(cur->data),
-                                           summaryview);
+                       mlist = g_slist_prepend(mlist, 
+                                procmsg_msginfo_new_ref(
+                                 GTKUT_CTREE_NODE_GET_ROW_DATA(cur->data)));
                }
+               mlist = g_slist_reverse(mlist);
        } else {
-               gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL,
-                                       GTK_CTREE_FUNC(summary_filter_func),
-                                       summaryview);
+               mlist = folder_item_get_msg_list(summaryview->folder_item);
        }
+       for (cur_list = mlist; cur_list; cur_list = cur_list->next) {
+               summary_filter_func((MsgInfo *)cur_list->data);
+       }
+       filtering_move_and_copy_msgs(mlist);
+       for (cur_list = mlist; cur_list; cur_list = cur_list->next) {
+               procmsg_msginfo_free((MsgInfo *)cur_list->data);
+       }
+       g_slist_free(mlist);
+
        gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
 
        folder_item_update_thaw();
@@ -4012,11 +4368,9 @@ void summary_filter(SummaryView *summaryview, gboolean selected_only)
        summary_show(summaryview, summaryview->folder_item);
 }
 
-static void summary_filter_func(GtkCTree *ctree, GtkCTreeNode *node,
-                               gpointer data)
+static void summary_filter_func(MsgInfo *msginfo)
 {
        MailFilteringData mail_filtering_data;
-       MsgInfo *msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node);
 
        mail_filtering_data.msginfo = msginfo;
        if (hooks_invoke(MAIL_MANUAL_FILTERING_HOOKLIST, &mail_filtering_data))
@@ -4101,6 +4455,7 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        gint color_index;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
+       g_return_if_fail(msginfo);
 
        color_index = labelcolor == 0 ? -1 : (gint)labelcolor - 1;
        ctree_style = gtk_widget_get_style(GTK_WIDGET(ctree));
@@ -4136,8 +4491,9 @@ static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *r
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
-       procmsg_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, 
+       summary_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, 
                                        MSG_CLABEL_FLAG_MASK, 0);
 }
 
@@ -4171,6 +4527,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
        if (!sel) return;
 
        menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       
        g_return_if_fail(menu != NULL);
 
        Xalloca(items, (N_COLOR_LABELS + 1) * sizeof(GtkWidget *), return);
@@ -4215,7 +4572,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                          GINT_TO_POINTER(0));
 }
 
-static void summary_colorlabel_menu_create(SummaryView *summaryview)
+static void summary_colorlabel_menu_create(SummaryView *summaryview, gboolean refresh)
 {
        GtkWidget *label_menuitem;
        GtkWidget *menu;
@@ -4244,13 +4601,19 @@ static void summary_colorlabel_menu_create(SummaryView *summaryview)
        g_object_set_data(G_OBJECT(item), "summaryview", summaryview);
        gtk_widget_show(item);
 
+       gtk_widget_add_accelerator(item, "activate", 
+                                  summaryview->popupfactory->accel_group, 
+                                  GDK_0, GDK_CONTROL_MASK,
+                                  GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
+
        item = gtk_menu_item_new();
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        gtk_widget_show(item);
 
        /* create pixmap/label menu items */
        for (i = 0; i < N_COLOR_LABELS; i++) {
-               item = colorlabel_create_check_color_menu_item(i);
+               item = colorlabel_create_check_color_menu_item(
+                       i, refresh, SUMMARY_COLORMENU);
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                g_signal_connect(G_OBJECT(item), "activate",
                                 G_CALLBACK(summary_colorlabel_menu_item_activate_cb),
@@ -4265,6 +4628,16 @@ static void summary_colorlabel_menu_create(SummaryView *summaryview)
        summaryview->colorlabel_menu = menu;
 }
 
+static gboolean summary_popup_menu(GtkWidget *widget, gpointer data)
+{
+       SummaryView *summaryview = (SummaryView *)data;
+       summaryview->display_msg = messageview_is_visible(summaryview->messageview);
+
+       gtk_menu_popup(GTK_MENU(summaryview->popupmenu), NULL, NULL,
+                      NULL, NULL, 0, gtk_get_current_event_time());
+       return TRUE;
+}
+
 static GtkWidget *summary_ctree_create(SummaryView *summaryview)
 {
        GtkWidget *ctree;
@@ -4281,6 +4654,7 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                summaryview->col_state[pos] = col_state[pos];
                type = col_state[pos].type;
                col_pos[type] = pos;
+               titles[pos] = "dummy";
        }
        col_state = summaryview->col_state;
 
@@ -4327,13 +4701,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
        gtk_ctree_set_expander_style(GTK_CTREE(ctree),
                                     GTK_CTREE_EXPANDER_SQUARE);
-#if 0
-       gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_NONE);
-       gtk_ctree_set_expander_style(GTK_CTREE(ctree),
-                                    GTK_CTREE_EXPANDER_TRIANGLE);
-#endif
        gtk_ctree_set_indent(GTK_CTREE(ctree), 12);
-       g_object_set_data(G_OBJECT(ctree), "user_data", summaryview);
+       g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(ctree)->column[pos].button,
@@ -4366,9 +4735,13 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
 
        g_signal_connect(G_OBJECT(ctree), "tree_select_row",
                         G_CALLBACK(summary_selected), summaryview);
+       g_signal_connect(G_OBJECT(ctree), "tree_unselect_row",
+                        G_CALLBACK(summary_unselected), summaryview);
        g_signal_connect(G_OBJECT(ctree), "button_press_event",
                         G_CALLBACK(summary_button_pressed),
                         summaryview);
+       g_signal_connect(G_OBJECT(ctree), "popup-menu",
+                        G_CALLBACK(summary_popup_menu), summaryview);
        g_signal_connect(G_OBJECT(ctree), "button_release_event",
                         G_CALLBACK(summary_button_released),
                         summaryview);
@@ -4393,6 +4766,18 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                         G_CALLBACK(summary_drag_data_get),
                         summaryview);
 
+       gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT,
+                         summary_drag_types, 2,
+                         GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_DEFAULT);
+
+       g_signal_connect(G_OBJECT(ctree), "drag_data_received",
+                        G_CALLBACK(summary_drag_data_received),
+                        summaryview);
+
+       g_signal_connect(G_OBJECT(ctree), "drag_motion",
+                        G_CALLBACK(summary_drag_motion_cb),
+                        summaryview);
+
        return ctree;
 }
 
@@ -4400,7 +4785,6 @@ void summary_set_column_order(SummaryView *summaryview)
 {
        GtkWidget *ctree;
        GtkWidget *scrolledwin = summaryview->scrolledwin;
-       GtkWidget *pixmap;
        FolderItem *item;
        guint selected_msgnum = summary_get_msgnum(summaryview, summaryview->selected);
        guint displayed_msgnum = summary_get_msgnum(summaryview, summaryview->displayed);
@@ -4412,10 +4796,7 @@ void summary_set_column_order(SummaryView *summaryview)
 
        summaryview->ctree = ctree = summary_ctree_create(summaryview);
        summary_set_fonts(summaryview);
-       pixmap = gtk_image_new_from_pixmap(clipxpm, clipxpmmask);
-       gtk_clist_set_column_widget(GTK_CLIST(ctree),
-                                   summaryview->col_pos[S_COL_MIME], pixmap);
-       gtk_widget_show(pixmap);
+       summary_set_column_titles(summaryview);
        gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(scrolledwin),
                                            GTK_CLIST(ctree)->hadjustment);
        gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(scrolledwin),
@@ -4472,9 +4853,9 @@ static gboolean summary_button_released(GtkWidget *ctree, GdkEventButton *event,
        return FALSE;
 }
 
-void summary_pass_key_press_event(SummaryView *summaryview, GdkEventKey *event)
+gboolean summary_pass_key_press_event(SummaryView *summaryview, GdkEventKey *event)
 {
-       summary_key_pressed(summaryview->ctree, event, summaryview);
+       return summary_key_pressed(summaryview->ctree, event, summaryview);
 }
 
 #define BREAK_ON_MODIFIER_KEY() \
@@ -4577,6 +4958,17 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                BREAK_ON_MODIFIER_KEY();
                summary_delete_trash(summaryview);
                break;
+       case GDK_y:
+       case GDK_t:
+       case GDK_l:
+       case GDK_c:
+               if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
+                       g_signal_stop_emission_by_name(G_OBJECT(widget), 
+                                       "key_press_event");
+                       mimeview_pass_key_press_event(messageview->mimeview,
+                                                     event);
+                       break;
+               }
        default:
                break;
        }
@@ -4603,11 +4995,17 @@ static void tog_searchbar_cb(GtkWidget *w, gpointer data)
        }
 }
 
+void summaryview_activate_quicksearch(SummaryView *summaryview) 
+{
+       gtk_toggle_button_set_active(
+               GTK_TOGGLE_BUTTON(summaryview->toggle_search), 
+               TRUE);
+       quicksearch_show(summaryview->quicksearch);
+}
+
 static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
 {
-       if (folder_has_parent_of_type(summaryview->folder_item, F_OUTBOX)
-       ||  folder_has_parent_of_type(summaryview->folder_item, F_DRAFT)
-       ||  folder_has_parent_of_type(summaryview->folder_item, F_QUEUE))
+       if (FOLDER_SHOWS_TO_HDR(summaryview->folder_item))
                summary_reedit(summaryview);
        else
                summary_open_msg(summaryview);
@@ -4619,11 +5017,13 @@ static void summary_tree_expanded(GtkCTree *ctree, GtkCTreeNode *node,
                                  SummaryView *summaryview)
 {
        summary_set_row_marks(summaryview, node);
-       while (prefs_common.bold_unread && node) {
-               GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
-               if (GTK_CTREE_ROW(node)->children)
-                       summary_set_row_marks(summaryview, node);
-               node = next;
+       if (prefs_common.bold_unread) {
+               while (node) {
+                       GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
+                       if (GTK_CTREE_ROW(node)->children)
+                               summary_set_row_marks(summaryview, node);
+                       node = next;
+               }
        }
 }
 
@@ -4633,6 +5033,17 @@ static void summary_tree_collapsed(GtkCTree *ctree, GtkCTreeNode *node,
        summary_set_row_marks(summaryview, node);
 }
 
+static void summary_unselected(GtkCTree *ctree, GtkCTreeNode *row,
+                              gint column, SummaryView *summaryview)
+{
+       if (summary_is_locked(summaryview)
+       ||  GTK_SCTREE(ctree)->selecting_range) {
+               return;
+       }
+
+       summary_status_show(summaryview);
+}
+
 static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                             gint column, SummaryView *summaryview)
 {
@@ -4659,6 +5070,11 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        g_return_if_fail(msginfo != NULL);
 
+       main_create_mailing_list_menu (summaryview->mainwin, msginfo);
+       toolbar_set_learn_button
+               (summaryview->mainwin->toolbar,
+                MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
+
        switch (column < 0 ? column : summaryview->col_state[column].type) {
        case S_COL_MARK:
                if (!MSG_IS_DELETED(msginfo->flags) &&
@@ -4675,6 +5091,11 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                if (MSG_IS_UNREAD(msginfo->flags)) {
                        summary_mark_row_as_read(summaryview, row);
                        summary_status_show(summaryview);
+               } else if (MSG_IS_SPAM(msginfo->flags)) {
+                               if (procmsg_spam_learner_learn(msginfo, NULL, FALSE) == 0)
+                                       summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+                               else
+                                       log_error(_("An error happened while learning.\n"));
                } else if (!MSG_IS_REPLIED(msginfo->flags) &&
                         !MSG_IS_FORWARDED(msginfo->flags)) {
                        marked_unread = TRUE;
@@ -4685,7 +5106,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                break;
        case S_COL_LOCKED:
                if (MSG_IS_LOCKED(msginfo->flags)) {
-                       procmsg_msginfo_unset_flags(msginfo, MSG_LOCKED, 0);
+                       summary_msginfo_unset_flags(msginfo, MSG_LOCKED, 0);
                        summary_set_row_marks(summaryview, row);
                }
                else
@@ -4808,11 +5229,13 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
 
        node = GTK_CTREE_NODE(GTK_CLIST(summaryview->ctree)->row_list);
 
-       while (prefs_common.bold_unread && node) {
-               GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
-               if (GTK_CTREE_ROW(node)->children)
-                       summary_set_row_marks(summaryview, node);
-               node = next;
+       if (prefs_common.bold_unread) {
+               while (node) {
+                       GtkCTreeNode *next = GTK_CTREE_NODE_NEXT(node);
+                       if (GTK_CTREE_ROW(node)->children)
+                               summary_set_row_marks(summaryview, node);
+                       node = next;
+               }
        }
        END_TIMING();
 }
@@ -4849,12 +5272,18 @@ static void summary_date_clicked(GtkWidget *button, SummaryView *summaryview)
 
 static void summary_from_clicked(GtkWidget *button, SummaryView *summaryview)
 {
-       summary_sort_by_column_click(summaryview, SORT_BY_FROM);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_FROM]].visible)
+               summary_sort_by_column_click(summaryview, SORT_BY_FROM);
+       else
+               summary_sort_by_column_click(summaryview, SORT_BY_TO);
 }
 
 static void summary_to_clicked(GtkWidget *button, SummaryView *summaryview)
 {
-       summary_sort_by_column_click(summaryview, SORT_BY_TO);
+       if (summaryview->col_state[summaryview->col_pos[S_COL_TO]].visible)
+               summary_sort_by_column_click(summaryview, SORT_BY_TO);
+       else
+               summary_sort_by_column_click(summaryview, SORT_BY_FROM);
 }
 
 static void summary_subject_clicked(GtkWidget *button,
@@ -4909,7 +5338,24 @@ static void summary_drag_data_get(GtkWidget        *widget,
                                (ctree, GTK_CTREE_NODE(cur->data));
                        tmp2 = procmsg_get_message_file(msginfo);
                        if (!tmp2) continue;
-                       tmp1 = g_strconcat("file://", tmp2, NULL);
+                       if (msginfo->subject) {
+                               gchar *san_subject = g_strdup(msginfo->subject);
+                               gchar *dest = NULL;
+                               subst_for_filename(san_subject);
+                               dest = g_strdup_printf("%s%s%s.%d.txt",
+                                               get_tmp_dir(),
+                                               G_DIR_SEPARATOR_S,
+                                               san_subject, msginfo->msgnum);
+                               g_free(san_subject);
+                               san_subject = g_filename_from_utf8(dest, -1, NULL, NULL, NULL);
+                               g_free(dest);
+                               dest = san_subject;
+                               if (copy_file(tmp2, dest, TRUE) == 0) {
+                                       g_free(tmp2);
+                                       tmp2 = dest;
+                               }
+                       } 
+                       tmp1 = g_strconcat("file://", tmp2, "\r\n", NULL);
                        g_free(tmp2);
 
                        if (!mail_list) {
@@ -4932,7 +5378,56 @@ static void summary_drag_data_get(GtkWidget        *widget,
                if (GTK_CLIST(summaryview->ctree)->selection)
                        gtk_selection_data_set(selection_data,
                                               selection_data->target, 8,
-                                              "Dummy", 6);
+                                              "Dummy-Summaryview", 
+                                              strlen("Dummy-Summaryview")+1);
+       }
+}
+
+static gboolean summary_drag_motion_cb(GtkWidget      *widget,
+                                         GdkDragContext *context,
+                                         gint            x,
+                                         gint            y,
+                                         guint           time,
+                                         SummaryView    *summaryview)
+{
+       FolderItem *item = summaryview->folder_item;
+       if (!(item && item->folder && folder_item_parent(item) != NULL
+                   && FOLDER_CLASS(item->folder)->add_msg != NULL)) {
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else if (gtk_drag_get_source_widget(context) ==
+               mainwindow_get_mainwindow()->folderview->ctree) {
+               /* no folders */
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else if (gtk_drag_get_source_widget(context) ==
+               summaryview->ctree) {
+               /* not from same folder */
+               gdk_drag_status(context, 0, time);
+               return FALSE;
+       } else {
+               gdk_drag_status(context, GDK_ACTION_COPY, time);
+               return TRUE;
+       }
+}
+
+static void summary_drag_data_received(GtkWidget        *widget,
+                                       GdkDragContext   *drag_context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *data,
+                                       guint             info,
+                                       guint             time,
+                                       SummaryView       *summaryview)
+{
+       if (info == TARGET_MAIL_URI_LIST) {
+               FolderItem *item = summaryview->folder_item;
+               if (!item) {
+                       gtk_drag_finish(drag_context, FALSE, FALSE, time);                      
+                       return;
+               } else {
+                       folderview_finish_dnd(data->data, drag_context, time, item);
+               }
        }
 }
 
@@ -5071,7 +5566,7 @@ static gint summary_cmp_by_score(GtkCList *clist,
 
        /* if score are equal, sort by date */
 
-       diff = msginfo1->threadscore - msginfo2->threadscore;
+       diff = msginfo1->score - msginfo2->score;
        if (diff != 0)
                return diff;
        else
@@ -5099,7 +5594,7 @@ static void news_flag_crosspost(MsgInfo *msginfo)
                    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)) {
-                               procmsg_msginfo_change_flags(msginfo, 
+                               summary_msginfo_change_flags(msginfo, 
                                        mff->account->crosspost_col, 0, MSG_NEW | MSG_UNREAD, 0);
                        }
                        g_hash_table_remove(mff->newsart, key);
@@ -5116,11 +5611,9 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
-       if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked--;
-
-       procmsg_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0);
+       summary_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0);
 
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is marked as ignore thread\n",
@@ -5149,11 +5642,9 @@ static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpo
        MsgInfo *msginfo;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
 
-       if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
-               summaryview->unreadmarked++;
-
-       procmsg_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0);
+       summary_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0);
 
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is marked as unignore thread\n",
@@ -5185,7 +5676,7 @@ static void summary_check_ignore_thread_func
        if (*found_ignore) return;
        else {
                msginfo = gtk_ctree_node_get_row_data(ctree, row);
-               *found_ignore = MSG_IS_IGNORE_THREAD(msginfo->flags);
+               *found_ignore = msginfo && MSG_IS_IGNORE_THREAD(msginfo->flags);
        }               
 }
 
@@ -5206,71 +5697,18 @@ void summary_toggle_ignore_thread(SummaryView *summaryview)
                summary_ignore_thread(summaryview);
 }
 
-#if 0 /* OLD PROCESSING */
-static gboolean processing_apply_func(GNode *node, gpointer data)
-{
-       FolderItem *item;
-       GSList * processing;
-       SummaryView * summaryview = (SummaryView *) data;
-       
-       if (node == NULL)
-               return FALSE;
-
-       item = node->data;
-       /* prevent from the warning */
-       if (item->path == NULL)
-               return FALSE;
-       processing = item->prefs->processing;
-
-
-       if (processing != NULL) {
-               gchar * buf;
-               GSList * mlist;
-               GSList * cur;
-
-               buf = g_strdup_printf(_("Processing (%s)..."), item->path);
-               debug_print(buf);
-               STATUSBAR_PUSH(summaryview->mainwin, buf);
-               g_free(buf);
-
-               mlist = folder_item_get_msg_list(item);
-               for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = cur->next) {
-                       MsgInfo * msginfo;
-                       
-                       msginfo = (MsgInfo *) cur->data;
-                       filter_message_by_msginfo(processing, msginfo, NULL);
-                       procmsg_msginfo_free(msginfo);
-               }
-
-               g_slist_free(mlist);
-               
-               STATUSBAR_POP(summaryview->mainwin);
-       }
-
-
-       return FALSE;
-}
-
-void processing_apply(SummaryView * summaryview)
-{
-       GList * cur;
-
-       for (cur = folder_get_list() ; cur != NULL && cur->data != NULL ; cur = g_list_next(cur)) {
-               Folder *folder;
-
-               folder = (Folder *) cur->data;
-               g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
-                               processing_apply_func, summaryview);
-       }
-}
-#endif
-
 void summary_toggle_show_read_messages(SummaryView *summaryview)
 {
-       if (summaryview->folder_item->hide_read_msgs)
+       FolderItemUpdateData source;
+       if (summaryview->folder_item->hide_read_msgs)
                summaryview->folder_item->hide_read_msgs = 0;
        else
                summaryview->folder_item->hide_read_msgs = 1;
+
+       source.item = summaryview->folder_item;
+       source.update_flags = F_ITEM_UPDATE_NAME;
+       source.msg = NULL;
+       hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source);
        summary_show(summaryview, summaryview->folder_item);
 }
  
@@ -5308,6 +5746,7 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_KEY, &keyxpm, &keyxpmmask);
        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);
 
        pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_DIR_OPEN);
        gtk_box_pack_start(GTK_BOX(summaryview->hbox), pixmap, FALSE, FALSE, 4);
@@ -5327,6 +5766,22 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        summary_set_column_titles(summaryview);
 }
 
+void summary_reflect_prefs_custom_colors(SummaryView *summaryview)
+{
+       GtkMenuShell *menu;
+       GList *cur;
+
+       /* re-create colorlabel submenu */
+       menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       g_return_if_fail(menu != NULL);
+
+       /* clear items. get item pointers. */
+       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+               gtk_menu_item_remove_submenu(GTK_MENU_ITEM(cur->data));
+       }
+       summary_colorlabel_menu_create(summaryview, TRUE);
+}
+
 /*
  * Harvest addresses for selected messages in summary view.
  */
@@ -5340,6 +5795,8 @@ void summary_harvest_address(SummaryView *summaryview)
        msgList = NULL;
        for( cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next ) {
                msginfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(cur->data) );
+               if (!msginfo)
+                       continue;
                msgList = g_list_append( msgList, GUINT_TO_POINTER( msginfo->msgnum ) );
        }
        addressbook_harvest( summaryview->folder_item, TRUE, msgList );
@@ -5390,15 +5847,6 @@ void summary_set_prefs_from_folderitem(SummaryView *summaryview, FolderItem *ite
        summaryview->thread_collapsed = item->thread_collapsed;
 
        /* Scoring */
-#if 0
-       if (global_scoring || item->prefs->scoring) {
-               summaryview->important_score = prefs_common.important_score;
-               if (item->prefs->important_score >
-                   summaryview->important_score)
-                       summaryview->important_score =
-                               item->prefs->important_score;
-       }
-#endif
 }
 
 void summary_save_prefs_to_folderitem(SummaryView *summaryview, FolderItem *item)
@@ -5422,7 +5870,9 @@ static gboolean summary_update_msg(gpointer source, gpointer data)
        g_return_val_if_fail(summaryview != NULL, FALSE);
 
        if (msginfo_update->flags & MSGINFO_UPDATE_FLAGS) {
-               node = gtk_ctree_find_by_row_data(GTK_CTREE(summaryview->ctree), NULL, msginfo_update->msginfo);
+               node = gtk_ctree_find_by_row_data(
+                               GTK_CTREE(summaryview->ctree), NULL, 
+                               msginfo_update->msginfo);
 
                if (node) 
                        summary_set_row_marks(summaryview, node);
@@ -5469,19 +5919,22 @@ static void summary_find_answers (SummaryView *summaryview, MsgInfo *msg)
                summary_select_node(summaryview, node, TRUE, TRUE);
 }
 
-void summaryview_export_mbox_list(SummaryView *summaryview)
+gint summaryview_export_mbox_list(SummaryView *summaryview)
+/* return values: -2 skipped, -1 error, 0 OK */
 {
        GSList *list = summary_get_selected_msg_list(summaryview);
        gchar *mbox = filesel_select_file_save(_("Export to mbox file"), NULL);
+       gint ret;
        
        if (mbox == NULL || list == NULL)
-               return;
+               return -1;
                
-       export_list_to_mbox(list, mbox);
+       ret = export_list_to_mbox(list, mbox);
        
        g_slist_free(list);
        g_free(mbox);
        
+       return ret;
 }
 
 void summaryview_lock(SummaryView *summaryview, FolderItem *item)