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.
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);
}
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++;
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))
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))
}
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))
{
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;
WHERE char *Status;
WHERE char *Tempdir;
WHERE char *Tochars;
+WHERE char *TrashPath;
WHERE char *TSStatusFormat;
WHERE char *TSIconFormat;
WHERE short TSSupported;
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);
}
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);
}
** 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
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 */
MUTT_UNREAD,
MUTT_DELETE,
MUTT_UNDELETE,
+ MUTT_PURGE,
MUTT_DELETED,
MUTT_FLAG,
MUTT_TAG,
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;
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)
{
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
{
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)
if (!purge)
{
for (i = 0; i < ctx->msgcount; i++)
+ {
ctx->hdrs[i]->deleted = 0;
+ ctx->hdrs[i]->purge = 0;
+ }
ctx->deleted = 0;
}
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;
}
}
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);
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))
{
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))
{
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;
{
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)
/* 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;