Fix crash when unmarkin a message with unread children.
[claws.git] / src / summaryview.c
index 3a335f1c08759b5d5c58dfec40834966cb33bbf1..f04c1b29a6221766fceada01ea1d6fd66d813e98 100644 (file)
@@ -85,6 +85,7 @@
 #include "news.h"
 #include "matcher.h"
 #include "matcher_parser.h"
+#include "hooks.h"
 
 #define SUMMARY_COL_MARK_WIDTH         10
 #define SUMMARY_COL_UNREAD_WIDTH       13
@@ -265,6 +266,9 @@ static void summary_key_pressed             (GtkWidget              *ctree,
 static void summary_searchbar_pressed  (GtkWidget              *ctree,
                                         GdkEventKey            *event,
                                         SummaryView            *summaryview);
+static void summary_searchbar_focus_evt        (GtkWidget              *ctree,
+                                        GdkEventFocus          *event,
+                                        SummaryView            *summaryview);
 static void summary_searchtype_changed (GtkMenuItem            *widget, 
                                         gpointer                data);
 static void summary_open_row           (GtkSCTree              *sctree,
@@ -379,7 +383,7 @@ static void news_flag_crosspost             (MsgInfo *msginfo);
 static void tog_searchbar_cb           (GtkWidget      *w,
                                         gpointer        data);
 
-static void summary_update_msg         (MsgInfo *info, gpointer data);
+static gboolean summary_update_msg     (gpointer source, gpointer data);
 
 GtkTargetEntry summary_drag_types[1] =
 {
@@ -485,7 +489,8 @@ SummaryView *summary_create(void)
        debug_print("Creating summary view...\n");
        summaryview = g_new0(SummaryView, 1);
 
-       vbox = gtk_vbox_new(FALSE, 3);
+#define SUMMARY_VBOX_SPACING 3
+       vbox = gtk_vbox_new(FALSE, SUMMARY_VBOX_SPACING);
        
        /* create status label */
        hbox = gtk_hbox_new(FALSE, 0);
@@ -570,6 +575,9 @@ SummaryView *summary_create(void)
                           summaryview);
 
        gtk_option_menu_set_menu(GTK_OPTION_MENU(search_type_opt), search_type);
+       
+       gtk_option_menu_set_history(GTK_OPTION_MENU(search_type_opt), prefs_common.summary_quicksearch_type);
+       
        gtk_widget_show(search_type);
        
        search_string = gtk_entry_new();
@@ -583,8 +591,16 @@ SummaryView *summary_create(void)
                           GTK_SIGNAL_FUNC(summary_searchbar_pressed),
                           summaryview);
 
+       gtk_signal_connect(GTK_OBJECT(search_string), "focus_in_event",
+                          GTK_SIGNAL_FUNC(summary_searchbar_focus_evt),
+                          summaryview);
+
+       gtk_signal_connect(GTK_OBJECT(search_string), "focus_out_event",
+                          GTK_SIGNAL_FUNC(summary_searchbar_focus_evt),
+                          summaryview);
+
        gtk_signal_connect (GTK_OBJECT(toggle_search), "toggled",
-                        GTK_SIGNAL_FUNC(tog_searchbar_cb), hbox_search);
+                        GTK_SIGNAL_FUNC(tog_searchbar_cb), summaryview);
 
        /* create popup menu */
        n_entries = sizeof(summary_popup_entries) /
@@ -612,7 +628,7 @@ SummaryView *summary_create(void)
        summaryview->search_type = search_type;
        summaryview->search_string = search_string;
        summaryview->msginfo_update_callback_id =
-               msginfo_update_callback_register(summary_update_msg, (gpointer) summaryview);
+               hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview);
 
        /* CLAWS: need this to get the SummaryView * from
         * the CList */
@@ -921,8 +937,17 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                gchar *searched_header = NULL;
                MatcherList * tmp_list = NULL;
                
-               if (search_type == S_SEARCH_EXTENDED)
-                       tmp_list = matcher_parser_get_cond(search_string);
+               if (search_type == S_SEARCH_EXTENDED) {
+                       char *newstr = NULL;
+
+                       newstr = expand_search_string(search_string);
+                       if (newstr) {
+                               tmp_list = matcher_parser_get_cond(newstr);
+                               g_free(newstr);
+                       }
+                       else
+                               tmp_list = NULL;
+               }
 
                not_killed = NULL;
                for (cur = mlist ; cur != NULL ; cur = g_slist_next(cur)) {
@@ -950,13 +975,12 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                else
                                        procmsg_msginfo_free(msginfo);
                        } else {
-                               if (tmp_list != NULL && matcherlist_match(tmp_list, msginfo))
+                               if ((tmp_list != NULL) && matcherlist_match(tmp_list, msginfo))
                                        not_killed = g_slist_append(not_killed, msginfo);
                                else
                                        procmsg_msginfo_free(msginfo);
                        }
                }
