catch an inadvertent (as in *probably* at the wrong time) saving back of summary...
[claws.git] / src / summaryview.c
index c73f331be379cfd39cf3ed1a513172d5df7a4c09..2259fff03e20a24e838863925199954a118538b6 100644 (file)
@@ -46,6 +46,7 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <regex.h>
 
 #include "intl.h"
 #include "main.h"
@@ -65,6 +66,7 @@
 #include "compose.h"
 #include "utils.h"
 #include "gtkutils.h"
+#include "stock_pixmap.h"
 #include "filesel.h"
 #include "manage_window.h"
 #include "alertpanel.h"
 #include "folder.h"
 #include "colorlabel.h"
 #include "inc.h"
+#include "imap.h"
 #include "addressbook.h"
 #include "addr_compl.h"
 #include "scoring.h"
 #include "prefs_folder_item.h"
 #include "filtering.h"
-
-#include "pixmaps/dir-open.xpm"
-#include "pixmaps/mark.xpm"
-#include "pixmaps/deleted.xpm"
-#include "pixmaps/new.xpm"
-#include "pixmaps/unread.xpm"
-#include "pixmaps/replied.xpm"
-#include "pixmaps/forwarded.xpm"
-#include "pixmaps/clip.xpm"
-#include "pixmaps/ignorethread.xpm"
-#include "pixmaps/locked.xpm"
+#include "string_match.h"
 
 #define STATUSBAR_PUSH(mainwin, str) \
 { \
@@ -119,9 +112,6 @@ static GtkStyle *small_style;
 static GtkStyle *small_marked_style;
 static GtkStyle *small_deleted_style;
 
-static GdkPixmap *folderxpm;
-static GdkBitmap *folderxpmmask;
-
 static GdkPixmap *markxpm;
 static GdkBitmap *markxpmmask;
 static GdkPixmap *deletedxpm;
@@ -155,6 +145,9 @@ static void summary_write_cache_func        (GtkCTree               *ctree,
 
 static void summary_set_menu_sensitive (SummaryView            *summaryview);
 
+static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
+                                            guint action);
+
 static guint summary_get_msgnum                (SummaryView            *summaryview,
                                         GtkCTreeNode           *node);
 
@@ -250,6 +243,9 @@ static void summary_unthread_for_exec_func  (GtkCTree       *ctree,
                                                 GtkCTreeNode   *node,
                                                 gpointer        data);
 
+void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
+                             GSList * mlist);
+
 void summary_processing(SummaryView *summaryview, GSList * mlist);
 static void summary_filter_func                (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
@@ -389,8 +385,6 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {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_("/_Forward"),               NULL, summary_reply_cb, COMPOSE_FORWARD, NULL},
-       {N_("/Forward as a_ttachment"),
-                                       NULL, summary_reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL},
        {N_("/Bounce"),                 NULL, summary_reply_cb, COMPOSE_BOUNCE, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/Re-_edit"),               NULL, summary_reedit,   0, NULL},
@@ -532,21 +526,24 @@ void summary_init(SummaryView *summaryview)
        GtkStyle *style;
        GtkWidget *pixmap;
 
-       PIXMAP_CREATE(summaryview->ctree, markxpm, markxpmmask, mark_xpm);
-       PIXMAP_CREATE(summaryview->ctree, deletedxpm, deletedxpmmask,
-                     deleted_xpm);
-       PIXMAP_CREATE(summaryview->ctree, newxpm, newxpmmask, new_xpm);
-       PIXMAP_CREATE(summaryview->ctree, unreadxpm, unreadxpmmask, unread_xpm);
-       PIXMAP_CREATE(summaryview->ctree, repliedxpm, repliedxpmmask,
-                     replied_xpm);
-       PIXMAP_CREATE(summaryview->ctree, forwardedxpm, forwardedxpmmask,
-                     forwarded_xpm);
-       PIXMAP_CREATE(summaryview->ctree, ignorethreadxpm, ignorethreadxpmmask,
-                     ignorethread_xpm);
-       PIXMAP_CREATE(summaryview->ctree, lockedxpm, lockedxpmmask, locked_xpm);                      
-       PIXMAP_CREATE(summaryview->ctree, clipxpm, clipxpmmask, clip_xpm);
-       PIXMAP_CREATE(summaryview->hbox, folderxpm, folderxpmmask,
-                     dir_open_xpm);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_MARK,
+                        &markxpm, &markxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_DELETED,
+                        &deletedxpm, &deletedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_NEW,
+                        &newxpm, &newxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_UNREAD,
+                        &unreadxpm, &unreadxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_REPLIED,
+                        &repliedxpm, &repliedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_FORWARDED,
+                        &forwardedxpm, &forwardedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_CLIP,
+                        &clipxpm, &clipxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_LOCKED,
+                        &lockedxpm, &lockedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_IGNORETHREAD,
+                        &ignorethreadxpm, &ignorethreadxpmmask);
 
        if (!small_style) {
                small_style = gtk_style_copy
@@ -582,7 +579,7 @@ void summary_init(SummaryView *summaryview)
        gtk_widget_set_style(summaryview->statlabel_select, style);
        gtk_widget_set_style(summaryview->statlabel_msgs, style);
 
-       pixmap = gtk_pixmap_new(folderxpm, folderxpmmask);
+       pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_DIR_OPEN);
        gtk_box_pack_start(GTK_BOX(summaryview->hbox), pixmap, FALSE, FALSE, 4);
        gtk_box_reorder_child(GTK_BOX(summaryview->hbox), pixmap, 0);
        gtk_widget_show(pixmap);
@@ -707,9 +704,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
                        return FALSE;
                }
                folder_update_op_count();
