2006-08-25 [colin] 2.4.0cvs92
authorColin Leroy <colin@colino.net>
Fri, 25 Aug 2006 17:02:15 +0000 (17:02 +0000)
committerColin Leroy <colin@colino.net>
Fri, 25 Aug 2006 17:02:15 +0000 (17:02 +0000)
* src/folder.c
* src/folderutils.c
* src/mh.c
* src/procmsg.h
* src/summaryview.c
Speed up MH moving, and add progressbar
for MH deletion
* src/msgcache.c
Write cache files using mmap() too

ChangeLog
PATCHSETS
configure.ac
src/folder.c
src/folderutils.c
src/mh.c
src/msgcache.c
src/procmsg.h
src/summaryview.c

index 1b047502f28b6e36b2684cd737aa4377bce956a7..30212973cab50b7d448bb10ab7f7c91d60e34508 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-08-25 [colin]     2.4.0cvs92
+
+       * src/folder.c
+       * src/folderutils.c
+       * src/mh.c
+       * src/procmsg.h
+       * src/summaryview.c
+               Speed up MH moving, and add progressbar
+               for MH deletion
+       * src/msgcache.c
+               Write cache files using mmap() too
+
 2006-08-25 [wwp]       2.4.0cvs91
 
        * src/summaryview.c
index aeb43aa372b89e6eb0782d4f3e9115ee0270b3fe..d3461c5d604c106cd3f2bca71b939c26f8c16270 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.11 -r 1.1.2.12 manual/glossary.xml;  cvs diff -u -r 1.60.2.32 -r 1.60.2.33 po/es.po;  ) > 2.4.0cvs89.patchset
 ( cvs diff -u -r 1.155.2.40 -r 1.155.2.41 src/Makefile.am;  cvs diff -u -r 1.25.2.26 -r 1.25.2.27 src/stock_pixmap.c;  cvs diff -u -r 1.18.2.17 -r 1.18.2.18 src/stock_pixmap.h;  cvs diff -u -r 1.395.2.232 -r 1.395.2.233 src/summaryview.c;  cvs diff -u -r 1.1.2.8 -r 1.1.2.9 src/gtk/icon_legend.c;  diff -u /dev/null src/pixmaps/copied.xpm;  diff -u /dev/null src/pixmaps/moved.xpm;  ) > 2.4.0cvs90.patchset
 ( cvs diff -u -r 1.395.2.233 -r 1.395.2.234 src/summaryview.c;  ) > 2.4.0cvs91.patchset
+( cvs diff -u -r 1.213.2.108 -r 1.213.2.109 src/folder.c;  cvs diff -u -r 1.3.2.11 -r 1.3.2.12 src/folderutils.c;  cvs diff -u -r 1.79.2.38 -r 1.79.2.39 src/mh.c;  cvs diff -u -r 1.16.2.36 -r 1.16.2.37 src/msgcache.c;  cvs diff -u -r 1.60.2.32 -r 1.60.2.33 src/procmsg.h;  cvs diff -u -r 1.395.2.234 -r 1.395.2.235 src/summaryview.c;  ) > 2.4.0cvs92.patchset
index 546cf4db06939246d96851ecf8006183483c21aa..af67985f71cf3781a409f42d34569dfa3b162e0a 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=4
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=91
+EXTRA_VERSION=92
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index dae3b4cbce4e9507b81d0941bc119d4f32fc2882..b26b12329193d03dac1896c098128c0483e1b4dc 100644 (file)
@@ -2590,7 +2590,7 @@ static void copy_msginfo_flags(MsgInfo *source, MsgInfo *dest)
                perm_flags |= MSG_IGNORE_THREAD;
 
        /* Unset tmp flags that should not be copied */