-
                if (search_type == S_SEARCH_EXTENDED && tmp_list != NULL) {
                        matcherlist_free(tmp_list);
                        tmp_list = NULL;
@@ -2201,7 +2225,7 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
 
        debug_print("done.\n");
        STATUSBAR_POP(summaryview->mainwin);
-       if (debug_mode) {
+       if (debug_get_mode()) {
                debug_print("\tmsgid hash table size = %d\n",
                            g_hash_table_size(msgid_table));
                debug_print("\tsubject hash table size = %d\n",
@@ -2688,18 +2712,19 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_MOVE(msginfo->flags)) {
                summaryview->moved--;
                changed = TRUE;
+               msginfo->to_folder->op_count--;
+               if (msginfo->to_folder->op_count == 0)
+                       folder_update_item(msginfo->to_folder, FALSE);
        }
        if (MSG_IS_COPY(msginfo->flags)) {
                summaryview->copied--;
                changed = TRUE;
-       }
-       changed |= summary_update_unread_children (summaryview, msginfo, TRUE);
-
-       if (changed && !prefs_common.immediate_exec) {
                msginfo->to_folder->op_count--;
                if (msginfo->to_folder->op_count == 0)
                        folder_update_item(msginfo->to_folder, FALSE);
        }
+       changed |= summary_update_unread_children (summaryview, msginfo, TRUE);
+
        msginfo->to_folder = NULL;
        procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE | MSG_COPY);
        procmsg_msginfo_set_flags(msginfo, MSG_MARKED, 0);
@@ -2916,18 +2941,19 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_MOVE(msginfo->flags)) {
                summaryview->moved--;
                changed = TRUE;
+               msginfo->to_folder->op_count--;
+               if (msginfo->to_folder->op_count == 0)
+                       folder_update_item(msginfo->to_folder, FALSE);
        }
        if (MSG_IS_COPY(msginfo->flags)) {
                summaryview->copied--;
                changed = TRUE;
-       }
-       changed |= summary_update_unread_children (summaryview, msginfo, FALSE);
-
-       if (changed && !prefs_common.immediate_exec) {
                msginfo->to_folder->op_count--;
                if (msginfo->to_folder->op_count == 0)
                        folder_update_item(msginfo->to_folder, FALSE);
        }
+       changed |= summary_update_unread_children (summaryview, msginfo, FALSE);
+
        msginfo->to_folder = NULL;
        procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, MSG_MOVE | MSG_COPY);
        procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
@@ -3078,20 +3104,25 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_DELETED(msginfo->flags))
                summaryview->deleted--;
        if (MSG_IS_MOVE(msginfo->flags)) {
+               if (!prefs_common.immediate_exec) {
+                       msginfo->to_folder->op_count--;
+                       if (msginfo->to_folder->op_count == 0)
+                               folder_update_item(msginfo->to_folder, FALSE);
+               }
                summaryview->moved--;
                changed = TRUE;
        }
        if (MSG_IS_COPY(msginfo->flags)) {
+               if (!prefs_common.immediate_exec) {
+                       msginfo->to_folder->op_count--;
+                       if (msginfo->to_folder->op_count == 0)
+                               folder_update_item(msginfo->to_folder, FALSE);
+               }
                summaryview->copied--;
                changed = TRUE;
        }
        changed |= summary_update_unread_children (summaryview, msginfo, FALSE);
 
-       if (changed && !prefs_common.immediate_exec) {
-               msginfo->to_folder->op_count--;
-               if (msginfo->to_folder->op_count == 0)
-                       folder_update_item(msginfo->to_folder, FALSE);
-       }
        msginfo->to_folder = NULL;
        procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY);
        summary_set_row_marks(summaryview, row);
@@ -4210,8 +4241,6 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        gint color_index;
 
        msginfo = gtk_ctree_node_get_row_data(ctree, node);
-       procmsg_msginfo_unset_flags(msginfo, MSG_CLABEL_FLAG_MASK, 0);
-       procmsg_msginfo_set_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0);
 
        color_index = labelcolor == 0 ? -1 : (gint)labelcolor - 1;
        ctree_style = gtk_widget_get_style(GTK_WIDGET(ctree));
@@ -4241,16 +4270,26 @@ void summary_set_colorlabel_color(GtkCTree *ctree, GtkCTreeNode *node,
        gtk_ctree_node_set_row_style(ctree, node, style);
 }
 
+static void summary_set_row_colorlable(SummaryView *summaryview, GtkCTreeNode *row, guint labelcolor)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       MsgInfo *msginfo;
+
+       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);
+}
+
 void summary_set_colorlabel(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_colorlabel_color(ctree, GTK_CTREE_NODE(cur->data),
-                                            labelcolor);
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL; cur = cur->next)
+               summary_set_row_colorlable(summaryview,
+                                          GTK_CTREE_NODE(cur->data), labelcolor);
 }
 
 static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item,
