2012-04-01 [colin] 3.8.0cvs36
[claws.git] / src / summaryview.c
index 7efd189d5580a510a90feb0eeae1f5a7bab2925d..f64c1cdded876cd79e617d5851d8880dc0461931 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2009 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2011 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "colorlabel.h"
 #include "inc.h"
 #include "imap.h"
-#include "addressbook.h"
+#ifndef USE_NEW_ADDRBOOK
+       #include "addressbook.h"
+#else
+       #include "addressbook-dbus.h"
+       #include "addressadd.h"
+#endif
 #include "addr_compl.h"
 #include "folder_item_prefs.h"
 #include "filtering.h"
@@ -97,6 +102,7 @@ static GdkPixbuf *newxpm;
 static GdkPixbuf *unreadxpm;
 static GdkPixbuf *repliedxpm;
 static GdkPixbuf *forwardedxpm;
+static GdkPixbuf *repliedandforwardedxpm;
 static GdkPixbuf *ignorethreadxpm;
 static GdkPixbuf *watchthreadxpm;
 static GdkPixbuf *lockedxpm;
@@ -125,6 +131,8 @@ static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                                             guint action);
 static void summary_set_hide_del_msgs_menu (SummaryView *summaryview,
                                             guint action);
+static void summary_set_hide_read_threads_menu (SummaryView *summaryview,
+                                            guint action);
 
 static GtkCMCTreeNode *summary_find_prev_msg
                                        (SummaryView            *summaryview,
@@ -512,7 +520,6 @@ SummaryView *summary_create(MainWindow *mainwin)
        GtkWidget *toggle_arrow;
        GtkWidget *toggle_search;
        QuickSearch *quicksearch;
-       CLAWS_TIP_DECL();
 
        debug_print("Creating summary view...\n");
        summaryview = g_new0(SummaryView, 1);
@@ -539,7 +546,7 @@ SummaryView *summary_create(MainWindow *mainwin)
        toggle_search = gtk_toggle_button_new();
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_search),
                                     prefs_common.show_searchbar);
-       GTK_WIDGET_UNSET_FLAGS(toggle_search, GTK_CAN_FOCUS);
+       gtkut_widget_set_can_focus(toggle_search, FALSE);
        gtk_widget_show(toggle_search);
 
        CLAWS_SET_TIP(toggle_search, _("Toggle quick search bar"));
@@ -791,8 +798,10 @@ void summary_relayout(SummaryView *summaryview)
        g_object_ref(summaryview->hbox_l);
        g_object_ref(summaryview->statlabel_msgs);
        
-       gtkut_container_remove(GTK_CONTAINER(summaryview->hbox_l->parent), summaryview->hbox_l);
-       gtkut_container_remove(GTK_CONTAINER(summaryview->statlabel_msgs->parent), summaryview->statlabel_msgs);
+       gtkut_container_remove(GTK_CONTAINER(
+               gtk_widget_get_parent(summaryview->hbox_l)), summaryview->hbox_l);
+       gtkut_container_remove(GTK_CONTAINER(
+               gtk_widget_get_parent(summaryview->statlabel_msgs)), summaryview->statlabel_msgs);
 
        switch (prefs_common.layout_mode) {
        case NORMAL_LAYOUT:
@@ -876,7 +885,7 @@ static void summary_set_fonts(SummaryView *summaryview)
        if (prefs_common.derive_from_normal_font || !SMALL_FONT) {
                font_desc = pango_font_description_new();
                size = pango_font_description_get_size
-                       (summaryview->ctree->style->font_desc);
+                       (gtk_widget_get_style(summaryview->ctree)->font_desc);
                pango_font_description_set_size(font_desc, size * PANGO_SCALE_SMALL);
        } else {
                font_desc = pango_font_description_from_string(SMALL_FONT);
@@ -928,6 +937,8 @@ void summary_init(SummaryView *summaryview)
                         &repliedxpm);
        stock_pixbuf_gdk(summaryview->ctree, STOCK_PIXMAP_FORWARDED,
                         &forwardedxpm);
+       stock_pixbuf_gdk(summaryview->ctree, STOCK_PIXMAP_REPLIED_AND_FORWARDED,
+                        &repliedandforwardedxpm);
        stock_pixbuf_gdk(summaryview->ctree, STOCK_PIXMAP_CLIP,
                         &clipxpm);
        stock_pixbuf_gdk(summaryview->ctree, STOCK_PIXMAP_LOCKED,
@@ -1128,7 +1139,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        if (!summaryview->mainwin)
                return FALSE;
        START_TIMING("");
-       summaryview->last_displayed = NULL;
        summary_switch_from_to(summaryview, item);
 
        inc_lock();
@@ -1211,6 +1221,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                item?item->no_select:FALSE);
                summary_set_hide_read_msgs_menu(summaryview, FALSE);
                summary_set_hide_del_msgs_menu(summaryview, FALSE);
+               summary_set_hide_read_threads_menu(summaryview, FALSE);
                summary_clear_all(summaryview);
                summaryview->folder_item = item;
                summary_thaw(summaryview);
@@ -1251,12 +1262,15 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                mlist = folder_item_get_msg_list(item);
        }
 