-       tmp_flags &= ~(MSG_MOVE | MSG_COPY);
+       tmp_flags &= ~(MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
 
        /* unset flags that are set but should not */
        /* and set new flags */
index 181e88e67dfcc9edb959d1b76e3599b8dbb175f7..5a7a2f4565e06117d35534d7e70fa89872f2b41b 100644 (file)
@@ -91,7 +91,8 @@ gint folderutils_delete_duplicates(FolderItem *item,
                                MsgInfo *msginfo = (MsgInfo *) cur->data;
 
                                procmsg_msginfo_set_to_folder(msginfo, NULL);
-                               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, MSG_MOVE | MSG_COPY);
+                               procmsg_msginfo_unset_flags(msginfo, MSG_MARKED, 
+                                       MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
                                procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
                        }
                        break;
index e00fb078a000fa435cff5e7e256ce30039f3d236..e3753cc8d0dc66d95cdcb9972781c278d8287967 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -537,6 +537,7 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
 
 
                if (MSG_IS_MOVE(msginfo->flags)) {
+                       msginfo->flags.tmp_flags &= ~MSG_MOVE_DONE;
                        if (move_file(srcfile, destfile, TRUE) < 0) {
                                FILE_OP_ERROR(srcfile, "move");
                                if (copy_file(srcfile, destfile, TRUE) < 0) {
@@ -545,6 +546,9 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
                                        g_free(destfile);
                                        goto err_reset_status;
                                }
+                       } else {
+                               /* say unlinking's not necessary */
+                               msginfo->flags.tmp_flags |= MSG_MOVE_DONE;
                        }
                } else if (copy_file(srcfile, destfile, TRUE) < 0) {
                        FILE_OP_ERROR(srcfile, "copy");
@@ -624,6 +628,7 @@ static gint mh_remove_msgs(Folder *folder, FolderItem *item,
        gchar *path, *file;
        time_t last_mtime = (time_t)0;
        MsgInfoList *cur;
+       gint total = 0, curnum = 0;
 
        g_return_val_if_fail(item != NULL, -1);
 
@@ -632,10 +637,25 @@ static gint mh_remove_msgs(Folder *folder, FolderItem *item,
        need_scan = mh_scan_required(folder, item);
        last_mtime = item->mtime;
 
+       total = g_slist_length(msglist);
+       if (total > 100) {
+               statusbar_print_all(_("Deleting messages..."));
+       }
+
        for (cur = msglist; cur; cur = cur->next) {
                MsgInfo *msginfo = (MsgInfo *)cur->data;
                if (msginfo == NULL)
                        continue;
+               if (MSG_IS_MOVE(msginfo->flags) && MSG_IS_MOVE_DONE(msginfo->flags)) {
+                       msginfo->flags.tmp_flags &= ~MSG_MOVE_DONE;
+                       continue;
+               }
+               if (total > 100) {
+                       statusbar_progress_all(curnum, total, 100);
+                       if (curnum % 100 == 0)
+                               GTK_EVENTS_FLUSH();
+                       curnum++;
+               }
                file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(msginfo->msgnum), NULL);
                if (file == NULL)
                        continue;
@@ -648,6 +668,10 @@ static gint mh_remove_msgs(Folder *folder, FolderItem *item,
                g_free(file);
        }
 
+       if (total > 100) {
+               statusbar_progress_all(0,0,0);
+               statusbar_pop_all();
+       }
        if (item->mtime == last_mtime && !need_scan)
                item->mtime = time(NULL);
 
index f6f28d3198e8de560be34d9f56477549035ac692..1441e7efd3c327df4fb87f3e3531e06edf9d3d1b 100644 (file)
      ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
      
+#define MMAP_TO_GUINT32(x)     \
+       (((x[3]&0xff)) |        \
+        ((x[2]&0xff) << 8) |   \
+        ((x[1]&0xff) << 16) |  \
+        ((x[0]&0xff) << 24))
+
+#define MMAP_TO_GUINT32_SWAPPED(x)     \
+       (((x[0]&0xff)) |                \
+        ((x[1]&0xff) << 8) |           \
+        ((x[2]&0xff) << 16) |          \
+        ((x[3]&0xff) << 24))
+
 static gboolean msgcache_use_mmap = FALSE;
+
 #else
 #define bswap_32(x) (x)
-static gboolean msgcache_use_mmap = TRUE;
-#endif
 
-#define MMAP_TO_GUINT32(x) \
-       (((x[0]&0xff)) | \
-        ((x[1]&0xff) << 8) | \
-        ((x[2]&0xff) << 16) | \
+#define MMAP_TO_GUINT32(x)     \
+       (((x[0]&0xff)) |        \
+        ((x[1]&0xff) << 8) |   \
+        ((x[2]&0xff) << 16) |  \
+        ((x[3]&0xff) << 24))
+
+#define MMAP_TO_GUINT32_SWAPPED(x)     \
+       (((x[0]&0xff)) |                \
+        ((x[1]&0xff) << 8) |           \
+        ((x[2]&0xff) << 16) |          \
         ((x[3]&0xff) << 24))
 
+static gboolean msgcache_use_mmap = TRUE;
+#endif
+
 static gboolean swapping = TRUE;
 
 typedef enum
@@ -273,8 +293,7 @@ gint msgcache_get_memory_usage(MsgCache *cache)
 
 #define GET_CACHE_DATA_INT(n) \
 { \
-       guint32 idata = MMAP_TO_GUINT32(walk_data); \
-       n = swapping ? bswap_32(idata) : (idata);\
+       n = (swapping ? (MMAP_TO_GUINT32_SWAPPED(walk_data)):(MMAP_TO_GUINT32(walk_data))); \
        walk_data += 4; rem_len -= 4;                   \
 }
 
@@ -292,29 +311,56 @@ gint msgcache_get_memory_usage(MsgCache *cache)
 }
 
 
-#define WRITE_CACHE_DATA_INT(n, fp)            \
-{                                              \
-       guint32 idata;                          \
-                                               \
+#define WRITE_CACHE_DATA_INT(n, fp)                    \
+{                                                      \
+       guint32 idata;                                  \
+                                                       \
        idata = (guint32)bswap_32(n);                   \
        if (fwrite(&idata, sizeof(idata), 1, fp) != 1)  \
                w_err = 1;                              \
+       wrote += 4;                                     \
+}
+
+#define PUT_CACHE_DATA_INT(n)                          \
+{                                                      \
+       walk_data[0]=(((guint32)n)&0x000000ff);                 \
+       walk_data[1]=(((guint32)n)&0x0000ff00)>>8;              \
+       walk_data[2]=(((guint32)n)&0x00ff0000)>>16;             \
+       walk_data[3]=(((guint32)n)&0xff000000)>>24;             \
+       walk_data += 4;                                 \
+       wrote += 4;                                     \
 }
 
 #define WRITE_CACHE_DATA(data, fp) \
 { \
-       size_t len; \
-       if (data == NULL) \
-               len = 0; \
-       else \
-               len = strlen(data); \
-       WRITE_CACHE_DATA_INT(len, fp); \
-       if (w_err == 0 && len > 0) { \
-               if (fwrite(data, 1, len, fp) != len) \
+       size_t len;                                     \
+       if (data == NULL)                               \
+               len = 0;                                \
+       else                                            \
+               len = strlen(data);                     \
+       WRITE_CACHE_DATA_INT(len, fp);                  \
+       if (w_err == 0 && len > 0) {                    \
+               if (fwrite(data, 1, len, fp) != len)    \
                        w_err = 1;                      \
+               wrote += len;                           \
        } \
 }
 
+#define PUT_CACHE_DATA(data)                           \
+{                                                      \
+       size_t len;                                     \
+       if (data == NULL)                               \
+               len = 0;                                \
+       else                                            \
+               len = strlen(data);                     \
+       PUT_CACHE_DATA_INT(len);                        \
+       if (len > 0) {                                  \
+               memcpy(walk_data, data, len);           \
+               walk_data += len;                       \
+               wrote += len;                           \
+       }                                               \
+}
+
 static FILE *msgcache_open_data_file(const gchar *file, guint version,
                                     DataOpenMode mode,
                                     gchar *buf, size_t buf_size)
@@ -325,8 +371,8 @@ static FILE *msgcache_open_data_file(const gchar *file, guint version,
        g_return_val_if_fail(file != NULL, NULL);
 
        if (mode == DATA_WRITE) {
-               int w_err = 0;
-               if ((fp = g_fopen(file, "wb")) == NULL) {
+               int w_err = 0, wrote = 0;
+               if ((fp = g_fopen(file, "w+")) == NULL) {
                        FILE_OP_ERROR(file, "fopen");
                        return NULL;
                }
@@ -759,7 +805,7 @@ static int msgcache_write_cache(MsgInfo *msginfo, FILE *fp)
 {
        MsgTmpFlags flags = msginfo->flags.tmp_flags & MSG_CACHED_FLAG_MASK;
        GSList *cur;
-       int w_err = 0;
+       int w_err = 0, wrote = 0;
 
        WRITE_CACHE_DATA_INT(msginfo->msgnum, fp);
        WRITE_CACHE_DATA_INT(msginfo->size, fp);
@@ -786,43 +832,119 @@ static int msgcache_write_cache(MsgInfo *msginfo, FILE *fp)
        for (cur = msginfo->references; cur != NULL; cur = cur->next) {
                WRITE_CACHE_DATA((gchar *)cur->data, fp);
        }
-       return w_err;
+       return w_err ? -1 : wrote;
+}
+
+static int msgcache_write_mmap_cache(MsgInfo *msginfo, char *walk_data)
+{
+       MsgTmpFlags flags = msginfo->flags.tmp_flags & MSG_CACHED_FLAG_MASK;
+       GSList *cur;
+       int wrote = 0;
+
+       PUT_CACHE_DATA_INT(msginfo->msgnum);
+       PUT_CACHE_DATA_INT(msginfo->size);
+       PUT_CACHE_DATA_INT(msginfo->mtime);
+       PUT_CACHE_DATA_INT(msginfo->date_t);
+       PUT_CACHE_DATA_INT(flags);
+       PUT_CACHE_DATA(msginfo->fromname);
+
+       PUT_CACHE_DATA(msginfo->date);
+       PUT_CACHE_DATA(msginfo->from);
+       PUT_CACHE_DATA(msginfo->to);
+       PUT_CACHE_DATA(msginfo->cc);
+       PUT_CACHE_DATA(msginfo->newsgroups);
+       PUT_CACHE_DATA(msginfo->subject);
+       PUT_CACHE_DATA(msginfo->msgid);
+       PUT_CACHE_DATA(msginfo->inreplyto);
+       PUT_CACHE_DATA(msginfo->xref);
+       PUT_CACHE_DATA_INT(msginfo->planned_download);
+       PUT_CACHE_DATA_INT(msginfo->total_size);
+        
+       PUT_CACHE_DATA_INT(g_slist_length(msginfo->references));
+
+       for (cur = msginfo->references; cur != NULL; cur = cur->next) {
+               PUT_CACHE_DATA((gchar *)cur->data);
+       }
+       return wrote;
 }
 
 static int msgcache_write_flags(MsgInfo *msginfo, FILE *fp)
 {
        MsgPermFlags flags = msginfo->flags.perm_flags;
-       int w_err = 0;
+       int w_err = 0, wrote = 0;
        WRITE_CACHE_DATA_INT(msginfo->msgnum, fp);
        WRITE_CACHE_DATA_INT(flags, fp);
-       return w_err;
+       return w_err ? -1 : wrote;
+}
+
+static int msgcache_write_mmap_flags(MsgInfo *msginfo, char *walk_data)
+{
+       MsgPermFlags flags = msginfo->flags.perm_flags;
+       int wrote = 0;
+
+       PUT_CACHE_DATA_INT(msginfo->msgnum);
+       PUT_CACHE_DATA_INT(flags);
+       return wrote;
 }
 
 struct write_fps
 {
        FILE *cache_fp;
        FILE *mark_fp;
+       char *cache_data;
+       char *mark_data;
        int error;
+       guint cache_size;
+       guint mark_size;
 };
 
 static void msgcache_write_func(gpointer key, gpointer value, gpointer user_data)
 {
        MsgInfo *msginfo;
        struct write_fps *write_fps;
+       int tmp;
+
+       msginfo = (MsgInfo *)value;
+       write_fps = user_data;
+
+       tmp = msgcache_write_cache(msginfo, write_fps->cache_fp);
+       if (tmp < 0)
+               write_fps->error = 1;
+       else
+               write_fps->cache_size += tmp;
+       tmp= msgcache_write_flags(msginfo, write_fps->mark_fp);
+       if (tmp < 0)
+               write_fps->error = 1;
+       else
+               write_fps->mark_size += tmp;
+}
+
+static void msgcache_write_mmap_func(gpointer key, gpointer value, gpointer user_data)
+{
+       MsgInfo *msginfo;
+       struct write_fps *write_fps;
+       int tmp;
 
        msginfo = (MsgInfo *)value;
        write_fps = user_data;
 
-       write_fps->error |= msgcache_write_cache(msginfo, write_fps->cache_fp);
-       write_fps->error |= msgcache_write_flags(msginfo, write_fps->mark_fp);
+       tmp = msgcache_write_mmap_cache(msginfo, write_fps->cache_data);
+       write_fps->cache_size += tmp;
+       write_fps->cache_data += tmp;
+       tmp = msgcache_write_mmap_flags(msginfo, write_fps->mark_data);
+       write_fps->mark_size += tmp;
+       write_fps->mark_data += tmp;
 }
 
 gint msgcache_write(const gchar *cache_file, const gchar *mark_file, MsgCache *cache)
 {
        struct write_fps write_fps;
        gchar *new_cache, *new_mark;
-       int w_err = 0;
-
+       int w_err = 0, wrote = 0;
+       gint map_len = -1;
+       char *cache_data = NULL;
+       char *mark_data = NULL;
+       START_TIMING("*** writing caches");
        g_return_val_if_fail(cache_file != NULL, -1);
        g_return_val_if_fail(mark_file != NULL, -1);
        g_return_val_if_fail(cache != NULL, -1);
@@ -831,6 +953,8 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, MsgCache *c
        new_mark  = g_strconcat(mark_file, ".new", NULL);
 
        write_fps.error = 0;
+       write_fps.cache_size = 0;
+       write_fps.mark_size = 0;
        write_fps.cache_fp = msgcache_open_data_file(new_cache, CACHE_VERSION,
                DATA_WRITE, NULL, 0);
        if (write_fps.cache_fp == NULL) {
@@ -865,8 +989,37 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, MsgCache *c
        if (change_file_mode_rw(write_fps.cache_fp, new_cache) < 0)
                FILE_OP_ERROR(new_cache, "chmod");
 
-       g_hash_table_foreach(cache->msgnum_table, msgcache_write_func, (gpointer)&write_fps);
+       write_fps.cache_size = ftell(write_fps.cache_fp);
+       write_fps.mark_size = ftell(write_fps.mark_fp);
+       if (msgcache_use_mmap && cache->memusage > 0) {
+               map_len = cache->memusage;
+               if (ftruncate(fileno(write_fps.cache_fp), (off_t)map_len) == 0) {
+                       cache_data = mmap(NULL, map_len, PROT_WRITE, MAP_SHARED, 
+                               fileno(write_fps.cache_fp), 0);
+               }
+               if (cache_data != NULL && cache_data != MAP_FAILED) {
+                       if (ftruncate(fileno(write_fps.mark_fp), (off_t)map_len) == 0) {
+                               mark_data = mmap(NULL, map_len, PROT_WRITE, MAP_SHARED, 
+                                       fileno(write_fps.mark_fp), 0);
+                       } 
+                       if (mark_data == NULL || mark_data == MAP_FAILED) {
+                               munmap(cache_data, map_len);
+                               cache_data = NULL;
+                       }
+               }
+       }
 
+       if (cache_data != NULL && cache_data != MAP_FAILED) {
+               write_fps.cache_data = cache_data + ftell(write_fps.cache_fp);
+               write_fps.mark_data = mark_data + ftell(write_fps.mark_fp);
+               g_hash_table_foreach(cache->msgnum_table, msgcache_write_mmap_func, (gpointer)&write_fps);
+               munmap(cache_data, map_len);
+               munmap(mark_data, map_len);
+       } else {
+               g_hash_table_foreach(cache->msgnum_table, msgcache_write_func, (gpointer)&write_fps);
+       }
+       ftruncate(fileno(write_fps.cache_fp), write_fps.cache_size);
+       ftruncate(fileno(write_fps.mark_fp), write_fps.mark_size);
        fclose(write_fps.cache_fp);
        fclose(write_fps.mark_fp);
 
@@ -886,6 +1039,7 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, MsgCache *c
        g_free(new_cache);
        g_free(new_mark);
        debug_print("done.\n");
+       END_TIMING();
        return 0;
 }
 
index 93d4637c51ff04fcfb05b3aba33f529a563919f7..f5fcf8e96dab9418068709a01566b2c45d51907b 100644 (file)
@@ -86,6 +86,7 @@ typedef guint32 MsgPermFlags;
 
 #define MSG_MOVE               (1U << 0)
 #define MSG_COPY               (1U << 1)
+#define MSG_MOVE_DONE          (1U << 15)              
 #define MSG_QUEUED             (1U << 16)
 #define MSG_DRAFT              (1U << 17)
 #define MSG_ENCRYPTED          (1U << 18)
@@ -130,6 +131,7 @@ typedef guint32 MsgTmpFlags;
 
 #define MSG_IS_MOVE(msg)               (((msg).tmp_flags & MSG_MOVE) != 0)
 #define MSG_IS_COPY(msg)               (((msg).tmp_flags & MSG_COPY) != 0)
+#define MSG_IS_MOVE_DONE(msg)          (((msg).tmp_flags & MSG_MOVE_DONE) != 0)
 
 #define MSG_IS_QUEUED(msg)             (((msg).tmp_flags & MSG_QUEUED) != 0)
 #define MSG_IS_DRAFT(msg)              (((msg).tmp_flags & MSG_DRAFT) != 0)
@@ -167,6 +169,13 @@ struct _MsgFlags
        MsgTmpFlags  tmp_flags;
 };
 
+/* *********************************************************** *
+ * WARNING: When adding or removing members to this structure, *
+ * be sure to update procmsg.c::procmsg_msginfo_memusage()  to *
+ * avoid underestimating cache memory usage - especially since *
+ * this would cause an overflow and metadata loss when writing *
+ * the cache to disk.                                          *
+ * *********************************************************** */
 struct _MsgInfo
 {
        guint refcnt;
index 5d5e2e3f23cd5210661f783bfe8ac87c3463cf32..270fd08fcfa8e0cae073262655965ae1646a35b1 100644 (file)
@@ -3156,7 +3156,8 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summary_set_row_marks(summaryview, row);
        debug_print("Message %s/%d is marked\n", msginfo->folder->path, msginfo->msgnum);
 }
@@ -3180,7 +3181,8 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
                changed = TRUE;
        }
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        
        summary_set_row_marks(summaryview, row);
        debug_print("Message %d is locked\n", msginfo->msgnum);
@@ -3486,7 +3488,8 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summaryview->deleted++;
 
        if (!prefs_common.immediate_exec && 
@@ -3625,7 +3628,8 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row)
                summaryview->copied--;
 
        procmsg_msginfo_set_to_folder(msginfo, NULL);
-       summary_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY);
+       summary_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, 
+               MSG_MOVE | MSG_COPY | MSG_MOVE_DONE);
        summary_set_row_marks(summaryview, row);
 
        debug_print("Message %s/%d is unmarked\n",
@@ -3668,7 +3672,8 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row,
                summaryview->copied--;
        }
        if (!MSG_IS_MOVE(msginfo->flags)) {
-               summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, MSG_COPY);
+               summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, 
+                       MSG_COPY | MSG_MOVE_DONE);
                summaryview->moved++;
        } else {
                summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_COPY);
@@ -3760,7 +3765,8 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row,
        }
        
        if (!MSG_IS_COPY(msginfo->flags)) {
-               summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, MSG_MOVE);
+               summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, 
+                       MSG_MOVE | MSG_MOVE_DONE);
                summaryview->copied++;
        } else {
                summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE);