2005-08-30 [colin] 1.9.13cvs73
[claws.git] / src / summaryview.c
index 16744bf081a54e24e7bd4692b4fea520ac274345..16db4655c0ffe075e806c18f92b9ad7288b856fa 100644 (file)
@@ -208,7 +208,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);
@@ -312,6 +312,8 @@ static void summary_date_clicked    (GtkWidget              *button,
                                         SummaryView            *summaryview);
 static void summary_from_clicked       (GtkWidget              *button,
                                         SummaryView            *summaryview);
+static void summary_to_clicked         (GtkWidget              *button,
+                                        SummaryView            *summaryview);
 static void summary_subject_clicked    (GtkWidget              *button,
                                         SummaryView            *summaryview);
 static void summary_score_clicked      (GtkWidget              *button,
@@ -459,6 +461,7 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        "",             /* S_COL_MIME    */
        N_("Subject"),  /* S_COL_SUBJECT */
        N_("From"),     /* S_COL_FROM    */
+       N_("To"),       /* S_COL_TO      */
        N_("Date"),     /* S_COL_DATE    */
        N_("Size"),     /* S_COL_SIZE    */
        N_("No."),      /* S_COL_NUMBER  */
@@ -821,6 +824,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        /* STATUSBAR_POP(summaryview->mainwin); */
 
        is_refresh = (item == summaryview->folder_item) ? TRUE : FALSE;
+
        if (is_refresh) {
                selected_msgnum = summary_get_msgnum(summaryview,
                                                     summaryview->selected);
@@ -896,7 +900,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        mlist = folder_item_get_msg_list(item);
 
-       if (summaryview->folder_item->hide_read_msgs) {
+       if (summaryview->folder_item->hide_read_msgs &&
+           quicksearch_is_active(summaryview->quicksearch) == FALSE) {
                GSList *not_killed;
                
                summary_set_hide_read_msgs_menu(summaryview, TRUE);
@@ -904,11 +909,12 @@ 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_MARKED(msginfo->flags)
-                            || MSG_IS_LOCKED(msginfo->flags)
-                            || CURRENTLY_DISPLAYED(msginfo))
-                            && !MSG_IS_IGNORE_THREAD(msginfo->flags))
+                       if (MSG_IS_UNREAD(msginfo->flags) &&
+                           !MSG_IS_IGNORE_THREAD(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);
@@ -1015,17 +1021,22 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                }
        } else {
                switch (prefs_common.select_on_entry) {
-                       case SELECTONENTRY_UNREAD:
+                       case SELECTONENTRY_NEW:
                                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_NEW:
+                       case SELECTONENTRY_UNREAD:
                                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;
+                               break;
                        default:
-                               node = summary_find_next_flagged_msg(summaryview, NULL,
-                                                                    0, FALSE);
+                               node = NULL;
                }
 
                if (node == NULL && GTK_CLIST(ctree)->row_list != NULL) {
@@ -1948,6 +1959,7 @@ static void summary_set_column_titles(SummaryView *summaryview)
                SORT_BY_MIME,
                SORT_BY_SUBJECT,
                SORT_BY_FROM,
+               SORT_BY_TO,
                SORT_BY_DATE,
                SORT_BY_SIZE,
                SORT_BY_NUMBER,
@@ -1966,6 +1978,7 @@ static void summary_set_column_titles(SummaryView *summaryview)
                switch (type) {
                case S_COL_SUBJECT:
                case S_COL_FROM:
+               case S_COL_TO:
                case S_COL_DATE:
                case S_COL_NUMBER:
                        if (prefs_common.trans_hdr)
@@ -2045,6 +2058,9 @@ void summary_sort(SummaryView *summaryview,
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
        GtkCListCompareFunc cmp_func = NULL;
+       g_signal_handlers_block_by_func(G_OBJECT(summaryview->ctree),
+                                      G_CALLBACK(summary_tree_expanded), summaryview);
+       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
 
        switch (sort_key) {
        case SORT_BY_MARK:
@@ -2089,7 +2105,7 @@ void summary_sort(SummaryView *summaryview,
        case SORT_BY_NONE:
                break;
        default:
-               return;
+               goto unlock;
        }
 
        summaryview->sort_key = sort_key;
@@ -2100,7 +2116,7 @@ void summary_sort(SummaryView *summaryview,
 
        /* allow fallback to don't sort */
        if (summaryview->sort_key == SORT_BY_NONE)
-               return;
+               goto unlock;
 
        if (cmp_func != NULL) {
                debug_print("Sorting summary...");
@@ -2123,6 +2139,10 @@ void summary_sort(SummaryView *summaryview,
                debug_print("done.\n");
                STATUSBAR_POP(summaryview->mainwin);
        }
+unlock:
+       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
+       g_signal_handlers_unblock_by_func(G_OBJECT(summaryview->ctree),
+                                      G_CALLBACK(summary_tree_expanded), summaryview);
 }
 
 gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
@@ -2149,6 +2169,7 @@ gboolean summary_insert_gnode_func(GtkCTree *ctree, guint depth, GNode *gnode,
        SET_TEXT(S_COL_SIZE);
        SET_TEXT(S_COL_DATE);
        SET_TEXT(S_COL_FROM);
+       SET_TEXT(S_COL_TO);
        SET_TEXT(S_COL_SUBJECT);
 
 #undef SET_TEXT
@@ -2279,6 +2300,9 @@ static gchar *summary_complete_address(const gchar *addr)
 {
        gint count;
        gchar *res, *tmp, *email_addr;
+       
+       if (addr == NULL)
+               return NULL;
 
        Xstrdup_a(email_addr, addr, return NULL);
        extract_address(email_addr);
@@ -2290,8 +2314,6 @@ static gchar *summary_complete_address(const gchar *addr)
        res = NULL;
        if (1 < (count = complete_address(email_addr))) {
                tmp = get_complete_address(1);
-/*     tmp = addressbook_lookup_name( email_addr );
-       if( tmp ) { */
                res = procheader_get_fromname(tmp);
                g_free(tmp);
        }
@@ -2303,11 +2325,12 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
                               MsgInfo *msginfo)
 {
        static gchar date_modified[80];
-       static gchar *to = NULL;
        static gchar col_score[11];
        static gchar buf[BUFFSIZE];
        gint *col_pos = summaryview->col_pos;
        FolderType ftype = F_UNKNOWN;
+       gchar *from_text = NULL, *to_text = NULL;
+       gboolean should_swap = FALSE;
 
        text[col_pos[S_COL_MARK]]   = NULL;
        text[col_pos[S_COL_STATUS]] = NULL;
@@ -2327,48 +2350,51 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        else
                text[col_pos[S_COL_DATE]] = _("(No Date)");
 
-       text[col_pos[S_COL_FROM]] = msginfo->fromname ? msginfo->fromname :
-               _("(No From)");
-       
-       if (msginfo->folder && msginfo->folder->folder)
-               ftype = msginfo->folder->folder->klass->type; 
-               
        if (ftype != F_NEWS && prefs_common.swap_from && msginfo->from && msginfo->to) {
                gchar *addr = NULL;
+               
+               addr = g_strdup(msginfo->from);
 
-               Xstrdup_a(addr, msginfo->from, return);
-               extract_address(addr);
-               if (prefs_common.use_addr_book) {
+               if (addr) {
+                       extract_address(addr);
                        if (account_find_from_address(addr)) {
-                               addr = summary_complete_address(msginfo->to);
-                               g_free(to);
-                               to   = g_strconcat("-->", addr == NULL ? msginfo->to : addr, NULL);
-                               text[col_pos[S_COL_FROM]] = to;
-                               g_free(addr);
-                       }
-               } else {
-                       if (account_find_from_address(addr)) {
-                               g_free(to);
-                               to = g_strconcat("-->", msginfo->to, NULL);
-                               text[col_pos[S_COL_FROM]] = to;
+                               should_swap = TRUE;
                        }
+                       g_free(addr);
                }
        }
 
-       /*
-        * CLAWS: note that the "text[col_pos[S_COL_FROM]] != to" is really a hack, 
-        * checking whether the above block (which handles the special case of
-        * the --> in sent boxes) was executed.
-        */
-       if (text[col_pos[S_COL_FROM]] != to && prefs_common.use_addr_book && msginfo->from) {
-               gchar *from = summary_complete_address(msginfo->from);
-               if (from) {
-                       g_free(to);
-                       to = from;
-                       text[col_pos[S_COL_FROM]] = to;
-               }                       
+       if (!prefs_common.use_addr_book) {
+               from_text = msginfo->fromname ? 
+                               msginfo->fromname :
+                               _("(No From)");
+       } else {
+               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)")
+                    )
+                  );
+
+       if (!should_swap) {
+               text[col_pos[S_COL_FROM]] = from_text;
+               text[col_pos[S_COL_TO]] = to_text;
+       } else {
+               gchar *tmp = NULL;
+               tmp = g_strconcat("-->", to_text, NULL);
+               text[col_pos[S_COL_FROM]] = tmp;
+               tmp = g_strconcat("<--", from_text, NULL);
+               text[col_pos[S_COL_TO]] = tmp;
+       }
+       
+       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, 
@@ -2541,9 +2567,10 @@ void summary_reedit(SummaryView *summaryview)
 
        if (!summaryview->selected) return;
        if (!summaryview->folder_item) return;
-       if (summaryview->folder_item->stype != F_OUTBOX &&
-           summaryview->folder_item->stype != F_DRAFT  &&
-           summaryview->folder_item->stype != F_QUEUE) 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))
+               return;
 
        msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree),
                                              summaryview->selected);
@@ -2780,8 +2807,7 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE | MSG_COPY);
-       procmsg_msginfo_set_flags(msginfo, MSG_MARKED, 0);
+       procmsg_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);
 }
@@ -2804,8 +2830,8 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
                changed = TRUE;
        }
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE | MSG_COPY);
-       procmsg_msginfo_set_flags(msginfo, MSG_LOCKED, 0);
+       procmsg_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);
 }
