X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fsummaryview.c;h=fa34635ede7bf2711abc46d48e9edbed05d700ab;hp=bbdd58e85c9ddc67145daf25ca633e3d81983b93;hb=3d8e51875c27c3ab6454632e66acfbda72bbfb53;hpb=4f7b40c17176b49d2135466f29783bbb30c74490 diff --git a/src/summaryview.c b/src/summaryview.c index bbdd58e85..fa34635ed 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -75,6 +74,7 @@ #include "addr_compl.h" #include "scoring.h" #include "prefs_folder_item.h" +#include "filtering.h" #include "pixmaps/dir-open.xpm" #include "pixmaps/mark.xpm" @@ -84,6 +84,7 @@ #include "pixmaps/replied.xpm" #include "pixmaps/forwarded.xpm" #include "pixmaps/clip.xpm" +#include "pixmaps/ignorethread.xpm" #define STATUSBAR_PUSH(mainwin, str) \ { \ @@ -120,6 +121,8 @@ static GdkPixmap *repliedxpm; static GdkBitmap *repliedxpmmask; static GdkPixmap *forwardedxpm; static GdkBitmap *forwardedxpmmask; +static GdkPixmap *ignorethreadxpm; +static GdkBitmap *ignorethreadxpmmask; static GdkPixmap *clipxpm; static GdkBitmap *clipxpmmask; @@ -204,6 +207,8 @@ static void summary_execute_delete (SummaryView *summaryview); static void summary_execute_delete_func (GtkCTree *ctree, GtkCTreeNode *node, gpointer data); +static void summary_ignore_thread(SummaryView *summaryview); +static void summary_unignore_thread(SummaryView *summaryview); /* thread functions */ static void summary_thread_func (GtkCTree *ctree, @@ -266,6 +271,8 @@ static void summary_from_clicked (GtkWidget *button, SummaryView *summaryview); static void summary_subject_clicked (GtkWidget *button, SummaryView *summaryview); +static void summary_mark_clicked (GtkWidget *button, + SummaryView *summaryview); static void summary_start_drag (GtkWidget *widget, int button, @@ -298,6 +305,9 @@ static gint summary_cmp_by_subject (GtkCList *clist, static gint summary_cmp_by_score (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2); +static gint summary_cmp_by_label (GtkCList *clist, + gconstpointer ptr1, + gconstpointer ptr2); GtkTargetEntry summary_drag_types[1] = { @@ -315,20 +325,34 @@ static GtkItemFactoryEntry summary_popup_entries[] = {N_("/_Mark/_Unmark"), NULL, summary_unmark, 0, NULL}, {N_("/_Mark/---"), NULL, NULL, 0, ""}, {N_("/_Mark/Mark as unr_ead"), NULL, summary_mark_as_unread, 0, NULL}, - {N_("/_Mark/Make it as _being read"), - NULL, summary_mark_as_read, 0, NULL}, + {N_("/_Mark/Mark as rea_d"), NULL, summary_mark_as_read, 0, NULL}, + {N_("/_Mark/Ignore thread"), NULL, summary_ignore_thread, 0, NULL}, + {N_("/_Mark/Unignore thread"), NULL, summary_unignore_thread, 0, NULL}, + + {N_("/_Label"), NULL, NULL, 0, ""}, + {N_("/_Label/None"), NULL, summary_set_label, MSG_LABEL_NONE, NULL}, + {N_("/_Label/---"), NULL, NULL, 0, ""}, + {N_("/_Label/Orange"), NULL, summary_set_label, MSG_LABEL_ORANGE, NULL}, + {N_("/_Label/Red"), NULL, summary_set_label, MSG_LABEL_RED, NULL}, + {N_("/_Label/Pink"), NULL, summary_set_label, MSG_LABEL_PINK, NULL}, + {N_("/_Label/SkyBlue"), NULL, summary_set_label, MSG_LABEL_SKYBLUE, NULL}, + {N_("/_Label/Blue"), NULL, summary_set_label, MSG_LABEL_BLUE, NULL}, + {N_("/_Label/Green"), NULL, summary_set_label, MSG_LABEL_GREEN, NULL}, + {N_("/_Label/Brown"), NULL, summary_set_label, MSG_LABEL_BROWN, NULL}, + {N_("/---"), NULL, NULL, 0, ""}, {N_("/_Reply"), NULL, summary_reply_cb, COMPOSE_REPLY, NULL}, + {N_("/Repl_y to sender"), NULL, summary_reply_cb, COMPOSE_REPLY_TO_SENDER, NULL}, + {N_("/Follow-up and reply to"), NULL, summary_reply_cb, COMPOSE_FOLLOWUP_AND_REPLY_TO, NULL}, {N_("/Reply to a_ll"), NULL, summary_reply_cb, COMPOSE_REPLY_TO_ALL, NULL}, - {N_("/Reply to author"), NULL, summary_reply_cb, COMPOSE_REPLY_TO_AUTHOR, NULL}, {N_("/_Forward"), NULL, summary_reply_cb, COMPOSE_FORWARD, NULL}, - {N_("/Forward as an a_ttachment"), + {N_("/Forward as a_ttachment"), NULL, summary_reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL}, {N_("/---"), NULL, NULL, 0, ""}, {N_("/Open in new _window"), NULL, summary_open_msg, 0, NULL}, {N_("/View so_urce"), NULL, summary_view_source, 0, NULL}, {N_("/Show all _header"), NULL, summary_show_all_header_cb, 0, NULL}, - {N_("/Re_edit"), NULL, summary_reedit, 0, NULL}, + {N_("/Re-_edit"), NULL, summary_reedit, 0, NULL}, {N_("/---"), NULL, NULL, 0, ""}, {N_("/_Save as..."), NULL, summary_save_as, 0, NULL}, {N_("/_Print..."), NULL, summary_print, 0, NULL}, @@ -336,6 +360,95 @@ static GtkItemFactoryEntry summary_popup_entries[] = {N_("/Select _all"), NULL, summary_select_all, 0, NULL} }; +void summary_set_label_color(GtkCTree *ctree, GtkCTreeNode *node, + guint labelcolor) +{ + GdkColor color; + GtkStyle *style, *prev_style, *ctree_style; + MsgInfo *msginfo; + + ctree_style = gtk_widget_get_style(GTK_WIDGET(ctree)); + + prev_style = gtk_ctree_node_get_row_style(ctree, node); + + if (!prev_style) + prev_style = ctree_style; + + style = gtk_style_copy(prev_style); + + switch (labelcolor) { + case MSG_LABEL_ORANGE: + color.red = 0xffff; + color.green = (0x99<<8); + color.blue = 0x0; + break; + case MSG_LABEL_RED: + color.red = 0xffff; + color.green = color.blue = 0x0; + break; + case MSG_LABEL_PINK: + color.red = 0xffff; + color.green = (0x66<<8); + color.blue = 0xffff; + break; + case MSG_LABEL_SKYBLUE: + color.red = 0x0; + color.green = (0xcc<<8); + color.blue = 0xffff; + break; + case MSG_LABEL_BLUE: + color.red = 0x0; + color.green = 0x0; + color.blue = 0xffff; + break; + case MSG_LABEL_GREEN: + color.red = 0x0; + color.green = (0x99<<8); + color.blue = 0x0; + break; + case MSG_LABEL_BROWN: + color.red = (0x66<<8); + color.green = (0x33<<8); + color.blue = (0x33<<8); + break; + case MSG_LABEL_NONE: + default: + labelcolor = MSG_LABEL_NONE; + color.red = ctree_style->fg[GTK_STATE_NORMAL].red; + color.green = ctree_style->fg[GTK_STATE_NORMAL].green; + color.blue = ctree_style->fg[GTK_STATE_NORMAL].blue; + style->fg[GTK_STATE_NORMAL] = color; + + color.red = ctree_style->fg[GTK_STATE_SELECTED].red; + color.green = ctree_style->fg[GTK_STATE_SELECTED].green; + color.blue = ctree_style->fg[GTK_STATE_SELECTED].blue; + style->fg[GTK_STATE_SELECTED] = color; + gtk_ctree_node_set_row_style(ctree, node, style); + break; + } + + msginfo = gtk_ctree_node_get_row_data(ctree, node); + + MSG_UNSET_FLAGS(msginfo->flags, MSG_LABEL); + MSG_SET_FLAGS(msginfo->flags, labelcolor); + + if ( style ) { + style->fg[GTK_STATE_NORMAL] = color; + style->fg[GTK_STATE_SELECTED] = color; + gtk_ctree_node_set_row_style(ctree, node, style); + } +} + +void summary_set_label(SummaryView *summaryview, guint labelcolor, GtkWidget *widget) +{ + GtkCTree *ctree = GTK_CTREE(summaryview->ctree); + GtkCList *clist = GTK_CLIST(summaryview->ctree); + GList *cur; + + for (cur = clist->selection; cur != NULL; cur = cur->next) + summary_set_label_color(ctree, GTK_CTREE_NODE(cur->data), labelcolor); +} + SummaryView *summary_create(void) { SummaryView *summaryview; @@ -351,7 +464,6 @@ SummaryView *summary_create(void) GtkWidget *toggle_arrow; GtkWidget *popupmenu; GtkItemFactory *popupfactory; - GtkBindingSet *binding_set; gint n_entries; gint i; @@ -467,6 +579,11 @@ SummaryView *summary_create(void) "clicked", GTK_SIGNAL_FUNC(summary_subject_clicked), summaryview); + gtk_signal_connect + (GTK_OBJECT(GTK_CLIST(ctree)->column[S_COL_MARK].button), + "clicked", + GTK_SIGNAL_FUNC(summary_mark_clicked), + summaryview); /* create status label */ hbox = gtk_hbox_new(FALSE, 0); @@ -493,20 +610,6 @@ SummaryView *summary_create(void) "", &popupfactory, summaryview); - /* bind keys */ - binding_set = gtk_binding_set_by_class - (GTK_CLIST_CLASS(GTK_OBJECT(ctree)->klass)); - - gtk_binding_entry_add_signal(binding_set, GDK_n, GDK_CONTROL_MASK, - "scroll_vertical", 2, - GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD, - GTK_TYPE_FLOAT, 0.0); - gtk_binding_entry_add_signal(binding_set, GDK_p, GDK_CONTROL_MASK, - "scroll_vertical", 2, - GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD, - GTK_TYPE_FLOAT, 0.0); - gtk_binding_entry_clear(binding_set, GDK_space, 0); - /* connect signals */ gtk_signal_connect(GTK_OBJECT(ctree), "tree_select_row", GTK_SIGNAL_FUNC(summary_selected), summaryview); @@ -562,6 +665,8 @@ void summary_init(SummaryView *summaryview) replied_xpm); PIXMAP_CREATE(summaryview->ctree, forwardedxpm, forwardedxpmmask, forwarded_xpm); + PIXMAP_CREATE(summaryview->ctree, ignorethreadxpm, ignorethreadxpmmask, + ignorethread_xpm); PIXMAP_CREATE(summaryview->ctree, clipxpm, clipxpmmask, clip_xpm); PIXMAP_CREATE(summaryview->hbox, folderxpm, folderxpmmask, DIRECTORY_OPEN_XPM); @@ -590,6 +695,68 @@ void summary_init(SummaryView *summaryview) summary_set_menu_sensitive(summaryview); } +GtkCTreeNode * summary_find_next_important_score(SummaryView *summaryview, + GtkCTreeNode *current_node) +{ + GtkCTree *ctree = GTK_CTREE(summaryview->ctree); + GtkCTreeNode *node; + MsgInfo *msginfo; + gint best_score = MIN_SCORE; + GtkCTreeNode *best_node = NULL; + + if (current_node) + /*node = current_node;*/ + node = GTK_CTREE_NODE_NEXT(current_node); + else + node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); + + for (; node != NULL; node = GTK_CTREE_NODE_NEXT(node)) { + msginfo = gtk_ctree_node_get_row_data(ctree, node); + if (msginfo->score >= summaryview->important_score) + break; + if (msginfo->score > best_score) { + best_score = msginfo->score; + best_node = node; + } + } + + if (node != NULL) + return node; + else + return best_node; +} + +GtkCTreeNode * summary_find_prev_important_score(SummaryView *summaryview, + GtkCTreeNode *current_node) +{ + GtkCTree *ctree = GTK_CTREE(summaryview->ctree); + GtkCTreeNode *node; + MsgInfo *msginfo; + gint best_score = MIN_SCORE; + GtkCTreeNode *best_node = NULL; + + if (current_node) + /*node = current_node;*/ + node = GTK_CTREE_NODE_PREV(current_node); + else + node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); + + for (; node != NULL; node = GTK_CTREE_NODE_PREV(node)) { + msginfo = gtk_ctree_node_get_row_data(ctree, node); + if (msginfo->score >= summaryview->important_score) + break; + if (msginfo->score > best_score) { + best_score = msginfo->score; + best_node = node; + } + } + + if (node != NULL) + return node; + else + return best_node; +} + gboolean summary_show(SummaryView *summaryview, FolderItem *item, gboolean update_cache) { @@ -599,6 +766,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, gchar *buf; gboolean is_refresh; guint prev_msgnum = 0; + GtkCTreeNode *selected_node = summaryview->folderview->selected; GSList *cur; gint sort_mode; gint sort_type; @@ -613,9 +781,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, is_refresh = FALSE; } -#if 0 /* process the marks if any */ - if (summaryview->deleted > 0 || summaryview->moved > 0) { + if (summaryview->moved > 0 || summaryview->copied > 0) { AlertValue val; val = alertpanel(_("Process mark"), @@ -628,9 +795,9 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, else return FALSE; } else -#endif - if (!is_refresh) - summary_write_cache(summaryview); + summary_write_cache(summaryview); + + summaryview->folderview->opened = selected_node; gtk_clist_freeze(GTK_CLIST(ctree)); @@ -639,7 +806,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, messageview_clear(summaryview->messageview); buf = NULL; - if (!item || !item->path || !item->parent || + if (!item || !item->path || !item->parent || item->no_select || (item->folder->type == F_MH && ((buf = folder_item_get_path(item)) == NULL || change_dir(buf) < 0))) { @@ -668,7 +835,36 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, for(cur = mlist ; cur != NULL ; cur = g_slist_next(cur)) { MsgInfo * msginfo = (MsgInfo *) cur->data; - msginfo->score = score_message(prefs_scoring, msginfo); + msginfo->score = score_message(global_scoring, msginfo); + if (msginfo->score != MAX_SCORE && + msginfo->score != MIN_SCORE) { + msginfo->score += score_message(item->prefs->scoring, + msginfo); + } + } + + summaryview->killed_messages = NULL; + if ((global_scoring || item->prefs->scoring) && + (item->folder->type == F_NEWS)) { + 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 = g_slist_next(cur)) { + MsgInfo * msginfo = (MsgInfo *) cur->data; + + if (MSG_IS_NEWS(msginfo->flags) && + (msginfo->score <= kill_score)) + summaryview->killed_messages = g_slist_append(summaryview->killed_messages, msginfo); + else + not_killed = g_slist_append(not_killed, + msginfo); + } + g_slist_free(mlist); + mlist = not_killed; } STATUSBAR_POP(summaryview->mainwin); @@ -697,20 +893,39 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, GTK_SIGNAL_FUNC(summary_open_row), summaryview); /*connect drag and drop signal*/ - gtk_signal_connect (GTK_OBJECT (ctree),"start_drag", - GTK_SIGNAL_FUNC (summary_start_drag), - summaryview); - gtk_signal_connect (GTK_OBJECT (ctree),"drag_data_get", - GTK_SIGNAL_FUNC (summary_drag_data_get), - summaryview); - - gtk_clist_thaw(GTK_CLIST(ctree)); + gtk_signal_connect(GTK_OBJECT (ctree),"start_drag", + GTK_SIGNAL_FUNC (summary_start_drag), + summaryview); + gtk_signal_connect(GTK_OBJECT (ctree),"drag_data_get", + GTK_SIGNAL_FUNC (summary_drag_data_get), + summaryview); + + gtk_clist_thaw(GTK_CLIST(ctree)); + + /* sort before */ + sort_mode = prefs_folder_item_get_sort_mode(item); + sort_type = prefs_folder_item_get_sort_type(item); + + if (sort_mode != SORT_BY_NONE) { + summaryview->sort_mode = sort_mode; + if (sort_type == GTK_SORT_DESCENDING) + summaryview->sort_type = GTK_SORT_ASCENDING; + else + summaryview->sort_type = GTK_SORT_DESCENDING; + + summary_sort(summaryview, sort_mode); + } if (is_refresh) { summary_select_by_msgnum(summaryview, prev_msgnum); } else { /* select first unread message */ - node = summary_find_next_unread_msg(summaryview, NULL); + if (sort_mode == SORT_BY_SCORE) + node = summary_find_next_important_score(summaryview, + NULL); + else + node = summary_find_next_unread_msg(summaryview, NULL); + if (node == NULL && GTK_CLIST(ctree)->row_list != NULL) node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list_end); if (node) { @@ -735,20 +950,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item, main_window_cursor_normal(summaryview->mainwin); - /* sort before */ - sort_mode = prefs_folder_item_get_sort_mode(item); - sort_type = prefs_folder_item_get_sort_type(item); - - if (sort_mode != SORT_BY_NONE) { - summaryview->sort_mode = sort_mode; - if (sort_type == GTK_SORT_DESCENDING) - summaryview->sort_type = GTK_SORT_ASCENDING; - else - summaryview->sort_type = GTK_SORT_DESCENDING; - - summary_sort(summaryview, sort_mode); - } - return TRUE; } @@ -756,9 +957,19 @@ void summary_clear_list(SummaryView *summaryview) { GtkCList *clist = GTK_CLIST(summaryview->ctree); gint optimal_width; + GSList * cur; gtk_clist_freeze(clist); + for(cur = summaryview->killed_messages ; cur != NULL ; + cur = g_slist_next(cur)) { + MsgInfo * msginfo = (MsgInfo *) cur->data; + + procmsg_msginfo_free(msginfo); + } + g_slist_free(summaryview->killed_messages); + summaryview->killed_messages = NULL; + gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL, summary_free_msginfo_func, NULL); @@ -776,6 +987,10 @@ void summary_clear_list(SummaryView *summaryview) g_hash_table_destroy(summaryview->msgid_table); summaryview->msgid_table = NULL; } + if (summaryview->subject_table) { + g_hash_table_destroy(summaryview->subject_table); + summaryview->subject_table = NULL; + } summaryview->mlist = NULL; if (summaryview->folder_table) { g_hash_table_destroy(summaryview->folder_table); @@ -838,18 +1053,18 @@ static void summary_set_menu_sensitive(SummaryView *summaryview) sens = (selection == SUMMARY_SELECTED_MULTIPLE) ? FALSE : TRUE; menu_set_sensitive(ifactory, "/Reply", sens); + menu_set_sensitive(ifactory, "/Reply to sender", sens); menu_set_sensitive(ifactory, "/Reply to all", sens); - menu_set_sensitive(ifactory, "/Reply to author", sens); - menu_set_sensitive(ifactory, "/Forward", sens); - menu_set_sensitive(ifactory, "/Forward as an attachment", sens); - + menu_set_sensitive(ifactory, "/Forward", TRUE); + menu_set_sensitive(ifactory, "/Forward as attachment", TRUE); + menu_set_sensitive(ifactory, "/Open in new window", sens); menu_set_sensitive(ifactory, "/View source", sens); menu_set_sensitive(ifactory, "/Show all header", sens); if ((summaryview->folder_item->stype == F_DRAFT) || (summaryview->folder_item->stype == F_OUTBOX) || (summaryview->folder_item->stype == F_QUEUE)) - menu_set_sensitive(ifactory, "/Reedit", sens); + menu_set_sensitive(ifactory, "/Re-edit", sens); menu_set_sensitive(ifactory, "/Save as...", sens); menu_set_sensitive(ifactory, "/Print...", TRUE); @@ -859,10 +1074,21 @@ static void summary_set_menu_sensitive(SummaryView *summaryview) menu_set_sensitive(ifactory, "/Mark/Mark", TRUE); menu_set_sensitive(ifactory, "/Mark/Unmark", TRUE); - menu_set_sensitive(ifactory, "/Mark/Mark as unread", TRUE); - menu_set_sensitive(ifactory, "/Mark/Make it as being read", TRUE); + menu_set_sensitive(ifactory, "/Mark/Mark as unread", TRUE); + menu_set_sensitive(ifactory, "/Mark/Mark as read", TRUE); + menu_set_sensitive(ifactory, "/Mark/Ignore thread", TRUE); + menu_set_sensitive(ifactory, "/Mark/Unignore thread", TRUE); + + menu_set_sensitive(ifactory, "/Label", TRUE); menu_set_sensitive(ifactory, "/Select all", TRUE); + + if (summaryview->folder_item->folder->account) + sens = summaryview->folder_item->folder->account->protocol + == A_NNTP; + else + sens = FALSE; + menu_set_sensitive(ifactory, "/Follow-up and reply to", sens); } void summary_select_next_unread(SummaryView *summaryview) @@ -876,6 +1102,8 @@ void summary_select_next_unread(SummaryView *summaryview) if (node) { gtk_sctree_unselect_all(GTK_SCTREE(ctree)); gtk_sctree_select(GTK_SCTREE(ctree), node); + gtk_ctree_node_moveto(ctree, node, -1, 0.5, 0.0); + if (summaryview->displayed == node) summaryview->displayed = NULL; summary_display_msg(summaryview, node, FALSE); @@ -964,11 +1192,16 @@ void summary_select_by_msgnum(SummaryView *summaryview, guint msgnum) node = summary_find_msg_by_msgnum(summaryview, msgnum); if (node) { + GTK_EVENTS_FLUSH(); + gtk_ctree_node_moveto(ctree, node, -1, 0.5, 0); + gtk_widget_grab_focus(GTK_WIDGET(ctree)); gtk_sctree_unselect_all(GTK_SCTREE(ctree)); gtk_sctree_select(GTK_SCTREE(ctree), node); - if (summaryview->displayed == node) - summaryview->displayed = NULL; - summary_display_msg(summaryview, node, FALSE); + if (summaryview->msg_is_toggled_on) { + if (summaryview->displayed == node) + summaryview->displayed = NULL; + summary_display_msg(summaryview, node, FALSE); + } } } @@ -992,13 +1225,13 @@ static GtkCTreeNode *summary_find_next_unread_msg(SummaryView *summaryview, if (current_node) node = current_node; - //node = GTK_CTREE_NODE_NEXT(current_node); + /*node = GTK_CTREE_NODE_NEXT(current_node);*/ else node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list); for (; node != NULL; node = GTK_CTREE_NODE_NEXT(node)) { msginfo = gtk_ctree_node_get_row_data(ctree, node); - if (MSG_IS_UNREAD(msginfo->flags)) break; + if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) break; } return node; @@ -1071,7 +1304,7 @@ static GtkCTreeNode *summary_find_prev_unread_msg(SummaryView *summaryview, if (current_node) node = current_node; - //node = GTK_CTREE_NODE_PREV(current_node); + /*node = GTK_CTREE_NODE_PREV(current_node);*/ else node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list_end); @@ -1188,9 +1421,9 @@ static void summary_set_marks_func(GtkCTree *ctree, GtkCTreeNode *node, msginfo = gtk_ctree_node_get_row_data(ctree, node); - if (MSG_IS_NEW(msginfo->flags)) + if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->newmsgs++; - if (MSG_IS_UNREAD(msginfo->flags)) + if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->unread++; if (MSG_IS_DELETED(msginfo->flags)) summaryview->deleted++; @@ -1215,9 +1448,9 @@ static void summary_update_status(SummaryView *summaryview) node != NULL; node = GTK_CTREE_NODE_NEXT(node)) { msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node); - if (MSG_IS_NEW(msginfo->flags)) + if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->newmsgs++; - if (MSG_IS_UNREAD(msginfo->flags)) + if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->unread++; if (MSG_IS_DELETED(msginfo->flags)) summaryview->deleted++; @@ -1351,6 +1584,9 @@ void summary_sort(SummaryView *summaryview, SummarySortType type) case SORT_BY_SCORE: cmp_func = (GtkCListCompareFunc)summary_cmp_by_score; break; + case SORT_BY_LABEL: + cmp_func = (GtkCListCompareFunc)summary_cmp_by_label; + break; default: return; } @@ -1375,7 +1611,7 @@ void summary_sort(SummaryView *summaryview, SummarySortType type) gtk_ctree_sort_node(ctree, NULL); gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0); - //gtkut_ctree_set_focus_row(ctree, summaryview->selected); + /*gtkut_ctree_set_focus_row(ctree, summaryview->selected);*/ prefs_folder_item_set_config(summaryview->folder_item, summaryview->sort_type, @@ -1388,6 +1624,24 @@ void summary_sort(SummaryView *summaryview, SummarySortType type) main_window_cursor_normal(summaryview->mainwin); } +static GtkCTreeNode * subject_table_lookup(GHashTable *subject_table, + gchar * subject) +{ + if (g_strncasecmp(subject, "Re: ", 4) == 0) + return g_hash_table_lookup(subject_table, subject + 4); + else + return g_hash_table_lookup(subject_table, subject); +} + +static void subject_table_insert(GHashTable *subject_table, gchar * subject, + GtkCTreeNode * node) +{ + if (g_strncasecmp(subject, "Re: ", 4) == 0) + g_hash_table_insert(subject_table, subject + 4, node); + else + g_hash_table_insert(subject_table, subject, node); +} + static void summary_set_ctree_from_list(SummaryView *summaryview, GSList *mlist) { @@ -1398,6 +1652,7 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, GtkCTreeNode *node, *parent; gchar *text[N_SUMMARY_COLS]; GHashTable *msgid_table; + GHashTable *subject_table; GSList * cur; GtkCTreeNode *cur_parent; @@ -1409,6 +1664,8 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, msgid_table = g_hash_table_new(g_str_hash, g_str_equal); summaryview->msgid_table = msgid_table; + subject_table = g_hash_table_new(g_str_hash, g_str_equal); + summaryview->subject_table = subject_table; if (prefs_common.use_addr_book) start_address_completion(); @@ -1420,25 +1677,53 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, msginfo->threadscore = msginfo->score; } + if (global_scoring || summaryview->folder_item->prefs->scoring) { + summaryview->important_score = prefs_common.important_score; + if (summaryview->folder_item->prefs->important_score > + summaryview->important_score) + summaryview->important_score = + summaryview->folder_item->prefs->important_score; + } + /* if (prefs_common.enable_thread) { */ if (summaryview->folder_item->prefs->enable_thread) { for (; mlist != NULL; mlist = mlist->next) { msginfo = (MsgInfo *)mlist->data; parent = NULL; + summary_set_header(text, msginfo); + /* search parent node for threading */ if (msginfo->inreplyto && *msginfo->inreplyto) { parent = g_hash_table_lookup (msgid_table, msginfo->inreplyto); } - - summary_set_header(text, msginfo); + if (parent == NULL && msginfo->subject) { + parent = subject_table_lookup + (subject_table, msginfo->subject); + } + if(parent) { + parentinfo = gtk_ctree_node_get_row_data(ctree, parent); + if(parentinfo && MSG_IS_IGNORE_THREAD(parentinfo->flags)) { +/* + if (MSG_IS_NEW(msginfo->flags)) + summaryview->newmsgs--; + if (MSG_IS_UNREAD(msginfo->flags)) + summaryview->unread--; +*/ + MSG_SET_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + } + } node = gtk_ctree_insert_node (ctree, parent, NULL, text, 2, NULL, NULL, NULL, NULL, FALSE, TRUE); GTKUT_CTREE_NODE_SET_ROW_DATA(node, msginfo); + summary_set_marks_func(ctree, node, summaryview); + + if ( MSG_GET_LABEL(msginfo->flags) ) + summary_set_label_color(ctree, node, (msginfo->flags & MSG_LABEL)); /* preserve previous node if the message is duplicated */ @@ -1447,6 +1732,12 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, == NULL) g_hash_table_insert(msgid_table, msginfo->msgid, node); + if (msginfo->subject && + subject_table_lookup(subject_table, + msginfo->subject) == NULL) { + subject_table_insert(subject_table, + msginfo->subject, node); + } cur_parent = parent; cur_msginfo = msginfo; @@ -1473,6 +1764,9 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, *cur_msginfo->inreplyto) { cur_parent = g_hash_table_lookup(msgid_table, cur_msginfo->inreplyto); } + if (cur_parent == NULL && cur_msginfo->subject) { + cur_parent = subject_table_lookup(subject_table, cur_msginfo->subject); + } } } @@ -1490,11 +1784,20 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, GTKUT_CTREE_NODE_SET_ROW_DATA(node, msginfo); summary_set_marks_func(ctree, node, summaryview); + if ( MSG_GET_LABEL(msginfo->flags) ) + summary_set_label_color(ctree, node, (msginfo->flags & MSG_LABEL)); + if (msginfo->msgid && *msginfo->msgid && g_hash_table_lookup(msgid_table, msginfo->msgid) == NULL) g_hash_table_insert(msgid_table, msginfo->msgid, node); + + if (msginfo->subject && + subject_table_lookup(subject_table, + msginfo->subject) == NULL) + subject_table_insert(subject_table, + msginfo->subject, node); } } @@ -1512,9 +1815,12 @@ static void summary_set_ctree_from_list(SummaryView *summaryview, debug_print(_("done.\n")); STATUSBAR_POP(summaryview->mainwin); - if (debug_mode) + if (debug_mode) { debug_print("\tmsgid hash table size = %d\n", g_hash_table_size(msgid_table)); + debug_print("\tsubject hash table size = %d\n", + g_hash_table_size(subject_table)); + } } struct wcachefp @@ -1530,10 +1836,14 @@ gint summary_write_cache(SummaryView *summaryview) gint ver = CACHE_VERSION; gchar *buf; gchar *cachefile, *markfile; + GSList * cur; if (!summaryview->folder_item || !summaryview->folder_item->path) return -1; + if (summaryview->folder_item->folder->update_mark != NULL) + summaryview->folder_item->folder->update_mark(summaryview->folder_item->folder, summaryview->folder_item); + cachefile = folder_item_get_cache_file(summaryview->folder_item); g_return_val_if_fail(cachefile != NULL, -1); if ((fps.cache_fp = fopen(cachefile, "w")) == NULL) { @@ -1568,6 +1878,14 @@ gint summary_write_cache(SummaryView *summaryview) gtk_ctree_pre_recursive(ctree, NULL, summary_write_cache_func, &fps); + for(cur = summaryview->killed_messages ; cur != NULL ; + cur = g_slist_next(cur)) { + MsgInfo *msginfo = (MsgInfo *) cur->data; + + procmsg_write_cache(msginfo, fps.cache_fp); + procmsg_write_flags(msginfo, fps.mark_fp); + } + fclose(fps.cache_fp); fclose(fps.mark_fp); @@ -1599,7 +1917,7 @@ static void summary_set_header(gchar *text[], MsgInfo *msginfo) text[S_COL_MARK] = NULL; text[S_COL_UNREAD] = NULL; - text[S_COL_MIME] = NULL; + text[S_COL_MIME] = NULL; text[S_COL_NUMBER] = itos_buf(col_number, msginfo->msgnum); text[S_COL_SIZE] = to_human_readable(msginfo->size); #if 0 @@ -1621,14 +1939,13 @@ static void summary_set_header(gchar *text[], MsgInfo *msginfo) text[S_COL_FROM] = msginfo->fromname ? msginfo->fromname : _("(No From)"); if (prefs_common.swap_from && msginfo->from && msginfo->to && - cur_account && cur_account->address && !MSG_IS_NEWS(msginfo->flags)) { gchar *from; Xalloca(from, strlen(msginfo->from) + 1, return); strcpy(from, msginfo->from); extract_address(from); - if (!strcmp(from, cur_account->address)) { + if (account_find_mail_from_address(from)) { g_free(to); to = g_strconcat("-->", msginfo->to, NULL); text[S_COL_FROM] = to; @@ -1657,6 +1974,14 @@ static void summary_set_header(gchar *text[], MsgInfo *msginfo) _("(No Subject)"); } +#define CHANGE_FLAGS(msginfo) \ +{ \ +if (msginfo->folder->folder->change_flags != NULL) \ +msginfo->folder->folder->change_flags(msginfo->folder->folder, \ + msginfo->folder, \ + msginfo); \ +} + static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row, gboolean new_window) { @@ -1682,6 +2007,20 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row, } g_free(filename); + if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) + summaryview->newmsgs--; + if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) + summaryview->unread--; + if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { + MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD); + + CHANGE_FLAGS(msginfo); + + summary_set_row_marks(summaryview, row); + gtk_clist_thaw(GTK_CLIST(ctree)); + summary_status_show(summaryview); + } + if (new_window) { MessageView *msgview; @@ -1704,17 +2043,6 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row, gtkut_ctree_node_move_if_on_the_edge(ctree, row); } - if (MSG_IS_NEW(msginfo->flags)) - summaryview->newmsgs--; - if (MSG_IS_UNREAD(msginfo->flags)) - summaryview->unread--; - if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { - MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD); - summary_set_row_marks(summaryview, row); - gtk_clist_thaw(GTK_CLIST(ctree)); - summary_status_show(summaryview); - } - if (GTK_WIDGET_VISIBLE(summaryview->headerwin->window)) header_window_show(summaryview->headerwin, msginfo); @@ -1836,7 +2164,10 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row) gtk_ctree_node_set_foreground(ctree, row, &summaryview->color_normal); /* set new/unread column */ - if (MSG_IS_NEW(flags)) { + if (MSG_IS_IGNORE_THREAD(flags)) { + gtk_ctree_node_set_pixmap(ctree, row, S_COL_UNREAD, + ignorethreadxpm, ignorethreadxpmmask); + } else if (MSG_IS_NEW(flags)) { gtk_ctree_node_set_pixmap(ctree, row, S_COL_UNREAD, newxpm, newxpmmask); } else if (MSG_IS_UNREAD(flags)) { @@ -1869,6 +2200,15 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row) gtk_ctree_node_set_text(ctree, row, S_COL_MARK, "O"); gtk_ctree_node_set_foreground(ctree, row, &summaryview->color_marked); + } + else if ((global_scoring || + summaryview->folder_item->prefs->scoring) && + (msginfo->score >= summaryview->important_score) && + ((msginfo->flags & + (MSG_MARKED | MSG_MOVE | MSG_COPY)) == 0)) { + gtk_ctree_node_set_text(ctree, row, S_COL_MARK, "!"); + gtk_ctree_node_set_foreground(ctree, row, + &summaryview->color_important); } else { gtk_ctree_node_set_text(ctree, row, S_COL_MARK, NULL); } @@ -1901,6 +2241,9 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row) summaryview->copied--; MSG_UNSET_FLAGS(msginfo->flags, MSG_DELETED | MSG_MOVE | MSG_COPY); MSG_SET_FLAGS(msginfo->flags, MSG_MARKED); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); debug_print(_("Message %d is marked\n"), msginfo->msgnum); } @@ -1914,6 +2257,7 @@ void summary_mark(SummaryView *summaryview) summary_mark_row(summaryview, GTK_CTREE_NODE(cur->data)); /* summary_step(summaryview, GTK_SCROLL_STEP_FORWARD); */ + summary_status_show(summaryview); } static void summary_mark_row_as_read(SummaryView *summaryview, @@ -1923,15 +2267,18 @@ static void summary_mark_row_as_read(SummaryView *summaryview, MsgInfo *msginfo; msginfo = gtk_ctree_node_get_row_data(ctree, row); - if (MSG_IS_NEW(msginfo->flags)) + if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->newmsgs--; - if (MSG_IS_UNREAD(msginfo->flags)) + if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) summaryview->unread--; if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); - debug_print(_("Message %d is marked as being read\n"), + debug_print(_("Message %d is marked as read\n"), msginfo->msgnum); } } @@ -1969,6 +2316,9 @@ static void summary_mark_row_as_unread(SummaryView *summaryview, debug_print(_("Message %d is marked as unread\n"), msginfo->msgnum); } + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); } @@ -2003,6 +2353,9 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row) MSG_MOVE | MSG_COPY); MSG_SET_FLAGS(msginfo->flags, MSG_DELETED); + + CHANGE_FLAGS(msginfo); + summaryview->deleted++; if (!prefs_common.immediate_exec) @@ -2094,6 +2447,9 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row) MSG_DELETED | MSG_MOVE | MSG_COPY); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); debug_print(_("Message %s/%d is unmarked\n"), @@ -2130,6 +2486,7 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row, MSG_SET_FLAGS(msginfo->flags, MSG_MOVE); summaryview->moved++; } + if (!prefs_common.immediate_exec) summary_set_row_marks(summaryview, row); @@ -2169,7 +2526,7 @@ void summary_move_to(SummaryView *summaryview) if (!summaryview->folder_item || summaryview->folder_item->folder->type == F_NEWS) return; - to_folder = foldersel_folder_sel(NULL); + to_folder = foldersel_folder_sel(NULL, NULL); summary_move_selected_to(summaryview, to_folder); } @@ -2191,6 +2548,7 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row, MSG_SET_FLAGS(msginfo->flags, MSG_COPY); summaryview->copied++; } + if (!prefs_common.immediate_exec) summary_set_row_marks(summaryview, row); @@ -2231,7 +2589,7 @@ void summary_copy_to(SummaryView *summaryview) if (!summaryview->folder_item || summaryview->folder_item->folder->type == F_NEWS) return; - to_folder = foldersel_folder_sel(NULL); + to_folder = foldersel_folder_sel(NULL, NULL); summary_copy_selected_to(summaryview, to_folder); } @@ -2326,7 +2684,8 @@ void summary_execute(SummaryView *summaryview) gtk_clist_freeze(clist); - if (prefs_common.enable_thread) + if (summaryview->folder_item->prefs->enable_thread) + /* if (prefs_common.enable_thread) */ summary_unthread_for_exec(summaryview); summary_execute_move(summaryview); @@ -2349,7 +2708,8 @@ void summary_execute(SummaryView *summaryview) node = next; } - if (prefs_common.enable_thread) + if (summaryview->folder_item->prefs->enable_thread) + /* if (prefs_common.enable_thread) */ summary_thread_build(summaryview); summaryview->selected = clist->selection ? @@ -2463,6 +2823,7 @@ static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node, g_slist_append(summaryview->mlist, msginfo); MSG_UNSET_FLAGS(msginfo->flags, MSG_COPY); + summary_set_row_marks(summaryview, node); } } @@ -2485,6 +2846,11 @@ static void summary_execute_delete(SummaryView *summaryview) if (!summaryview->mlist) return; + for(cur = summaryview->mlist ; cur != NULL ; cur = cur->next) { + MsgInfo * msginfo = cur->data; + MSG_UNSET_FLAGS(msginfo->flags, MSG_DELETED); + } + folder_item_move_msgs_with_dest(trash, summaryview->mlist); for (cur = summaryview->mlist; cur != NULL; cur = cur->next) @@ -2515,6 +2881,13 @@ static void summary_execute_delete_func(GtkCTree *ctree, GtkCTreeNode *node, msginfo->msgid)) g_hash_table_remove(summaryview->msgid_table, msginfo->msgid); + + if (msginfo->subject && + node == subject_table_lookup(summaryview->subject_table, + msginfo->subject)) { + gchar *s = msginfo->subject + (g_strncasecmp(msginfo->subject, "Re: ", 4) == 0 ? 4 : 0); + g_hash_table_remove(summaryview->subject_table, s); + } } } @@ -2531,7 +2904,7 @@ void summary_thread_build(SummaryView *summaryview) gtk_ctree_pre_recursive_to_depth (GTK_CTREE(summaryview->ctree), NULL, 1, GTK_CTREE_FUNC(summary_thread_func), - summaryview->msgid_table); + summaryview); gtk_clist_thaw(GTK_CLIST(summaryview->ctree)); @@ -2586,14 +2959,22 @@ static void summary_thread_func(GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { MsgInfo *msginfo; - GtkCTreeNode *parent; - GHashTable *msgid_table = (GHashTable *)data; + GtkCTreeNode *parent = NULL; + + SummaryView * summaryview = (SummaryView *) data; + GHashTable *msgid_table = summaryview->msgid_table; + GHashTable *subject_table = summaryview->subject_table; msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node); - if (!msginfo || !msginfo->inreplyto) return; + if (!msginfo) return; - parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); + if(msginfo->inreplyto) { + parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); + } + if (parent == NULL && msginfo->subject) { + parent = subject_table_lookup(subject_table, msginfo->subject); + } if (parent && parent != node) { gtk_ctree_move(ctree, node, parent, NULL); @@ -2661,16 +3042,35 @@ void summary_filter(SummaryView *summaryview) gtk_clist_freeze(GTK_CLIST(summaryview->ctree)); - gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL, - GTK_CTREE_FUNC(summary_filter_func), - summaryview); + if (prefs_filtering == NULL) { + gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL, + GTK_CTREE_FUNC(summary_filter_func), + summaryview); + + gtk_clist_thaw(GTK_CLIST(summaryview->ctree)); - gtk_clist_thaw(GTK_CLIST(summaryview->ctree)); + if (prefs_common.immediate_exec) + summary_execute(summaryview); + else + summary_status_show(summaryview); + } + else { + summaryview->folder_table = g_hash_table_new(NULL, NULL); - if (prefs_common.immediate_exec) - summary_execute(summaryview); - else - summary_status_show(summaryview); + gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL, + GTK_CTREE_FUNC(summary_filter_func), + summaryview); + + gtk_clist_thaw(GTK_CLIST(summaryview->ctree)); + + folder_item_scan_foreach(summaryview->folder_table); + folderview_update_item_foreach(summaryview->folder_table); + + g_hash_table_destroy(summaryview->folder_table); + summaryview->folder_table = NULL; + + summary_show(summaryview, summaryview->folder_item, FALSE); + } debug_print(_("done.\n")); STATUSBAR_POP(summaryview->mainwin); @@ -2685,13 +3085,19 @@ static void summary_filter_func(GtkCTree *ctree, GtkCTreeNode *node, gchar *file; FolderItem *dest; - file = procmsg_get_message_file_path(msginfo); - dest = filter_get_dest_folder(prefs_common.fltlist, file); - g_free(file); + if (prefs_filtering == NULL) { + /* old filtering */ + file = procmsg_get_message_file_path(msginfo); + dest = filter_get_dest_folder(prefs_common.fltlist, file); + g_free(file); - if (dest && strcmp2(dest->path, FILTER_NOT_RECEIVE) != 0 && - summaryview->folder_item != dest) - summary_move_row_to(summaryview, node, dest); + if (dest && strcmp2(dest->path, FILTER_NOT_RECEIVE) != 0 && + summaryview->folder_item != dest) + summary_move_row_to(summaryview, node, dest); + } + else + filter_msginfo_move_or_delete(prefs_filtering, msginfo, + summaryview->folder_table); } /* callback functions */ @@ -2740,6 +3146,13 @@ void summary_pass_key_press_event(SummaryView *summaryview, GdkEventKey *event) #define BREAK_ON_MODIFIER_KEY() \ if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0) break +#define KEY_PRESS_EVENT_STOP() \ + if (gtk_signal_n_emissions_by_name \ + (GTK_OBJECT(ctree), "key_press_event") > 0) { \ + gtk_signal_emit_stop_by_name(GTK_OBJECT(ctree), \ + "key_press_event"); \ + } + static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, SummaryView *summaryview) { @@ -2753,13 +3166,8 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, case GDK_g: /* Go */ case GDK_G: BREAK_ON_MODIFIER_KEY(); - - if (gtk_signal_n_emissions_by_name - (GTK_OBJECT(ctree), "key_press_event") > 0) - gtk_signal_emit_stop_by_name(GTK_OBJECT(ctree), - "key_press_event"); - - to_folder = foldersel_folder_sel(NULL); + KEY_PRESS_EVENT_STOP(); + to_folder = foldersel_folder_sel(NULL, NULL); if (to_folder) { debug_print(_("Go to %s\n"), to_folder->path); folderview_select(summaryview->folderview, to_folder); @@ -2767,17 +3175,20 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, return; case GDK_w: /* Write new message */ BREAK_ON_MODIFIER_KEY(); - if (summaryview->folder_item) - compose_new(summaryview->folder_item->folder->account); - else + if (summaryview->folder_item) { + PrefsAccount *ac; + ac = summaryview->folder_item->folder->account; + if (ac && ac->protocol == A_NNTP) + compose_new_with_recipient + (ac, summaryview->folder_item->path); + else + compose_new(ac); + } else compose_new(NULL); return; case GDK_D: /* Empty trash */ BREAK_ON_MODIFIER_KEY(); - if (gtk_signal_n_emissions_by_name - (GTK_OBJECT(ctree), "key_press_event") > 0) - gtk_signal_emit_stop_by_name(GTK_OBJECT(ctree), - "key_press_event"); + KEY_PRESS_EVENT_STOP(); main_window_empty_trash(summaryview->mainwin, TRUE); return; case GDK_Q: /* Quit */ @@ -2799,6 +3210,7 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, gtk_widget_grab_focus(summaryview->folderview->ctree); return; default: + break; } if (!summaryview->selected) { @@ -2879,6 +3291,7 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, case GDK_x: /* Execute */ case GDK_X: BREAK_ON_MODIFIER_KEY(); + KEY_PRESS_EVENT_STOP(); summary_execute(summaryview); break; case GDK_a: /* Reply to the message */ @@ -2904,9 +3317,13 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event, summary_save_as(summaryview); break; default: + break; } } +#undef BREAK_ON_MODIFIER_KEY +#undef KEY_PRESS_EVENT_STOP + static void summary_open_row(GtkSCTree *sctree, SummaryView *summaryview) { if (summaryview->folder_item->stype == F_DRAFT) @@ -2939,6 +3356,9 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row, case S_COL_MARK: if (MSG_IS_MARKED(msginfo->flags)) { MSG_UNSET_FLAGS(msginfo->flags, MSG_MARKED); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); } else summary_mark_row(summaryview, row); @@ -2954,6 +3374,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row, } break; default: + break; } if (summaryview->display_msg) @@ -2994,6 +3415,7 @@ static void summary_col_resized(GtkCList *clist, gint column, gint width, prefs_common.summary_col_subject = width; break; default: + break; } } @@ -3001,6 +3423,7 @@ static void summary_reply_cb(SummaryView *summaryview, guint action, GtkWidget *widget) { MsgInfo *msginfo; + GList *sel = GTK_CLIST(summaryview->ctree)->selection; msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree), summaryview->selected); @@ -3017,6 +3440,21 @@ static void summary_reply_cb(SummaryView *summaryview, guint action, case COMPOSE_REPLY_WITHOUT_QUOTE: compose_reply(msginfo, FALSE, FALSE, FALSE); break; + case COMPOSE_REPLY_TO_SENDER: + compose_reply(msginfo, prefs_common.reply_with_quote, + FALSE, TRUE); + break; + case COMPOSE_FOLLOWUP_AND_REPLY_TO: + compose_followup_and_reply_to(msginfo, + prefs_common.reply_with_quote, + FALSE, TRUE); + break; + case COMPOSE_REPLY_TO_SENDER_WITH_QUOTE: + compose_reply(msginfo, TRUE, FALSE, TRUE); + break; + case COMPOSE_REPLY_TO_SENDER_WITHOUT_QUOTE: + compose_reply(msginfo, FALSE, FALSE, TRUE); + break; case COMPOSE_REPLY_TO_ALL: compose_reply(msginfo, prefs_common.reply_with_quote, TRUE, FALSE); @@ -3027,25 +3465,25 @@ static void summary_reply_cb(SummaryView *summaryview, guint action, case COMPOSE_REPLY_TO_ALL_WITHOUT_QUOTE: compose_reply(msginfo, FALSE, TRUE, FALSE); break; - case COMPOSE_REPLY_TO_AUTHOR: - compose_reply(msginfo, prefs_common.reply_with_quote, - FALSE, TRUE); - break; - case COMPOSE_REPLY_TO_AUTHOR_WITH_QUOTE: - compose_reply(msginfo, TRUE, FALSE, TRUE); - break; - case COMPOSE_REPLY_TO_AUTHOR_WITHOUT_QUOTE: - compose_reply(msginfo, FALSE, FALSE, TRUE); - break; case COMPOSE_FORWARD: - compose_forward(NULL, msginfo, FALSE); - break; + if (!sel->next) { + compose_forward(NULL, msginfo, FALSE); + break; + } + /* if (sel->next) FALL THROUGH */ case COMPOSE_FORWARD_AS_ATTACH: - compose_forward(NULL, msginfo, TRUE); + { + GSList *msginfo_list = NULL; + for ( ; sel != NULL; sel = sel->next) + msginfo_list = g_slist_append(msginfo_list, + gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree), + GTK_CTREE_NODE(sel->data))); + compose_forward_multiple(NULL, msginfo_list); + g_slist_free(msginfo_list); + } break; default: - compose_reply(msginfo, prefs_common.reply_with_quote, - FALSE, FALSE); + g_warning("summary_reply_cb(): invalid action: %d\n", action); } summary_set_marks_selected(summaryview); @@ -3066,13 +3504,15 @@ static void summary_add_sender_to_cb (SummaryView *summaryview, GtkMenuShell *menushell; GtkWidget *menu; GtkWidget *menuitem; - GList *child = menushell->children; + GList *child; gboolean found = FALSE; MsgInfo *msginfo; gchar *from_address; menushell = GTK_MENU_SHELL(summaryview->popupmenu); - g_return_if_fail(GTK_MENU_SHELL(summaryview->popupmenu)); + g_return_if_fail(menushell != NULL); + child = menushell->children; + g_return_if_fail(child); /* we're iterating each menu item searching for the one with * a "contacts" object data. if not found add the menu, @@ -3098,15 +3538,19 @@ static void summary_add_sender_to_cb (SummaryView *summaryview, /* get the address info from the summary view */ msginfo = gtk_ctree_node_get_row_data(GTK_CTREE(summaryview->ctree), summaryview->selected); - g_return_if_fail(msginfo != NULL); - - from_address = g_strdup(msginfo->from); - eliminate_address_comment(from_address); - extract_address(from_address); - log_message("adding %s %s\n", msginfo->fromname, from_address); - addressbook_add_contact_by_menu(submenu, msginfo->fromname, from_address, NULL); - g_free(from_address); - + + if (msginfo != NULL && msginfo->fromname != NULL && msginfo->from != NULL) { + gtk_widget_set_sensitive(GTK_WIDGET(submenu), TRUE); + from_address = g_strdup(msginfo->from); + eliminate_address_comment(from_address); + extract_address(from_address); + log_message("adding %s %s\n", msginfo->fromname, from_address); + addressbook_add_contact_by_menu(submenu, msginfo->fromname, from_address, NULL); + g_free(from_address); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(submenu), FALSE); + } } static void summary_num_clicked(GtkWidget *button, SummaryView *summaryview) @@ -3141,6 +3585,12 @@ static void summary_subject_clicked(GtkWidget *button, summary_sort(summaryview, SORT_BY_SUBJECT); } +static void summary_mark_clicked(GtkWidget *button, + SummaryView *summaryview) +{ + summary_sort(summaryview, SORT_BY_LABEL); +} + void summary_change_display_item(SummaryView *summaryview) { GtkCList *clist = GTK_CLIST(summaryview->ctree); @@ -3282,6 +3732,15 @@ static gint summary_cmp_by_subject(GtkCList *clist, return strcasecmp(msginfo1->subject, msginfo2->subject); } +static gint summary_cmp_by_label(GtkCList *clist, + gconstpointer ptr1, gconstpointer ptr2) +{ + MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data; + MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data; + + return MSG_GET_LABEL(msginfo1->flags) - MSG_GET_LABEL(msginfo2->flags); +} + static gint summary_cmp_by_score(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) { @@ -3297,3 +3756,66 @@ static gint summary_cmp_by_score(GtkCList *clist, else return summary_cmp_by_date(clist, ptr1, ptr2); } + +static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data) +{ + SummaryView *summaryview = (SummaryView *) data; + MsgInfo *msginfo; + + msginfo = gtk_ctree_node_get_row_data(ctree, row); + if (MSG_IS_NEW(msginfo->flags)) + summaryview->newmsgs--; + if (MSG_IS_UNREAD(msginfo->flags)) + summaryview->unread--; + MSG_SET_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + + CHANGE_FLAGS(msginfo); + + summary_set_row_marks(summaryview, row); + debug_print(_("Message %d is marked as ignore thread\n"), + msginfo->msgnum); +} + +static void summary_ignore_thread(SummaryView *summaryview) +{ + GtkCTree *ctree = GTK_CTREE(summaryview->ctree); + GList *cur; + + for (cur = GTK_CLIST(ctree)->selection; cur != NULL; cur = cur->next) { + gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), GTK_CTREE_FUNC(summary_ignore_thread_func), summaryview); + } + + summary_status_show(summaryview); +} + +static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data) +{ + SummaryView *summaryview = (SummaryView *) data; + MsgInfo *msginfo; + + msginfo = gtk_ctree_node_get_row_data(ctree, row); + if (MSG_IS_NEW(msginfo->flags)) + summaryview->newmsgs++; + if (MSG_IS_UNREAD(msginfo->flags)) + summaryview->unread++; + MSG_UNSET_FLAGS(msginfo->flags, MSG_IGNORE_THREAD); + + CHANGE_FLAGS(msginfo); + + summary_set_row_marks(summaryview, row); + debug_print(_("Message %d is marked as unignore thread\n"), + msginfo->msgnum); +} + +static void summary_unignore_thread(SummaryView *summaryview) +{ + GtkCTree *ctree = GTK_CTREE(summaryview->ctree); + GList *cur; + + for (cur = GTK_CLIST(ctree)->selection; cur != NULL; cur = cur->next) { + gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), GTK_CTREE_FUNC(summary_unignore_thread_func), summaryview); + } + + summary_status_show(summaryview); +} +