@@ -4653,21 +4692,59 @@ static void summary_searchbar_pressed(GtkWidget *widget, GdkEventKey *event,
                summary_show(summaryview, summaryview->folder_item);
 }
 
+static void summary_searchbar_focus_evt(GtkWidget *widget, GdkEventFocus *event,
+                               SummaryView *summaryview)
+{
+       if (event != NULL && event->in)
+               gtk_signal_handler_block_by_func(GTK_OBJECT(summaryview->mainwin->window), 
+                                                GTK_SIGNAL_FUNC(mainwindow_key_pressed),
+                                                summaryview->mainwin);
+       else
+               gtk_signal_handler_unblock_by_func(GTK_OBJECT(summaryview->mainwin->window), 
+                                                  GTK_SIGNAL_FUNC(mainwindow_key_pressed),
+                                                  summaryview->mainwin);
+}
+
 static void summary_searchtype_changed(GtkMenuItem *widget, gpointer data)
 {
        SummaryView *sw = (SummaryView *)data;
+       prefs_common.summary_quicksearch_type = GPOINTER_TO_INT(gtk_object_get_user_data(
+                                  GTK_OBJECT(GTK_MENU_ITEM(gtk_menu_get_active(
+                                  GTK_MENU(sw->search_type))))));
+
        if (gtk_entry_get_text(GTK_ENTRY(sw->search_string)))
                summary_show(sw, sw->folder_item);
 }
 
 static void tog_searchbar_cb(GtkWidget *w, gpointer data)
 {
+       SummaryView *summaryview = (SummaryView *)data;
+       GtkWidget *hbox= summaryview->hbox_search;
+       GtkAllocation size = hbox->allocation;
+       GtkAllocation msgview_size = summaryview->messageview->vbox->allocation;
+       GtkAllocation parent_size = summaryview->vbox->allocation;
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
                prefs_common.show_searchbar = TRUE;
-               gtk_widget_show(GTK_WIDGET(data));
+               gtk_widget_show(hbox);
+               if (!prefs_common.sep_msg && messageview_is_visible(summaryview->messageview)
+               &&  msgview_size.height > 1 && parent_size.height > 1) {
+                       gtk_widget_set_usize(GTK_WIDGET(summaryview->messageview->vbox),
+                                               -1,msgview_size.height - size.height - SUMMARY_VBOX_SPACING);
+                       gtk_widget_set_usize(GTK_WIDGET(summaryview->vbox),
+                                               -1,parent_size.height + size.height + SUMMARY_VBOX_SPACING);
+                       gtk_paned_set_position(GTK_PANED(summaryview->vbox->parent),-1);
+               }
        } else {
                prefs_common.show_searchbar = FALSE;
-               gtk_widget_hide(GTK_WIDGET(data));
+               gtk_widget_hide(hbox);
+               if (!prefs_common.sep_msg && messageview_is_visible(summaryview->messageview)
+               &&  msgview_size.height > 1 && parent_size.height > 1) {
+                       gtk_widget_set_usize(GTK_WIDGET(summaryview->messageview->vbox),
+                                               -1,msgview_size.height + size.height + SUMMARY_VBOX_SPACING);
+                       gtk_widget_set_usize(GTK_WIDGET(summaryview->vbox),
+                                               -1,parent_size.height - size.height - SUMMARY_VBOX_SPACING);
+                       gtk_paned_set_position(GTK_PANED(summaryview->vbox->parent),-1);
+               }
        }
 }
 
@@ -5398,13 +5475,20 @@ void summary_save_prefs_to_folderitem(SummaryView *summaryview, FolderItem *item
        item->threaded = summaryview->threaded;
 }
 
-static void summary_update_msg(MsgInfo *msginfo, gpointer data) {
-       GtkCTreeNode *node;
+static gboolean summary_update_msg(gpointer source, gpointer data) {
+       MsgInfoUpdate *msginfo_update = (MsgInfoUpdate *) source;
        SummaryView *summaryview = (SummaryView *)data;
-       node = gtk_ctree_find_by_row_data(GTK_CTREE(summaryview->ctree), NULL, msginfo);
+       GtkCTreeNode *node;
+
+       g_return_val_if_fail(msginfo_update != NULL, TRUE);
+       g_return_val_if_fail(summaryview != NULL, FALSE);
+
+       node = gtk_ctree_find_by_row_data(GTK_CTREE(summaryview->ctree), NULL, msginfo_update->msginfo);
        
        if (node) 
                summary_set_row_marks(summaryview, node);
+
+       return FALSE;
 }
 
 /*