]> granicus.if.org Git - mutt/commitdiff
Add the trash folder patch.
authorKevin McCarthy <kevin@8t8.us>
Mon, 18 Jul 2016 02:31:09 +0000 (19:31 -0700)
committerKevin McCarthy <kevin@8t8.us>
Mon, 18 Jul 2016 02:31:09 +0000 (19:31 -0700)
This is based on the trash folder patch by Cedric Duval.
Modifications to the original patch are:

* Use a flag called M_PURGE instead of M_APPENDED.  The same flag is
  then used in the following "purge" patch instead of adding a
  different flag.

* Removed the counter in context.  The existing context->deleted
  is all that's needed.

* Removed the "auto unset M_PURGE" when M_DELETED is unset inside
  _mutt_set_flag(), although this is convenient, it easily leads to
  header->purge not being reset in a few situations.

* Reset purge flag along with the deleted flag if $delete is answered
  no.

* Set M_PURGE on an edited message. (edit_one_message())

* Preserve purge flag in mutt_reopen_mailbox()

* Turn off OPTCONFIRMAPPEND when saving to the trash, rather than
  hardcoding it off in mutt_save_confirm().  That way, normal save to the
  folder will respect the option.

13 files changed:
commands.c
curs_main.c
editmsg.c
flags.c
globals.h
imap/message.c
init.h
mbox.c
mutt.h
mx.c
pager.c
pattern.c
postpone.c