@@ -3035,12 +3061,11 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, MSG_MOVE | MSG_COPY);
-       procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
+       procmsg_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, MSG_MOVE | MSG_COPY);
        summaryview->deleted++;
 
        if (!prefs_common.immediate_exec && 
-           summaryview->folder_item->stype != F_TRASH)
+           !folder_has_parent_of_type(summaryview->folder_item, F_TRASH))
                summary_set_row_marks(summaryview, row);
 
        debug_print("Message %s/%d is set to delete\n",
@@ -3127,7 +3152,7 @@ void summary_delete(SummaryView *summaryview)
 
        summary_select_node(summaryview, node, prefs_common.always_show_msg, TRUE);
        
-       if (prefs_common.immediate_exec || item->stype == F_TRASH) {
+       if (prefs_common.immediate_exec || folder_has_parent_of_type(item, F_TRASH)) {
                summary_execute(summaryview);
                /* after deleting, the anchor may be at an invalid row
                 * so reset it to the node we found earlier */
@@ -3140,12 +3165,16 @@ void summary_delete(SummaryView *summaryview)
 
 void summary_delete_trash(SummaryView *summaryview)
 {
-       FolderItem *to_folder;
-
+       FolderItem *to_folder = NULL;
+       PrefsAccount *ac;
        if (!summaryview->folder_item ||
            FOLDER_TYPE(summaryview->folder_item->folder) == F_NEWS) return;
+       
+       if (NULL != (ac = account_find_from_item(summaryview->folder_item)))
+               to_folder = account_get_special_folder(ac, F_TRASH);
 
-       to_folder = summaryview->folder_item->folder->trash;
+       if (to_folder == NULL)
+               to_folder = summaryview->folder_item->folder->trash;
        
        if (to_folder == NULL || to_folder == summaryview->folder_item)
                summary_delete(summaryview);
@@ -3208,11 +3237,13 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        if (MSG_IS_COPY(msginfo->flags)) {
                summaryview->copied--;
        }
-       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_COPY);
        if (!MSG_IS_MOVE(msginfo->flags)) {
-               procmsg_msginfo_set_flags(msginfo, 0, MSG_MOVE);
+               procmsg_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_MARKED | MSG_DELETED, MSG_COPY);
                summaryview->moved++;
+       } else {
+               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_COPY);
        }
+       
        if (!prefs_common.immediate_exec) {
                summary_set_row_marks(summaryview, row);
        }
@@ -3287,10 +3318,12 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        if (MSG_IS_MOVE(msginfo->flags)) {
                summaryview->moved--;
        }
-       procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE);
+       
        if (!MSG_IS_COPY(msginfo->flags)) {
-               procmsg_msginfo_set_flags(msginfo, 0, MSG_COPY);
+               procmsg_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_MARKED | MSG_DELETED, MSG_MOVE);
                summaryview->copied++;