-       if ((summaryview->folder_item->hide_read_msgs || summaryview->folder_item->hide_del_msgs) &&
+       if ((summaryview->folder_item->hide_read_msgs
+             || summaryview->folder_item->hide_del_msgs
+             || summaryview->folder_item->hide_read_threads) &&
            quicksearch_is_active(summaryview->quicksearch) == FALSE) {
                GSList *not_killed;
                
                summary_set_hide_read_msgs_menu(summaryview, summaryview->folder_item->hide_read_msgs);
                summary_set_hide_del_msgs_menu(summaryview, summaryview->folder_item->hide_del_msgs);
+               summary_set_hide_read_threads_menu(summaryview, summaryview->folder_item->hide_read_threads);
                not_killed = NULL;
                for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
@@ -1291,6 +1305,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
        } else {
                summary_set_hide_read_msgs_menu(summaryview, FALSE);
                summary_set_hide_del_msgs_menu(summaryview, FALSE);
+               summary_set_hide_read_threads_menu(summaryview, FALSE);
        }
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
@@ -1372,7 +1387,6 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (is_refresh) {
                if (!quicksearch_is_in_typing(summaryview->quicksearch)) {
-                       summaryview->last_displayed = summaryview->displayed;
                        summaryview->displayed =
                                summary_find_msg_by_msgnum(summaryview,
                                                           displayed_msgnum);
@@ -1643,7 +1657,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
 
                {"Menus/SummaryViewPopup/Move"                  , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
                {"Menus/SummaryViewPopup/Copy"                  , M_TARGET_EXIST|M_EXEC},
-               {"Menus/SummaryViewPopup/Trash"         , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
+               {"Menus/SummaryViewPopup/Trash"         , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS|M_NOT_TRASH},
 #ifndef GENERIC_UMPC
                {"Menus/SummaryViewPopup/Delete"                        , M_TARGET_EXIST|M_ALLOW_DELETE},
 #endif
@@ -1701,7 +1715,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
        &&  summaryview->messageview->mimeview
        &&  summaryview->messageview->mimeview->textview)
                cm_toggle_menu_set_active_full(summaryview->mainwin->ui_manager, "Menus/SummaryViewPopup/View/AllHeaders",
-                       summaryview->messageview->mimeview->textview->show_all_headers);
+                       prefs_common.show_all_headers);
 #endif
        summary_unlock(summaryview);
 }
@@ -2033,12 +2047,6 @@ void summary_select_next_labeled(SummaryView *summaryview)
                summary_select_node(summaryview, node, TRUE, FALSE);
 }
 
-void summary_select_last_read(SummaryView *summaryview)
-{
-       if (summaryview->last_displayed)
-               summary_select_node(summaryview, summaryview->last_displayed, TRUE, FALSE);
-}
-
 void summary_select_parent(SummaryView *summaryview)
 {
        GtkCMCTreeNode *node = NULL;
@@ -2057,6 +2065,14 @@ void summary_select_by_msgnum(SummaryView *summaryview, guint msgnum)
        summary_select_node(summaryview, node, FALSE, TRUE);
 }
 
+void summary_display_by_msgnum(SummaryView *summaryview, guint msgnum)
+{
+       GtkCMCTreeNode *node;
+
+       node = summary_find_msg_by_msgnum(summaryview, msgnum);
+       summary_select_node(summaryview, node, TRUE, FALSE);
+}
+
 void summary_select_by_msg_list(SummaryView    *summaryview, GSList *msginfos)
 {
        GtkCMCTree *ctree;
@@ -2448,9 +2464,7 @@ static void summary_status_show(SummaryView *summaryview)
        goffset sel_size = 0, n_size = 0;
        MsgInfo *msginfo;
        gchar *name;
-#if GTK_CHECK_VERSION(2, 12, 0)
        gchar *tooltip;
-#endif
        
        if (!summaryview->folder_item) {
                gtk_label_set_text(GTK_LABEL(summaryview->statlabel_folder), "");
@@ -2473,6 +2487,7 @@ static void summary_status_show(SummaryView *summaryview)
        
        if (summaryview->folder_item->hide_read_msgs 
        || summaryview->folder_item->hide_del_msgs
+       || summaryview->folder_item->hide_read_threads
        || quicksearch_is_active(summaryview->quicksearch)) {
                rowlist = GTK_CMCLIST(summaryview->ctree)->row_list;
                for (cur = rowlist; cur != NULL && cur->data != NULL; cur = cur->next) {
@@ -2542,10 +2557,7 @@ static void summary_status_show(SummaryView *summaryview)
 
        if (n_selected) {
                sel = g_strdup_printf(" (%s)", to_human_readable((goffset)sel_size));
-               if (n_selected == 1)
-                       itstr = g_strdup(_(" item selected"));
-               else
-                       itstr = g_strdup(_(" items selected"));
+               itstr = g_strdup_printf(ngettext(" item selected"," items selected", n_selected));
        } else {
                sel = g_strdup("");
                itstr = g_strdup("");
@@ -2570,7 +2582,6 @@ static void summary_status_show(SummaryView *summaryview)
 
                gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
                g_free(str);
-#if GTK_CHECK_VERSION(2, 12, 0)
                tooltip = g_strdup_printf(_("<b>Message summary</b>\n"
                                            "<b>New:</b> %d\n"
                                            "<b>Unread:</b> %d\n"
@@ -2590,7 +2601,6 @@ static void summary_status_show(SummaryView *summaryview)
                gtk_widget_set_tooltip_markup(GTK_WIDGET(summaryview->statlabel_msgs),
                                            tooltip); 
                g_free(tooltip);
-#endif
        } else {
                gchar *ssize, *tsize;
                if (n_selected) {
@@ -2729,7 +2739,7 @@ static void summary_set_column_titles(SummaryView *summaryview)
 void summary_reflect_tags_changes(SummaryView *summaryview)
 {
        GtkMenuShell *menu;
-       GList *cur;
+       GList *children, *cur;
        GtkCMCTreeNode *node;
        GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
        gboolean froze = FALSE;
@@ -2740,9 +2750,11 @@ void summary_reflect_tags_changes(SummaryView *summaryview)
        cm_return_if_fail(menu != NULL);
 
        /* clear items. get item pointers. */
-       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+       children = gtk_container_get_children(GTK_CONTAINER(menu));
+       for (cur = children; cur != NULL && cur->data != NULL; cur = cur->next) {
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(cur->data), NULL);
        }
+       g_list_free(children);
        summary_tags_menu_create(summaryview, TRUE);
 
        START_LONG_OPERATION(summaryview, TRUE);
@@ -2922,6 +2934,30 @@ static void summary_find_thread_age(GNode *gnode)
        msginfo->thread_date = most_recent;
 }
 
+static gboolean summary_update_is_read(GNode *node, gpointer data)
+{
+       MsgInfo *msginfo = node->data;
+       gboolean *all_read = (gboolean *)data;
+
+       if (MSG_IS_UNREAD(msginfo->flags)) {
+               *all_read = FALSE;
+               return TRUE;
+       }
+       return FALSE;
+}      
+
+static gboolean summary_thread_is_read(GNode *gnode)
+{
+       MsgInfo *msginfo = (MsgInfo *)gnode->data;
+       gboolean all_read = TRUE;
+
+       if (!msginfo)
+               return all_read;
+
+       g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, summary_update_is_read, &all_read);
+    return all_read;
+}
+
 static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode *gnode,
                                   GtkCMCTreeNode *cnode, gpointer data)
 {
@@ -2935,7 +2971,7 @@ static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode
 
        summary_set_header(summaryview, text, msginfo);
 
-       gtk_sctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
+       gtk_cmctree_set_node_info(ctree, cnode, text[col_pos[S_COL_SUBJECT]], 2,
                                NULL, NULL, FALSE, summaryview->threaded && !summaryview->thread_collapsed);
 #define SET_TEXT(col) {                                                \
        gtk_cmctree_node_set_text(ctree, cnode, col_pos[col],   \
@@ -3015,10 +3051,14 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                
                for (gnode = root->children; gnode != NULL;
                     gnode = gnode->next) {
-                       summary_find_thread_age(gnode);
-                       node = gtk_sctree_insert_gnode
-                               (ctree, NULL, node, gnode,
-                                summary_insert_gnode_func, summaryview);
+            if (!summaryview->folder_item->hide_read_threads ||
+                    !summary_thread_is_read(gnode))
+            {
+                summary_find_thread_age(gnode);
+                node = gtk_sctree_insert_gnode
+                    (ctree, NULL, node, gnode,
+                     summary_insert_gnode_func, summaryview);
+            }
                }
 
                g_node_destroy(root);
@@ -3136,13 +3176,9 @@ static inline void summary_set_header(SummaryView *summaryview, gchar *text[],
        gchar *from_text = NULL, *to_text = NULL, *tags_text = NULL;
        gboolean should_swap = FALSE;
        gboolean vert = (prefs_common.layout_mode == VERTICAL_LAYOUT);
-#if GTK_CHECK_VERSION(2,12,0)
        static const gchar *color_dim_rgb = NULL;
        if (!color_dim_rgb)
                color_dim_rgb = gdk_color_to_string(&summaryview->color_dim);
-#else
-       static const gchar *color_dim_rgb = "#888888";
-#endif
        text[col_pos[S_COL_FROM]]   = "";
        text[col_pos[S_COL_TO]]     = "";
        text[col_pos[S_COL_SUBJECT]]= "";
@@ -3211,9 +3247,16 @@ static inline void summary_set_header(SummaryView *summaryview, gchar *text[],
        }
 
        if (!prefs_common.use_addr_book) {
-               from_text = msginfo->fromname ? 
-                               msginfo->fromname :
-                               _("(No From)");
+               if (prefs_common.summary_from_show == SHOW_NAME)
+                       from_text = msginfo->fromname;
+               else if (prefs_common.summary_from_show == SHOW_BOTH)
+                       from_text = msginfo->from;
+               else {
+                       from_text = msginfo->from;
+                       extract_address(from_text);
+               }
+               if (!from_text)
+                       _("(No From)");         
        } else {
                gchar *tmp = summary_complete_address(msginfo->from);
                if (tmp) {
@@ -3221,9 +3264,16 @@ static inline void summary_set_header(SummaryView *summaryview, gchar *text[],
                        g_free(tmp);
                        from_text = buf;
                } else {
-                       from_text = (msginfo->fromname) ?
-                                       msginfo->fromname: 
-                                       _("(No From)");
+                       if (prefs_common.summary_from_show == SHOW_NAME)
+                               from_text = msginfo->fromname;
+                       else if (prefs_common.summary_from_show == SHOW_BOTH)
+                               from_text = msginfo->from;
+                       else {
+                               from_text = msginfo->from;
+                               extract_address(from_text);
+                       }
+                       if (!from_text)
+                               _("(No From)");         
                }
        }
        
@@ -3420,7 +3470,8 @@ static void summary_display_msg_full(SummaryView *summaryview,
        gint val;
        START_TIMING("");
        if (!new_window) {
-               if (summaryview->displayed == row)
+               if (summaryview->displayed == row &&
+                   messageview_is_visible(summaryview->messageview))
                        return;
                else if (summaryview->messageview)
                        summaryview->messageview->filtered = FALSE;
@@ -3456,23 +3507,22 @@ static void summary_display_msg_full(SummaryView *summaryview,
                        else
                                gtkut_window_popup(summaryview->ext_messageview->window);
                        msgview = summaryview->ext_messageview;
-                       summaryview->last_displayed = summaryview->displayed;
                        summaryview->displayed = row;
                        val = messageview_show(msgview, msginfo, all_headers);
-                       if (GTK_CMCLIST(msgview->mimeview->ctree)->row_list == NULL)
+                       if (mimeview_tree_is_empty(msgview->mimeview))
                                gtk_widget_grab_focus(summaryview->ctree);
                        gtkut_ctree_node_move_if_on_the_edge(ctree, row,
                                GTK_CMCLIST(summaryview->ctree)->focus_row);
                } else {
                        msgview = summaryview->messageview;
-                       summaryview->last_displayed = summaryview->displayed;
                        summaryview->displayed = row;
-                       if (!messageview_is_visible(msgview)) {
+                       if (!messageview_is_visible(msgview) &&
+                           gtk_window_is_active(GTK_WINDOW(summaryview->mainwin->window))) {
                                main_window_toggle_message_view(summaryview->mainwin);
                                GTK_EVENTS_FLUSH();
                        }
                        val = messageview_show(msgview, msginfo, all_headers);
-                       if (GTK_CMCLIST(msgview->mimeview->ctree)->row_list == NULL)
+                       if (mimeview_tree_is_empty(msgview->mimeview))
                                gtk_widget_grab_focus(summaryview->ctree);
                        gtkut_ctree_node_move_if_on_the_edge(ctree, row,
                                GTK_CMCLIST(summaryview->ctree)->focus_row);
@@ -3629,6 +3679,8 @@ void summary_toggle_view(SummaryView *summaryview)
 {
        if (prefs_common.layout_mode == SMALL_LAYOUT)
                return;
+       if (summary_is_locked(summaryview))
+               return;
        if (!messageview_is_visible(summaryview->messageview) &&
            summaryview->selected && summary_is_list(summaryview))
                summary_display_msg(summaryview,
@@ -3707,6 +3759,9 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCMCTreeNode *row)
        } else if (MSG_IS_UNREAD(flags)) {
                gtk_cmctree_node_set_pixbuf(ctree, row, col_pos[S_COL_STATUS],
                                          unreadxpm);
+       } else if (MSG_IS_REPLIED(flags) && MSG_IS_FORWARDED(flags)) {
+               gtk_cmctree_node_set_pixbuf(ctree, row, col_pos[S_COL_STATUS],
+                                         repliedandforwardedxpm);
        } else if (MSG_IS_REPLIED(flags)) {
                gtk_cmctree_node_set_pixbuf(ctree, row, col_pos[S_COL_STATUS],
                                          repliedxpm);
@@ -3742,13 +3797,24 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCMCTreeNode *row)
        } else if (MSG_IS_MOVE(flags)) {
                gtk_cmctree_node_set_pixbuf(ctree, row, col_pos[S_COL_MARK],
                                          movedxpm);
-               if (style)
-                       style = bold_marked_style;
-               else {
-                       style = small_marked_style;
-               }
+               if (!msginfo->to_folder ||
+                   !folder_has_parent_of_type(msginfo->to_folder, F_TRASH)) {
+                       if (style)
+                               style = bold_marked_style;
+                       else {
+                               style = small_marked_style;
+                       }
                        gtk_cmctree_node_set_foreground
                                (ctree, row, &summaryview->color_marked);
+               } else {
+                       if (style)
+                               style = bold_deleted_style;
+                       else {
+                               style = small_deleted_style;
+                       }
+                               gtk_cmctree_node_set_foreground
+                                       (ctree, row, &summaryview->color_dim);
+               }
        } else if (MSG_IS_COPY(flags)) {
                gtk_cmctree_node_set_pixbuf(ctree, row, col_pos[S_COL_MARK],
                                          copiedxpm);
@@ -4565,8 +4631,13 @@ void summary_add_address(SummaryView *summaryview)
        if (image)
                picture = gtk_image_get_pixbuf(GTK_IMAGE(image));
 
+#ifndef USE_NEW_ADDRBOOK
        addressbook_add_contact(msginfo->fromname, from, NULL, picture);
-
+#else
+       if (addressadd_selection(msginfo->fromname, from, NULL, picture)) {
+               debug_print( "addressbook_add_contact - added\n" );
+       }
+#endif
        if (image)
                gtk_widget_destroy(image);
 }
@@ -5766,7 +5837,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
        GtkMenuShell *menu;
        GtkCheckMenuItem **items;
        gint n;
-       GList *cur, *sel;
+       GList *children, *cur, *sel;
 
        summaryview = (SummaryView *)data;
        cm_return_if_fail(summaryview != NULL);
@@ -5786,7 +5857,8 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                          GINT_TO_POINTER(1));
 
        /* clear items. get item pointers. */
-       for (n = 0, cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+       children = gtk_container_get_children(GTK_CONTAINER(menu));
+       for (n = 0, cur = children; cur != NULL && cur->data != NULL; cur = cur->next) {
                if (GTK_IS_CHECK_MENU_ITEM(cur->data)) {
                        gtk_check_menu_item_set_active
                                (GTK_CHECK_MENU_ITEM(cur->data), FALSE);
@@ -5795,6 +5867,8 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                }
        }
 
+       g_list_free(children);
+
        if (n == (N_COLOR_LABELS + 1)) {
                /* iterate all messages and set the state of the appropriate
                 * items */
@@ -5807,7 +5881,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                                 GTK_CMCTREE_NODE(sel->data));
                        if (msginfo) {
                                clabel = MSG_GET_COLORLABEL_VALUE(msginfo->flags);
-                               if (!items[clabel]->active)
+                               if (!gtk_check_menu_item_get_active(items[clabel]))
                                        gtk_check_menu_item_set_active
                                                (items[clabel], TRUE);
                        }
@@ -5890,7 +5964,7 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                                                          gpointer data)
 {
        GtkMenuShell *menu;
-       GList *cur;
+       GList *children, *cur;
        GList *sel;
        GHashTable *menu_table = g_hash_table_new_full(
                                        g_direct_hash,
@@ -5916,7 +5990,8 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                          GINT_TO_POINTER(1));
 
        /* clear items. get item pointers. */
-       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+       children = gtk_container_get_children(GTK_CONTAINER(menu));
+       for (cur = children; cur != NULL && cur->data != NULL; cur = cur->next) {
                if (GTK_IS_CHECK_MENU_ITEM(cur->data)) {
                        gint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cur->data),
                                "tag_id"));
@@ -5928,6 +6003,8 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                }
        }
 
+       g_list_free(children);
+
        /* iterate all messages and set the state of the appropriate
         * items */
        sel_len = 0;
@@ -5949,7 +6026,7 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                                gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, tags->data));
                                id = GPOINTER_TO_INT(tags->data);
                                item = g_hash_table_lookup(menu_table, GINT_TO_POINTER(tags->data));
-                               if (item && !item->active) {
+                               if (item && !gtk_check_menu_item_get_active(item)) {
                                        gtk_check_menu_item_set_active
                                                (item, TRUE);
                                }
@@ -5959,7 +6036,8 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                }
        }
 
-       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+       children = gtk_container_get_children(GTK_CONTAINER(menu));
+       for (cur = children; cur != NULL && cur->data != NULL; cur = cur->next) {
                if (GTK_IS_CHECK_MENU_ITEM(cur->data)) {
                        gint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cur->data),
                                "tag_id"));
@@ -5970,6 +6048,7 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                                gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
                }
        }
+       g_list_free(children);
        g_hash_table_destroy(menu_table);
        g_hash_table_destroy(menu_allsel_table);
        /* reset "dont_toggle" state */
@@ -6099,7 +6178,7 @@ static gboolean summary_popup_menu(GtkWidget *widget, gpointer data)
        return TRUE;
 }
 
-#if GTK_CHECK_VERSION(2,12,0) && !GENERIC_UMPC
+#if !GENERIC_UMPC
 static gchar *summaryview_get_tooltip_text(SummaryView *summaryview, MsgInfo *info, gint column)
 {
        MsgFlags flags;
@@ -6120,6 +6199,8 @@ static gchar *summaryview_get_tooltip_text(SummaryView *summaryview, MsgInfo *in
                                return _("New");
                        } else if (MSG_IS_UNREAD(flags)) {
                                return _("Unread");
+                       } else if (MSG_IS_REPLIED(flags) && MSG_IS_FORWARDED(flags)) {
+                               return _("Replied but also forwarded - click to see reply");
                        } else if (MSG_IS_REPLIED(flags)) {
                                return _("Replied - click to see reply");
                        } else if (MSG_IS_FORWARDED(flags)) {
@@ -6304,15 +6385,9 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        gtk_cmclist_set_column_width(GTK_CMCLIST(ctree), col_pos[S_COL_TAGS],
                                   prefs_common.summary_col_size[S_COL_TAGS]);
 
-       if (prefs_common.enable_dotted_lines) {
-               gtk_cmctree_set_line_style(GTK_CMCTREE(ctree), GTK_CMCTREE_LINES_DOTTED);
-               gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree),
-                                    GTK_CMCTREE_EXPANDER_SQUARE);
-       } else {
-               gtk_cmctree_set_line_style(GTK_CMCTREE(ctree), GTK_CMCTREE_LINES_NONE);
-               gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree),
-                                    GTK_CMCTREE_EXPANDER_TRIANGLE);
-       }
+       gtk_cmctree_set_line_style(GTK_CMCTREE(ctree), GTK_CMCTREE_LINES_NONE);
+       gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree),
+                            GTK_CMCTREE_EXPANDER_TRIANGLE);
 
        gtk_sctree_set_stripes(GTK_SCTREE(ctree), prefs_common.use_stripes_in_summaries);
 