-       }
-        
-       summary_write_cache(summaryview);
+       } else
+               summary_write_cache(summaryview);
         
        summaryview->folderview->opened = selected_node;
 
@@ -728,6 +724,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
              change_dir(buf) < 0))) {
                g_free(buf);
                debug_print(_("empty folder\n\n"));
+               summary_set_hide_read_msgs_menu(summaryview, FALSE);
                if (is_refresh)
                        messageview_clear(summaryview->messageview);
                summary_clear_all(summaryview);
@@ -766,6 +763,31 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
        }
 
        summaryview->killed_messages = NULL;
+
+       if (summaryview->folder_item->hide_read_msgs) {
+               GSList *not_killed;
+               gint kill_score;
+               
+               summary_set_hide_read_msgs_menu(summaryview, TRUE);
+               not_killed = NULL;
+               for(cur = mlist ; cur != NULL ; cur = g_slist_next(cur)) {
+                       MsgInfo * msginfo = (MsgInfo *) cur->data;
+                       
+                       if ((MSG_IS_UNREAD(msginfo->flags)
+                            || MSG_IS_MARKED(msginfo->flags)
+                            || MSG_IS_LOCKED(msginfo->flags))
+                            && !MSG_IS_IGNORE_THREAD(msginfo->flags))
+                           not_killed = g_slist_append(not_killed, msginfo);
+                       else
+                               summaryview->killed_messages = 
+                                       g_slist_append(summaryview->killed_messages, msginfo);
+               }
+               g_slist_free(mlist);
+               mlist = not_killed;
+       } else {
+               summary_set_hide_read_msgs_menu(summaryview, FALSE);
+       }
+
        if ((global_scoring || item->prefs->scoring) &&
            (item->folder->type == F_NEWS)) {
                GSList *not_killed;
@@ -789,6 +811,14 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
                mlist = not_killed;
        }
 