+       } else {
+               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE);
        }
        if (!prefs_common.immediate_exec) {
                summary_set_row_marks(summaryview, row);
@@ -3537,6 +3570,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;
 
@@ -3549,7 +3583,7 @@ gboolean summary_execute(SummaryView *summaryview)
                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);
        
@@ -3586,8 +3620,7 @@ gboolean summary_execute(SummaryView *summaryview)
                summary_unlock(summaryview);
                gtk_sctree_select
                        (GTK_SCTREE(ctree),
-                        summaryview->displayed ? summaryview->displayed
-                        : new_selected);
+                        new_selected);
                summary_lock(summaryview);
        }
 
@@ -3614,26 +3647,30 @@ gboolean summary_execute(SummaryView *summaryview)
        gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
 
        summary_unlock(summaryview);
+       
+       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;
 }
 
 static void summary_execute_move_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -3882,22 +3919,18 @@ static void summary_unthread_for_exec(SummaryView *summaryview)
        GtkCTreeNode *node;
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
 
-       summary_lock(summaryview);
-
        debug_print("Unthreading for execution...");
 
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       START_LONG_OPERATION(summaryview);
 
        for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
             node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
                summary_unthread_for_exec_func(ctree, node, NULL);
        }
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
+       END_LONG_OPERATION(summaryview);
 
        debug_print("done.\n");