@@ -6320,8 +6395,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
-               GTK_WIDGET_UNSET_FLAGS(GTK_CMCLIST(ctree)->column[pos].button,
-                                      GTK_CAN_FOCUS);
+               gtkut_widget_set_can_focus(GTK_CMCLIST(ctree)->column[pos].button,
+                                      FALSE);
                if (((pos == summaryview->col_pos[S_COL_FROM] && !FOLDER_SHOWS_TO_HDR(summaryview->folder_item)) ||
                     (pos == summaryview->col_pos[S_COL_TO] && FOLDER_SHOWS_TO_HDR(summaryview->folder_item)) ||
                     pos == summaryview->col_pos[S_COL_DATE]) && vert &&
@@ -6413,7 +6488,7 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                         G_CALLBACK(summary_drag_motion_cb),
                         summaryview);
 
-#if GTK_CHECK_VERSION(2,12,0) && !GENERIC_UMPC
+#if !GENERIC_UMPC
        g_object_set (G_OBJECT(ctree), "has-tooltip", TRUE, NULL);
        g_signal_connect(G_OBJECT(ctree), "query-tooltip", 
                         G_CALLBACK(tooltip_cb),
@@ -6451,7 +6526,6 @@ void summary_set_column_order(SummaryView *summaryview)
 
        summaryview->selected = summary_find_msg_by_msgnum(summaryview, selected_msgnum);
        summaryview->displayed = summary_find_msg_by_msgnum(summaryview, displayed_msgnum);
-       summaryview->last_displayed = summaryview->displayed;
        if (!summaryview->displayed)
                messageview_clear(summaryview->messageview);
        else
@@ -6499,11 +6573,8 @@ static gboolean summary_button_pressed(GtkWidget *ctree, GdkEventButton *event,
        if (!event) return FALSE;
 
        if (event->button == 3) {
-               summaryview->display_msg = messageview_is_visible(summaryview->messageview);
                /* right clicked */
                summary_set_menu_sensitive(summaryview);
-               cm_menu_set_sensitive_full(summaryview->mainwin->ui_manager, "Menus/SummaryViewPopup/Trash", 
-                       !folder_has_parent_of_type(summaryview->folder_item, F_TRASH) && summaryview->selected);
                gtk_menu_popup(GTK_MENU(summaryview->popupmenu), NULL, NULL,
                               NULL, NULL, event->button, event->time);
        } else if (event->button == 2) {
@@ -6561,7 +6632,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        if (summaryview->selected) {
                gboolean handled = FALSE;
                switch (event->keyval) {
-               case GDK_space:         /* Page down or go to the next */
+               case GDK_KEY_space:             /* Page down or go to the next */
                        handled = TRUE;
                        if (event->state & GDK_CONTROL_MASK) {
                                handled = FALSE;
@@ -6584,12 +6655,12 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                                }                               
                        }
                        break;
-               case GDK_BackSpace:     /* Page up */
+               case GDK_KEY_BackSpace: /* Page up */
                        handled = TRUE;
                        mimeview_scroll_page(messageview->mimeview, TRUE);
                        break;
-               case GDK_Return:        /* Scroll up/down one line */
-               case GDK_KP_Enter:
+               case GDK_KEY_Return:    /* Scroll up/down one line */
+               case GDK_KEY_KP_Enter:
                        handled = TRUE;
                        if (summaryview->displayed != summaryview->selected) {
 #ifndef GENERIC_UMPC
@@ -6611,21 +6682,21 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                return TRUE;
 
        switch (event->keyval) {
-       case GDK_Left:          /* Move focus */
+       case GDK_KEY_Left:              /* Move focus */
                adj = gtk_scrolled_window_get_hadjustment
                        (GTK_SCROLLED_WINDOW(summaryview->scrolledwin));
-               if (adj->lower != adj->value)
+               if (gtk_adjustment_get_lower(adj) != gtk_adjustment_get_value(adj))
                        break;
                /* FALLTHROUGH */       
-       case GDK_Escape:
+       case GDK_KEY_Escape:
                gtk_widget_grab_focus(summaryview->folderview->ctree);
                mainwindow_exit_folder(summaryview->mainwin);
                return TRUE;
-       case GDK_Home:
-       case GDK_End:
+       case GDK_KEY_Home:
+       case GDK_KEY_End:
                if ((node = summaryview->selected) != NULL) {
                        GtkCMCTreeNode *next = NULL;
-                       next = (event->keyval == GDK_Home)
+                       next = (event->keyval == GDK_KEY_Home)
                                        ? gtk_cmctree_node_nth(ctree, 0)
                                        : gtk_cmctree_node_nth(ctree, 
                                                g_list_length(GTK_CMCLIST(ctree)->row_list)-1);
@@ -6653,16 +6724,17 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        }
 
        switch (event->keyval) {
-       case GDK_Delete:
+       case GDK_KEY_Delete:
                BREAK_ON_MODIFIER_KEY();
                summary_delete_trash(summaryview);
                break;
-       case GDK_y:
-       case GDK_t:
-       case GDK_l:
-       case GDK_o:
-       case GDK_c:
-       case GDK_a:
+       case GDK_KEY_y:
+       case GDK_KEY_t:
+       case GDK_KEY_l:
+       case GDK_KEY_o:
+       case GDK_KEY_c:
+       case GDK_KEY_a:
+       case GDK_KEY_z:
                if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
                        g_signal_stop_emission_by_name(G_OBJECT(widget), 
                                        "key_press_event");
@@ -6755,6 +6827,8 @@ static void summary_unselected(GtkCMCTree *ctree, GtkCMCTreeNode *row,
 static void summary_selected(GtkCMCTree *ctree, GtkCMCTreeNode *row,
                             gint column, SummaryView *summaryview)
 {
+       GList *list, *cur;
+       MessageView *msgview;
        MsgInfo *msginfo;
        gboolean marked_unread = FALSE;
 
@@ -6846,6 +6920,17 @@ static void summary_selected(GtkCMCTree *ctree, GtkCMCTreeNode *row,
                break;
        }
 
+       list = messageview_get_msgview_list();
+       for (cur = list; cur != NULL; cur = cur->next) {
+               msgview = (MessageView *) cur->data;
+               
+               if (msgview->new_window && msgview->update_needed) {
+                       MsgInfo *new_msginfo = summary_get_selected_msg(summaryview);
+                       messageview_show(msgview, new_msginfo, msgview->all_headers);
+                       msgview->update_needed = FALSE;         
+               }
+       }
+
        if (summaryview->display_msg ||
            (prefs_common.always_show_msg &&
             messageview_is_visible(summaryview->messageview))) {
@@ -7016,7 +7101,7 @@ static void summary_start_drag(GtkWidget *widget, gint button, GdkEvent *event,
                                 GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT, button, event);
        gtk_drag_set_icon_default(context);
        if (prefs_common.layout_mode == SMALL_LAYOUT) {
-               GtkWidget *paned = GTK_WIDGET_PTR(summaryview)->parent;
+               GtkWidget *paned = gtk_widget_get_parent(GTK_WIDGET_PTR(summaryview));
                if (paned && GTK_IS_PANED(paned)) {
                        mainwindow_reset_paned(GTK_PANED(paned));
                }
@@ -7093,14 +7178,14 @@ static void summary_drag_data_get(GtkWidget        *widget,
 
                if (mail_list != NULL) {
                        gtk_selection_data_set(selection_data,
-                                              selection_data->target, 8,
+                                              gtk_selection_data_get_target(selection_data), 8,
                                               mail_list, strlen(mail_list));
                        g_free(mail_list);
                } 
        } else if (info == TARGET_DUMMY) {
                if (GTK_CMCLIST(summaryview->ctree)->selection)
                        gtk_selection_data_set(selection_data,
-                                              selection_data->target, 8,
+                                              gtk_selection_data_get_target(selection_data), 8,
                                               "Dummy-Summaryview", 
                                               strlen("Dummy-Summaryview")+1);
        } else if (info == TARGET_MAIL_CM_PATH_LIST) {
@@ -7132,7 +7217,7 @@ static void summary_drag_data_get(GtkWidget        *widget,
 
                if (path_list != NULL) {
                        gtk_selection_data_set(selection_data,
-                                              selection_data->target, 8,
+                                              gtk_selection_data_get_target(selection_data), 8,
                                               path_list, strlen(path_list));
                        g_free(path_list);
                }
@@ -7182,7 +7267,8 @@ static void summary_drag_data_received(GtkWidget        *widget,
                        gtk_drag_finish(drag_context, FALSE, FALSE, time);                      
                        return;
                } else {
-                       folderview_finish_dnd(data->data, drag_context, time, item);
+                       folderview_finish_dnd(gtk_selection_data_get_data(data),
+                               drag_context, time, item);
                }
        }
 }
@@ -7639,6 +7725,21 @@ void summary_toggle_show_del_messages(SummaryView *summaryview)
        summary_show(summaryview, summaryview->folder_item);
 }
  
+void summary_toggle_show_read_threads(SummaryView *summaryview)
+{
+       FolderItemUpdateData source;
+       if (summaryview->folder_item->hide_read_threads)
+               summaryview->folder_item->hide_read_threads = 0;
+       else
+               summaryview->folder_item->hide_read_threads = 1;
+
+       source.item = summaryview->folder_item;
+       source.update_flags = F_ITEM_UPDATE_NAME;
+       source.msg = NULL;
+       hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source);
+       summary_show(summaryview, summaryview->folder_item);
+}
 static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                                             guint action)
 {
@@ -7652,6 +7753,19 @@ static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                          GINT_TO_POINTER(0));
 }
 
+static void summary_set_hide_read_threads_menu (SummaryView *summaryview,
+                                            guint action)
+{
+       GtkWidget *widget;
+
+       widget = gtk_ui_manager_get_widget(summaryview->mainwin->ui_manager, "/Menu/View/HideReadThreads");
+       g_object_set_data(G_OBJECT(widget), "dont_toggle",
+                         GINT_TO_POINTER(1));
+       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(widget), action);
+       g_object_set_data(G_OBJECT(widget), "dont_toggle",
+                         GINT_TO_POINTER(0));
+}
+
 static void summary_set_hide_del_msgs_menu (SummaryView *summaryview,
                                             guint action)
 {
@@ -7676,6 +7790,7 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_UNREAD, &unreadxpm);
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_REPLIED, &repliedxpm);
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_FORWARDED, &forwardedxpm);
+       stock_pixbuf_gdk(ctree, STOCK_PIXMAP_REPLIED_AND_FORWARDED, &repliedandforwardedxpm);
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_CLIP, &clipxpm);
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_LOCKED, &lockedxpm);
        stock_pixbuf_gdk(ctree, STOCK_PIXMAP_IGNORETHREAD, &ignorethreadxpm);
@@ -7715,20 +7830,22 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
 void summary_reflect_prefs_custom_colors(SummaryView *summaryview)
 {
        GtkMenuShell *menu;
-       GList *cur;
+       GList *children, *cur;
 
        /* re-create colorlabel submenu */
        menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
        cm_return_if_fail(menu != NULL);
 
        /* clear items. get item pointers. */
-       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+       children = gtk_container_get_children(GTK_CONTAINER(menu));
+       for (cur = children; cur != NULL && cur->data != NULL; cur = cur->next) {
                g_signal_handlers_disconnect_matched
                         (gtk_ui_manager_get_accel_group(summaryview->mainwin->ui_manager), 
                         G_SIGNAL_MATCH_DATA|G_SIGNAL_MATCH_FUNC,
                         0, 0, NULL, mainwin_accel_changed_cb, cur->data);
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(cur->data), NULL);
        }
+       g_list_free(children);
        summary_colorlabel_menu_create(summaryview, TRUE);
 }
 
@@ -7749,7 +7866,9 @@ void summary_harvest_address(SummaryView *summaryview)
                        continue;
                msgList = g_list_append( msgList, GUINT_TO_POINTER( msginfo->msgnum ) );
        }
+
        addressbook_harvest( summaryview->folder_item, TRUE, msgList );
+
        g_list_free( msgList );
 }
 
@@ -7907,9 +8026,11 @@ static gboolean summary_update_folder_hook(gpointer source, gpointer data)
        FolderUpdateData *hookdata;
        SummaryView *summaryview = (SummaryView *)data;
        hookdata = source;
-       if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM)
+       if (hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM) {
                summary_update_unread(summaryview, hookdata->item);
-       else
+               quicksearch_folder_item_invalidate(summaryview->quicksearch,
+                                                  hookdata->item);
+       } else
                summary_update_unread(summaryview, NULL);
 
        return FALSE;