+       if (item->prefs->enable_simplify_subject
+           && item->prefs->simplify_subject_regexp != NULL
+           && strlen(item->prefs->simplify_subject_regexp) != 0) {
+               summary_simplify_subject(summaryview, 
+                                        item->prefs->simplify_subject_regexp,
+                                        mlist);
+       }
+
        STATUSBAR_POP(summaryview->mainwin);
 
        /* set ctree and hash table from the msginfo list
@@ -1012,7 +1042,6 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
        menu_set_sensitive(ifactory, "/Reply to sender",          sens);
        menu_set_sensitive(ifactory, "/Reply to all",             sens);
        menu_set_sensitive(ifactory, "/Forward",                  TRUE);
-       menu_set_sensitive(ifactory, "/Forward as attachment",    TRUE);
        menu_set_sensitive(ifactory, "/Bounce",                   TRUE);
 
        menu_set_sensitive(ifactory, "/Add sender to address book", sens);
@@ -1624,6 +1653,7 @@ static void summary_status_show(SummaryView *summaryview)
        gchar *del, *mv, *cp;
        gchar *sel;
        gchar *spc;
+       gchar *itstr;
        GList *rowlist, *cur;
        guint n_selected = 0;
        off_t sel_size = 0;
@@ -1674,19 +1704,26 @@ static void summary_status_show(SummaryView *summaryview)
        else
                spc = "";
 
-       if (n_selected)
+       if (n_selected) {
                sel = g_strdup_printf(" (%s)", to_human_readable(sel_size));
-       else
+               if (n_selected == 1)
+                       itstr = g_strdup(_(" item selected"));
+               else
+                       itstr = g_strdup(_(" items selected"));
+       } else {
                sel = g_strdup("");
+               itstr = g_strdup("");
+       }
+               
        str = g_strconcat(n_selected ? itos(n_selected) : "",
-                         n_selected ? _(" item(s) selected") : "",
-                         sel, spc, del, mv, cp, NULL);
+                                       itstr, sel, spc, del, mv, cp, NULL);
        gtk_label_set(GTK_LABEL(summaryview->statlabel_select), str);
        g_free(str);
        g_free(sel);
        g_free(del);
        g_free(mv);
        g_free(cp);
+       g_free(itstr);
 
        if (summaryview->folder_item &&
            FOLDER_IS_LOCAL(summaryview->folder_item->folder)) {
@@ -2233,6 +2270,15 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row,
                summaryview->newmsgs--;
        if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->unread--;
+       if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags) || 
+           MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags)) {
+               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
+               if (MSG_IS_IMAP(msginfo->flags))
+                       imap_msg_unset_perm_flags(msginfo, MSG_NEW | MSG_UNREAD);
+               summary_set_row_marks(summaryview, row);
+               gtk_clist_thaw(GTK_CLIST(ctree));
+               summary_status_show(summaryview);
+       }
 
        if (new_window) {
                MessageView *msgview;
@@ -2362,10 +2408,7 @@ static void summary_toggle_view(SummaryView *summaryview)
                summaryview->msg_is_toggled_on = FALSE;
                summaryview->displayed = NULL;
                gtk_widget_ref(vpaned);
-               gtk_editable_claim_selection
-                       (GTK_EDITABLE(summaryview->messageview->textview->text),
-                        FALSE, GDK_CURRENT_TIME);
-               gtk_container_remove(GTK_CONTAINER(container), vpaned);
+               gtkut_container_remove(GTK_CONTAINER(container), vpaned);
                gtk_widget_reparent(GTK_WIDGET_PTR(summaryview), container);
                gtk_arrow_set(GTK_ARROW(summaryview->toggle_arrow),
                              GTK_ARROW_UP, GTK_SHADOW_OUT);
@@ -2567,9 +2610,10 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
        MSG_SET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_set_perm_flags(msginfo, MSG_MARKED);
        CHANGE_FLAGS(msginfo);
        summary_set_row_marks(summaryview, row);
-       imap_do_mark(msginfo);
        debug_print(_("Message %s/%d is marked\n"), msginfo->folder->path, msginfo->msgnum);
 }
 
@@ -2600,6 +2644,8 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
        MSG_SET_PERM_FLAGS(msginfo->flags, MSG_LOCKED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_set_perm_flags(msginfo, MSG_LOCKED);
        CHANGE_FLAGS(msginfo);
        summary_set_row_marks(summaryview, row);
        debug_print(_("Message %d is locked\n"), msginfo->msgnum);
@@ -2631,6 +2677,8 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
        if (MSG_IS_NEW(msginfo->flags) ||
            MSG_IS_UNREAD(msginfo->flags)) {
                MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
+               if (MSG_IS_IMAP(msginfo->flags))
+                       imap_msg_unset_perm_flags(msginfo, MSG_NEW | MSG_UNREAD);
                CHANGE_FLAGS(msginfo);
                summary_set_row_marks(summaryview, row);
                debug_print(_("Message %d is marked as read\n"),
@@ -2683,8 +2731,12 @@ static void summary_mark_row_as_unread(SummaryView *summaryview,
                summaryview->deleted--;
        }
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_REPLIED | MSG_FORWARDED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, MSG_REPLIED);
        if (!MSG_IS_UNREAD(msginfo->flags)) {
                MSG_SET_PERM_FLAGS(msginfo->flags, MSG_UNREAD);
+               if (MSG_IS_IMAP(msginfo->flags))
+                       imap_msg_set_perm_flags(msginfo, MSG_UNREAD);
                summaryview->unread++;
                debug_print(_("Message %d is marked as unread\n"),
                            msginfo->msgnum);
@@ -2734,6 +2786,8 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
        }
        msginfo->to_folder = NULL;
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
        MSG_SET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
        CHANGE_FLAGS(msginfo);
@@ -2859,10 +2913,11 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
        }
        msginfo->to_folder = NULL;
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
        CHANGE_FLAGS(msginfo);
        summary_set_row_marks(summaryview, row);
-       imap_do_unmark(msginfo);
        debug_print(_("Message %s/%d is unmarked\n"),
                    msginfo->folder->path, msginfo->msgnum);
 }
@@ -2872,8 +2927,7 @@ void summary_unmark(SummaryView *summaryview)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        GList *cur;
 
-       for (cur = GTK_CLIST(ctree)->selection; cur != NULL;
-            cur = cur->next)
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL; cur = cur->next)
                summary_unmark_row(summaryview, GTK_CTREE_NODE(cur->data));
 
        summary_status_show(summaryview);
@@ -2907,6 +2961,8 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                        msginfo->to_folder->op_count--;
        }
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_COPY);
        if (!MSG_IS_MOVE(msginfo->flags)) {
                MSG_SET_TMP_FLAGS(msginfo->flags, MSG_MOVE);
@@ -2996,6 +3052,8 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                        msginfo->to_folder->op_count--;
        }
        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED | MSG_DELETED);
+       if (MSG_IS_IMAP(msginfo->flags))
+               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
        MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE);
        if (!MSG_IS_COPY(msginfo->flags)) {
                MSG_SET_TMP_FLAGS(msginfo->flags, MSG_COPY);
@@ -3558,6 +3616,17 @@ static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
        }
 }
 
+void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
+                             GSList * mlist)
+{
+       GSList * cur;
+       for(cur = mlist ; cur != NULL ; cur = cur->next) {
+               MsgInfo * msginfo = (MsgInfo *) cur->data;
+               string_remove_all_matches(msginfo->subject, rexp, 
+                                         REG_EXTENDED, 0);
+       }
+}
+
 void summary_processing(SummaryView *summaryview, GSList * mlist)
 {
        GSList * processing_list;
@@ -4010,8 +4079,16 @@ void summary_set_column_order(SummaryView *summaryview)
        GtkWidget *scrolledwin = summaryview->scrolledwin;
        GtkWidget *pixmap;
        FolderItem *item;
+       guint selected_msgnum = summary_get_msgnum(summaryview, summaryview->selected);
+       guint displayed_msgnum = summary_get_msgnum(summaryview, summaryview->displayed);
 
+       
        item = summaryview->folder_item;
+
+       summary_lock(summaryview);
+       summary_write_cache(summaryview);
+       summary_unlock(summaryview);
+       
        summary_clear_all(summaryview);
        gtk_widget_destroy(summaryview->ctree);
 
@@ -4028,6 +4105,13 @@ void summary_set_column_order(SummaryView *summaryview)
        gtk_widget_show(ctree);
 
        summary_show(summaryview, item, FALSE);
+
+       summary_select_by_msgnum(summaryview, selected_msgnum);
+       summaryview->displayed = summary_find_msg_by_msgnum(summaryview, displayed_msgnum);
+       if (!summaryview->displayed)
+               messageview_clear(summaryview->messageview);
+       else
+               summary_redisplay_msg(summaryview);
 }
 
 
@@ -4312,6 +4396,8 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        case S_COL_MARK:
                if (MSG_IS_MARKED(msginfo->flags)) {
                        MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_MARKED);
+                       if (MSG_IS_IMAP(msginfo->flags))
+                               imap_msg_unset_perm_flags(msginfo, MSG_MARKED);
                        CHANGE_FLAGS(msginfo);
                        summary_set_row_marks(summaryview, row);
                } else
@@ -4401,7 +4487,16 @@ static void summary_reply_cb(SummaryView *summaryview, guint action,
                compose_reply(msginfo, FALSE, TRUE, FALSE);
                break;
        case COMPOSE_FORWARD:
-               if (!sel->next) {
+               if (prefs_common.forward_as_attachment) {
+                       summary_reply_cb(summaryview, COMPOSE_FORWARD_AS_ATTACH, widget);
+                       return;
+               } else {
+                       summary_reply_cb(summaryview, COMPOSE_FORWARD_INLINE, widget);
+                       return;
+               }
+               break;
+       case COMPOSE_FORWARD_INLINE:
+               if (!sel->next) {
                        compose_forward(NULL, msginfo, FALSE);
                        break;
                }
@@ -4514,7 +4609,7 @@ static void summary_start_drag(GtkWidget *widget, gint button, GdkEvent *event,
        list = gtk_target_list_new(summary_drag_types, 1);
 
        context = gtk_drag_begin(widget, list,
-                                GDK_ACTION_MOVE, button, event);
+                                GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT, button, event);
        gtk_drag_set_icon_default(context);
 }
 
@@ -4805,7 +4900,28 @@ void processing_apply(SummaryView * summaryview)
        }
 }
 
-
+void summary_toggle_show_read_messages(SummaryView *summaryview)
+{
+       if (summaryview->folder_item->hide_read_msgs)
+               summaryview->folder_item->hide_read_msgs = 0;
+       else
+               summaryview->folder_item->hide_read_msgs = 1;
+       summary_show(summaryview, summaryview->folder_item, FALSE);
+}
+static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
+                                            guint action)
+{
+       GtkWidget *widget;
+       widget = gtk_item_factory_get_item(gtk_item_factory_from_widget(summaryview->mainwin->menubar),
+                                          "/Summary/Hide read messages");
+       gtk_object_set_data(GTK_OBJECT(widget), "dont_toggle",
+                           GINT_TO_POINTER(1));
+       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(widget), action);
+       gtk_object_set_data(GTK_OBJECT(widget), "dont_toggle",
+                           GINT_TO_POINTER(0));
+}
 /*
  * End of Source.
  */