-
-       summary_unlock(summaryview);
 }
 
 static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -4145,8 +4178,8 @@ static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *r
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
 
-       procmsg_msginfo_unset_flags(msginfo, MSG_CLABEL_FLAG_MASK, 0);
-       procmsg_msginfo_set_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0);
+       procmsg_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, 
+                                       MSG_CLABEL_FLAG_MASK, 0);
 }
 
 void summary_set_colorlabel(SummaryView *summaryview, guint labelcolor,
@@ -4322,6 +4355,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                                   prefs_common.summary_col_size[S_COL_SUBJECT]);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_FROM],
                                   prefs_common.summary_col_size[S_COL_FROM]);
+       gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_TO],
+                                  prefs_common.summary_col_size[S_COL_TO]);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_DATE],
                                   prefs_common.summary_col_size[S_COL_DATE]);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_SIZE],
@@ -4363,6 +4398,7 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SIZE   , summary_size_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_DATE   , summary_date_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_FROM   , summary_from_clicked);
+       CLIST_BUTTON_SIGNAL_CONNECT(S_COL_TO     , summary_to_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SUBJECT, summary_subject_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SCORE,   summary_score_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_LOCKED,  summary_locked_clicked);
@@ -4610,9 +4646,9 @@ static void tog_searchbar_cb(GtkWidget *w, gpointer data)
 
 static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview)
 {
-       if (summaryview->folder_item->stype == F_OUTBOX ||
-           summaryview->folder_item->stype == F_DRAFT  ||
-           summaryview->folder_item->stype == F_QUEUE)
+       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))
                summary_reedit(summaryview);
        else
                summary_open_msg(summaryview);
@@ -4644,7 +4680,8 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        MsgInfo *msginfo;
        gboolean marked_unread = FALSE;
 
-       if (summary_is_locked(summaryview)) {
+       if (summary_is_locked(summaryview)
+       ||  GTK_SCTREE(ctree)->selecting_range) {
                return;
        }
 
@@ -4803,9 +4840,6 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
 {
        GtkCTreeNode *node = NULL;
        START_TIMING("summary_sort_by_column_click");
-       g_signal_handlers_block_by_func(G_OBJECT(summaryview->ctree),
-                                      G_CALLBACK(summary_tree_expanded), summaryview);
-       gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
        if (summaryview->sort_key == sort_key)
                summary_sort(summaryview, sort_key,
                             summaryview->sort_type == SORT_ASCENDING
@@ -4813,10 +4847,6 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
        else
                summary_sort(summaryview, sort_key, SORT_ASCENDING);
 
-       gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
-       g_signal_handlers_unblock_by_func(G_OBJECT(summaryview->ctree),
-                                      G_CALLBACK(summary_tree_expanded), summaryview);
-
        node = GTK_CTREE_NODE(GTK_CLIST(summaryview->ctree)->row_list);
 
        while (prefs_common.bold_unread && node) {
@@ -4863,6 +4893,11 @@ static void summary_from_clicked(GtkWidget *button, SummaryView *summaryview)
        summary_sort_by_column_click(summaryview, SORT_BY_FROM);
 }
 
+static void summary_to_clicked(GtkWidget *button, SummaryView *summaryview)
+{
+       summary_sort_by_column_click(summaryview, SORT_BY_TO);
+}
+
 static void summary_subject_clicked(GtkWidget *button,
                                    SummaryView *summaryview)
 {
@@ -4974,24 +5009,6 @@ CMP_FUNC_DEF(summary_cmp_by_num, msginfo1->msgnum - msginfo2->msgnum)
 CMP_FUNC_DEF(summary_cmp_by_size, msginfo1->size - msginfo2->size)
 CMP_FUNC_DEF(summary_cmp_by_date, msginfo1->date_t - msginfo2->date_t)
 
-#undef CMP_FUNC_DEF
-#define CMP_FUNC_DEF(func_name, var_name)                               \
-static gint func_name(GtkCList *clist,                                  \
-                     gconstpointer ptr1, gconstpointer ptr2)            \
-{                                                                       \
-       MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data;                 \
-       MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data;                 \
-                                                                        \
-       if (!msginfo1->var_name)                                         \
-               return (msginfo2->var_name != NULL);                     \
-       if (!msginfo2->var_name)                                         \
-               return -1;                                               \
-                                                                        \
-       return g_utf8_collate(msginfo1->var_name, msginfo2->var_name);   \
-}
-
-CMP_FUNC_DEF(summary_cmp_by_to, to);
-
 #undef CMP_FUNC_DEF
 
 static gint summary_cmp_by_subject(GtkCList *clist,
@@ -5032,6 +5049,28 @@ static gint summary_cmp_by_from(GtkCList *clist, gconstpointer ptr1,
        return g_utf8_collate(str1, str2);
 }
  
+static gint summary_cmp_by_to(GtkCList *clist, gconstpointer ptr1,
+                               gconstpointer ptr2)
+{
+       const gchar *str1, *str2;
+       const GtkCListRow *r1 = (const GtkCListRow *) ptr1;
+       const GtkCListRow *r2 = (const GtkCListRow *) ptr2;
+       const SummaryView *sv = g_object_get_data(G_OBJECT(clist), "summaryview");
+       
+       g_return_val_if_fail(sv, -1);
+       
+       str1 = GTK_CELL_TEXT(r1->cell[sv->col_pos[S_COL_TO]])->text;
+       str2 = GTK_CELL_TEXT(r2->cell[sv->col_pos[S_COL_TO]])->text;
+
+       if (!str1)
+               return str2 != NULL;
+       if (!str2)
+               return -1;
+       return g_utf8_collate(str1, str2);
+}
 static gint summary_cmp_by_simplified_subject
        (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
 {
@@ -5095,14 +5134,14 @@ static void news_flag_crosspost(MsgInfo *msginfo)
 
        if (mff->account->mark_crosspost_read) {
                line = g_string_sized_new(128);
-               g_string_sprintf(line, "%s:%d", msginfo->folder->path, msginfo->msgnum);
+               g_string_printf(line, "%s:%d", msginfo->folder->path, msginfo->msgnum);
                debug_print("nfcp: checking <%s>", line->str);
                if (mff->newsart && 
                    g_hash_table_lookup_extended(mff->newsart, line->str, &key, &value)) {
                        debug_print(" <%s>", (gchar *)value);
                        if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
-                               procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
-                               procmsg_msginfo_set_flags(msginfo, mff->account->crosspost_col, 0);
+                               procmsg_msginfo_change_flags(msginfo, 
+                                       mff->account->crosspost_col, 0, MSG_NEW | MSG_UNREAD, 0);
                        }
                        g_hash_table_remove(mff->newsart, key);
                        g_free(key);
@@ -5122,8 +5161,7 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin
        if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                summaryview->unreadmarked--;
 
-       procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0);
-       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
+       procmsg_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",