index c5811bd4500733f2f1756062f0f51ae8e1d2b82c..2202a673328ec3ba027525f5f0e569da0133da8a 100644 (file)
@@ -717,6 +717,7 @@ int _mutt_save_message (HEADER *h, CONTEXT *ctx, int delete, int decode, int dec
   if (delete)
   {
     mutt_set_flag (Context, h, MUTT_DELETE, 1);
+    mutt_set_flag (Context, h, MUTT_PURGE, 1);
     if (option (OPTDELETEUNTAG))
       mutt_set_flag (Context, h, MUTT_TAG, 0);
   }
index d0ff0aa6adc4c4bb6222c83f60a0630740d9ebd8..8c291bdfd98dd17b27b154ddf81f26026442e890 100644 (file)
@@ -2273,11 +2273,13 @@ int mutt_index_menu (void)
        if (tag)
        {
          mutt_tag_set_flag (MUTT_DELETE, 0);
+         mutt_tag_set_flag (MUTT_PURGE, 0);
          menu->redraw = REDRAW_INDEX;
        }
        else
        {
          mutt_set_flag (Context, CURHDR, MUTT_DELETE, 0);
+         mutt_set_flag (Context, CURHDR, MUTT_PURGE, 0);
          if (option (OPTRESOLVE) && menu->current < Context->vcount - 1)
          {
            menu->current++;
@@ -2300,7 +2302,9 @@ int mutt_index_menu (void)
 
        rc = mutt_thread_set_flag (CURHDR, MUTT_DELETE, 0,
                                   op == OP_UNDELETE_THREAD ? 0 : 1);
-
+        if (rc != -1)
+          rc = mutt_thread_set_flag (CURHDR, MUTT_PURGE, 0,
+                                     op == OP_UNDELETE_THREAD ? 0 : 1);
        if (rc != -1)
        {
          if (option (OPTRESOLVE))
index 57d8b1ca1495135d029d6c1bf239f1bb99f9e73d..356810a00cf1a0e5069a6433a0703eb507545058 100644 (file)
--- a/editmsg.c
+++ b/editmsg.c
@@ -200,6 +200,7 @@ static int edit_one_message (CONTEXT *ctx, HEADER *cur)
   if (rc == 0)
   {
     mutt_set_flag (Context, cur, MUTT_DELETE, 1);
+    mutt_set_flag (Context, cur, MUTT_PURGE, 1);
     mutt_set_flag (Context, cur, MUTT_READ, 1);
 
     if (option (OPTDELETEUNTAG))
diff --git a/flags.c b/flags.c
index 82e48647131767d88cb96a63b07877f0255d8cef..3e80251372dab11c7daceaf219fa23621db0e702 100644 (file)
--- a/flags.c
+++ b/flags.c
@@ -87,6 +87,20 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
       }
       break;
 
+    case MUTT_PURGE:
+
+      if (!mutt_bit_isset(ctx->rights,MUTT_ACL_DELETE))
+        return;
+
+      if (bf)
+      {
+        if (!h->purge && !ctx->readonly)
+          h->purge = 1;
+      }
+      else if (h->purge)
+        h->purge = 0;
+      break;
+
     case MUTT_NEW:
 
       if (!mutt_bit_isset(ctx->rights,MUTT_ACL_SEEN))
@@ -345,6 +359,13 @@ int mutt_change_flag (HEADER *h, int bf)
   {
     case 'd':
     case 'D':
+      if (!bf)
+      {
+        if (h)
+          mutt_set_flag (Context, h, MUTT_PURGE, bf);
+        else
+          mutt_tag_set_flag (MUTT_PURGE, bf);
+      }
       flag = MUTT_DELETE;
       break;
 
index d2b6124d48f9676ff5741ad2267d24e700c4f4e9..af38a43c73b3afd1df40cf4df8ee0972e26bd49b 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -147,6 +147,7 @@ WHERE char *StChars;
 WHERE char *Status;
 WHERE char *Tempdir;
 WHERE char *Tochars;
+WHERE char *TrashPath;
 WHERE char *TSStatusFormat;
 WHERE char *TSIconFormat;
 WHERE short TSSupported;
index 0882780840866ecb50b781ebc875a0ae0eb7b7f6..5ce585868f716b9e987aaa79c29182f372f6cff1 100644 (file)
@@ -902,6 +902,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
         if (ctx->hdrs[n]->tagged)
         {
           mutt_set_flag (ctx, ctx->hdrs[n], MUTT_DELETE, 1);
+          mutt_set_flag (ctx, ctx->hdrs[n], MUTT_PURGE, 1);
           if (option (OPTDELETEUNTAG))
             mutt_set_flag (ctx, ctx->hdrs[n], MUTT_TAG, 0);
         }
@@ -909,6 +910,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
     else
     {
       mutt_set_flag (ctx, h, MUTT_DELETE, 1);
+      mutt_set_flag (ctx, h, MUTT_PURGE, 1);
       if (option (OPTDELETEUNTAG))
         mutt_set_flag (ctx, h, MUTT_TAG, 0);
     }
diff --git a/init.h b/init.h
index 2f582025ae4044592a9b1982a5cea8f2e327b0bd..02073557e64e41dd2127475499869984b18bf41b 100644 (file)
--- a/init.h
+++ b/init.h
@@ -3553,6 +3553,16 @@ struct option_t MuttVars[] = {
   ** by \fIyou\fP.  The sixth character is used to indicate when a mail
   ** was sent to a mailing-list you subscribe to.
   */
+  { "trash",           DT_PATH, R_NONE, UL &TrashPath, 0 },
+  /*
+  ** .pp
+  ** If set, this variable specifies the path of the trash folder where the
+  ** mails marked for deletion will be moved, instead of being irremediably
+  ** purged.
+  ** .pp
+  ** NOTE: When you delete a message in the trash folder, it is really
+  ** deleted, so that you have a way to clean the trash.
+  */
   {"ts_icon_format",   DT_STR,  R_BOTH, UL &TSIconFormat, UL "M%?n?AIL&ail?"},
   /*
   ** .pp
diff --git a/mbox.c b/mbox.c
index 12d423641d055c4f984bdacd1c4450da78028e80..36dd81e7306a5b4ba26b76be0680f87aac4a7dc1 100644 (file)
--- a/mbox.c
+++ b/mbox.c
@@ -1265,6 +1265,7 @@ int mutt_reopen_mailbox (CONTEXT *ctx, int *index_hint)
          mutt_set_flag (ctx, ctx->hdrs[i], MUTT_READ, old_hdrs[j]->read);
        }
        mutt_set_flag (ctx, ctx->hdrs[i], MUTT_DELETE, old_hdrs[j]->deleted);
+       mutt_set_flag (ctx, ctx->hdrs[i], MUTT_PURGE, old_hdrs[j]->purge);
        mutt_set_flag (ctx, ctx->hdrs[i], MUTT_TAG, old_hdrs[j]->tagged);
 
        /* we don't need this header any more */
diff --git a/mutt.h b/mutt.h
index ce04a68a6bcb5650161ae13fd693471be1a8e503..bd90a49b4d2d9b7fbd0ec705456686dbba8cf431 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -181,6 +181,7 @@ enum
   MUTT_UNREAD,
   MUTT_DELETE,
   MUTT_UNDELETE,
+  MUTT_PURGE,
   MUTT_DELETED,
   MUTT_FLAG,
   MUTT_TAG,
@@ -728,6 +729,7 @@ typedef struct header
   unsigned int flagged : 1;            /* marked important? */
   unsigned int tagged : 1;
   unsigned int deleted : 1;
+  unsigned int purge : 1;               /* skip trash folder when deleting */
   unsigned int changed : 1;
   unsigned int attach_del : 1;                 /* has an attachment marked for deletion */
   unsigned int old : 1;
diff --git a/mx.c b/mx.c
index fe956aac1724c0d2a43f1d2f1db61a5956155303..07f3b4080da8f7d38ac39c6a0914e18e3b5e6c4b 100644 (file)
--- a/mx.c
+++ b/mx.c
@@ -797,6 +797,65 @@ static int sync_mailbox (CONTEXT *ctx, int *index_hint)
   return rc;
 }
 
+/* move deleted mails to the trash folder */
+static int trash_append (CONTEXT *ctx)
+{
+  CONTEXT *ctx_trash;
+  int i;
+  struct stat st, stc;
+  int opt_confappend, rc;
+
+  if (!TrashPath || !ctx->deleted ||
+      (ctx->magic == MUTT_MAILDIR && option (OPTMAILDIRTRASH)))
+    return 0;
+
+  for (i = 0; i < ctx->msgcount; i++)
+    if (ctx->hdrs[i]->deleted  && (!ctx->hdrs[i]->purge))
+      break;
+  if (i == ctx->msgcount)
+    return 0; /* nothing to be done */
+
+  /* avoid the "append messages" prompt */
+  opt_confappend = option (OPTCONFIRMAPPEND);
+  if (opt_confappend)
+    unset_option (OPTCONFIRMAPPEND);
+  rc = mutt_save_confirm (TrashPath, &st);
+  if (opt_confappend)
+    set_option (OPTCONFIRMAPPEND);
+  if (rc != 0)
+  {
+    mutt_error _("message(s) not deleted");
+    return -1;
+  }
+
+  if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
+      && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
+    return 0;  /* we are in the trash folder: simple sync */
+
+  if ((ctx_trash = mx_open_mailbox (TrashPath, MUTT_APPEND, NULL)) != NULL)
+  {
+    /* continue from initial scan above */
+    for (; i < ctx->msgcount ; i++)
+      if (ctx->hdrs[i]->deleted  && (!ctx->hdrs[i]->purge))
+      {
+        if (mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1)
+        {
+          mx_close_mailbox (ctx_trash, NULL);
+          return -1;
+        }
+      }
+
+    mx_close_mailbox (ctx_trash, NULL);
+  }
+  else
+  {
+    mutt_error _("Can't open trash folder");
+    return -1;
+  }
+
+  return 0;
+}
+
 /* save changes and close mailbox */
 int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
 {
@@ -939,6 +998,7 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
          if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0)
          {
            mutt_set_flag (ctx, ctx->hdrs[i], MUTT_DELETE, 1);
+           mutt_set_flag (ctx, ctx->hdrs[i], MUTT_PURGE, 1);
          }
          else
          {
@@ -962,7 +1022,17 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
     mx_fastclose_mailbox (ctx);
     return 0;
   }
-  
+
+  /* copy mails to the trash before expunging */
+  if (purge && ctx->deleted && mutt_strcmp (ctx->path, TrashPath))
+  {
+    if (trash_append (ctx) != 0)
+    {
+      ctx->closing = 0;
+      return -1;
+    }
+  }
+
 #ifdef USE_IMAP
   /* allow IMAP to preserve the deleted flag across sessions */
   if (ctx->magic == MUTT_IMAP)
@@ -979,7 +1049,10 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
     if (!purge)
     {
       for (i = 0; i < ctx->msgcount; i++)
+      {
         ctx->hdrs[i]->deleted = 0;
+        ctx->hdrs[i]->purge = 0;
+      }
       ctx->deleted = 0;
     }
 
@@ -1159,7 +1232,10 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
       if (ctx->magic != MUTT_IMAP)
       {
         for (i = 0 ; i < ctx->msgcount ; i++)
+        {
           ctx->hdrs[i]->deleted = 0;
+          ctx->hdrs[i]->purge = 0;
+        }
         ctx->deleted = 0;
       }
     }
@@ -1172,6 +1248,12 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
   msgcount = ctx->msgcount;
   deleted = ctx->deleted;
 
+  if (purge && ctx->deleted && mutt_strcmp (ctx->path, TrashPath))
+  {
+    if (trash_append (ctx) != 0)
+      return -1;
+  }
+
 #ifdef USE_IMAP
   if (ctx->magic == MUTT_IMAP)
     rc = imap_sync_mailbox (ctx, purge, index_hint);
diff --git a/pager.c b/pager.c
index e6ee9392e47d686f4b7c33625bab50155ae83a09..f8113aea5b7e27bdcee65f3291cd1480c6b566d0 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -2743,6 +2743,7 @@ search_next:
        CHECK_ACL(MUTT_ACL_DELETE, _("Cannot undelete message"));
 
        mutt_set_flag (Context, extra->hdr, MUTT_DELETE, 0);
+       mutt_set_flag (Context, extra->hdr, MUTT_PURGE, 0);
        redraw = REDRAW_STATUS | REDRAW_INDEX;
        if (option (OPTRESOLVE))
        {
@@ -2760,7 +2761,9 @@ search_next:
 
        r = mutt_thread_set_flag (extra->hdr, MUTT_DELETE, 0,
                                  ch == OP_UNDELETE_THREAD ? 0 : 1);
-
+       if (r != -1)
+          r = mutt_thread_set_flag (extra->hdr, MUTT_PURGE, 0,
+                                    ch == OP_UNDELETE_THREAD ? 0 : 1);
        if (r != -1)
        {
          if (option (OPTRESOLVE))
index ef3cf01a4ae52d602cb52f32456e32914b8cf965..85d38b5f44f57053c295becb6d9aead903a38c0e 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1367,8 +1367,10 @@ int mutt_pattern_func (int op, char *prompt)
       {
        switch (op)
        {
+          case MUTT_UNDELETE:
+            mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], MUTT_PURGE,
+                           0);
          case MUTT_DELETE:
-         case MUTT_UNDELETE:
            mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], MUTT_DELETE, 
                          (op == MUTT_DELETE));
            break;
index 9e19da2cd2941a8b580049c5273df5ececc4e5e8..525a72fda7d2349ba9d8c5186dbe15e049ea4e1c 100644 (file)
@@ -178,6 +178,7 @@ static HEADER *select_msg (void)
     {
       case OP_DELETE:
       case OP_UNDELETE:
+        /* should deleted draft messages be saved in the trash folder? */
        mutt_set_flag (PostContext, PostContext->hdrs[menu->current], MUTT_DELETE, (i == OP_DELETE) ? 1 : 0);
        PostCount = PostContext->msgcount - PostContext->deleted;
        if (option (OPTRESOLVE) && menu->current < menu->max - 1)
@@ -276,6 +277,7 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size
 
   /* finished with this message, so delete it. */
   mutt_set_flag (PostContext, h, MUTT_DELETE, 1);
+  mutt_set_flag (PostContext, h, MUTT_PURGE, 1);
 
   /* update the count for the status display */
   PostCount = PostContext->msgcount - PostContext->deleted;