···11-From: Cedric Duval <cedricduval@free.fr>
22-Date: Thu, 27 Feb 2014 12:27:41 +0100
33-Subject: trash-folder
44-55-With this patch, if the trash variable is set to a path (unset by default), the
66-deleted mails will be moved to a trash folder instead of being irremediably
77-purged when syncing the mailbox.
88-99-For instance, set trash="~/Mail/trash" will cause every deleted mail to go to
1010-this folder.
1111-1212-Note that the append to the trash folder doesn't occur until the resync is
1313-done. This allows you to change your mind and undo deletes, and thus the moves
1414-to the trash folder are unnecessary.
1515-1616-Notes
1717-1818- * You might also want to have a look at the purge message feature below
1919- which is related to this patch.
2020- * IMAP is now supported. To retain the previous behavior, add this to your
2121- muttrc:
2222- folder-hook ^imap:// 'unset trash'
2323-2424-FAQ
2525-2626-Every once in a while, someone asks what are the advantages of this patch over
2727-a macro based solution. Here's an attempt to answer this question:
2828-2929- * The folder history doesn't clutter up with unwanted trash entries.
3030- * Delayed move to the trash allows to change one's mind.
3131- * No need to treat the case of "normal folders" and trash folders
3232- separately with folder-hooks, and to create two sets of macros (one for
3333- the index, one for the pager).
3434- * Works not only with delete-message, but also with every deletion
3535- functions like delete-pattern, delete-thread or delete-subthread.
3636-3737-To sum up, it's more integrated and transparent to the user.
3838-3939-* Patch last synced with upstream:
4040- - Date: 2007-02-15
4141- - File: http://cedricduval.free.fr/mutt/patches/download/patch-1.5.5.1.cd.trash_folder.3.4
4242-4343-* Changes made:
4444- - Updated to 1.5.13:
4545- - structure of _mutt_save_message changed (commands.c)
4646- - context of option (OPTCONFIRMAPPEND) changed (muttlib.c)
4747- - Fixed indentation of "appended" in mutt.h.
4848-4949-Signed-off-by: Matteo F. Vescovi <mfvescovi@gmail.com>
5050-5151-Gbp-Pq: Topic features
5252----
5353- commands.c | 1 +
5454- flags.c | 19 +++++++++++++++++-
5555- globals.h | 1 +
5656- imap/message.c | 2 ++
5757- init.h | 10 ++++++++++
5858- mutt.h | 3 +++
5959- muttlib.c | 4 +++-
6060- mx.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6161- postpone.c | 3 +++
6262- 9 files changed, 103 insertions(+), 2 deletions(-)
6363-6464-diff --git a/commands.c b/commands.c
6565-index 5dbd100..7fd014b 100644
6666---- a/commands.c
6767-+++ b/commands.c
6868-@@ -720,6 +720,7 @@ int _mutt_save_message (HEADER *h, CONTEXT *ctx, int delete, int decode, int dec
6969- if (option (OPTDELETEUNTAG))
7070- mutt_set_flag (Context, h, M_TAG, 0);
7171- }
7272-+ mutt_set_flag (Context, h, M_APPENDED, 1);
7373-7474- return 0;
7575- }
7676-diff --git a/flags.c b/flags.c
7777-index f0f3d81..dfa6a50 100644
7878---- a/flags.c
7979-+++ b/flags.c
8080-@@ -65,7 +65,13 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
8181- {
8282- h->deleted = 0;
8383- update = 1;
8484-- if (upd_ctx) ctx->deleted--;
8585-+ if (upd_ctx)
8686-+ {
8787-+ ctx->deleted--;
8888-+ if (h->appended)
8989-+ ctx->appended--;
9090-+ }
9191-+ h->appended = 0; /* when undeleting, also reset the appended flag */
9292- #ifdef USE_IMAP
9393- /* see my comment above */
9494- if (ctx->magic == M_IMAP)
9595-@@ -87,6 +93,17 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
9696- }
9797- break;
9898-9999-+ case M_APPENDED:
100100-+ if (bf)
101101-+ {
102102-+ if (!h->appended)
103103-+ {
104104-+ h->appended = 1;
105105-+ if (upd_ctx) ctx->appended++;
106106-+ }
107107-+ }
108108-+ break;
109109-+
110110- case M_NEW:
111111-112112- if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN))
113113-diff --git a/globals.h b/globals.h
114114-index e77030c..6a1b8da 100644
115115---- a/globals.h
116116-+++ b/globals.h
117117-@@ -144,6 +144,7 @@ WHERE char *Tochars;
118118- WHERE char *TSStatusFormat;
119119- WHERE char *TSIconFormat;
120120- WHERE short TSSupported;
121121-+WHERE char *TrashPath;
122122- WHERE char *Username;
123123- WHERE char *Visual;
124124-125125-diff --git a/imap/message.c b/imap/message.c
126126-index 3877381..039fda6 100644
127127---- a/imap/message.c
128128-+++ b/imap/message.c
129129-@@ -884,6 +884,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
130130- if (ctx->hdrs[n]->tagged)
131131- {
132132- mutt_set_flag (ctx, ctx->hdrs[n], M_DELETE, 1);
133133-+ mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1);
134134- if (option (OPTDELETEUNTAG))
135135- mutt_set_flag (ctx, ctx->hdrs[n], M_TAG, 0);
136136- }
137137-@@ -891,6 +892,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
138138- else
139139- {
140140- mutt_set_flag (ctx, h, M_DELETE, 1);
141141-+ mutt_set_flag (ctx, h, M_APPENDED, 1);
142142- if (option (OPTDELETEUNTAG))
143143- mutt_set_flag (ctx, h, M_TAG, 0);
144144- }
145145-diff --git a/init.h b/init.h
146146-index 6b49341..d3206f9 100644
147147---- a/init.h
148148-+++ b/init.h
149149-@@ -3341,6 +3341,16 @@ struct option_t MuttVars[] = {
150150- ** provided that ``$$ts_enabled'' has been set. This string is identical in
151151- ** formatting to the one used by ``$$status_format''.
152152- */
153153-+ { "trash", DT_PATH, R_NONE, UL &TrashPath, 0 },
154154-+ /*
155155-+ ** .pp
156156-+ ** If set, this variable specifies the path of the trash folder where the
157157-+ ** mails marked for deletion will be moved, instead of being irremediably
158158-+ ** purged.
159159-+ ** .pp
160160-+ ** NOTE: When you delete a message in the trash folder, it is really
161161-+ ** deleted, so that you have a way to clean the trash.
162162-+ */
163163- #ifdef USE_SOCKET
164164- { "tunnel", DT_STR, R_NONE, UL &Tunnel, UL 0 },
165165- /*
166166-diff --git a/mutt.h b/mutt.h
167167-index f8565fa..29bb6c2 100644
168168---- a/mutt.h
169169-+++ b/mutt.h
170170-@@ -185,6 +185,7 @@ enum
171171- M_DELETE,
172172- M_UNDELETE,
173173- M_DELETED,
174174-+ M_APPENDED,
175175- M_FLAG,
176176- M_TAG,
177177- M_UNTAG,
178178-@@ -713,6 +714,7 @@ typedef struct header
179179- unsigned int mime : 1; /* has a MIME-Version header? */
180180- unsigned int flagged : 1; /* marked important? */
181181- unsigned int tagged : 1;
182182-+ unsigned int appended : 1; /* has been saved */
183183- unsigned int deleted : 1;
184184- unsigned int changed : 1;
185185- unsigned int attach_del : 1; /* has an attachment marked for deletion */
186186-@@ -885,6 +887,7 @@ typedef struct _context
187187- int new; /* how many new messages? */
188188- int unread; /* how many unread messages? */
189189- int deleted; /* how many deleted messages */
190190-+ int appended; /* how many saved messages? */
191191- int flagged; /* how many flagged messages */
192192- int msgnotreadyet; /* which msg "new" in pager, -1 if none */
193193-194194-diff --git a/muttlib.c b/muttlib.c
195195-index 02067cc..0fd9766 100644
196196---- a/muttlib.c
197197-+++ b/muttlib.c
198198-@@ -1505,7 +1505,9 @@ int mutt_save_confirm (const char *s, struct stat *st)
199199-200200- if (magic > 0 && !mx_access (s, W_OK))
201201- {
202202-- if (option (OPTCONFIRMAPPEND))
203203-+ if (option (OPTCONFIRMAPPEND) &&
204204-+ (!TrashPath || (mutt_strcmp (s, TrashPath) != 0)))
205205-+ /* if we're appending to the trash, there's no point in asking */
206206- {
207207- snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s);
208208- if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO)
209209-diff --git a/mx.c b/mx.c
210210-index 4c5cb07..c0a6d30 100644
211211---- a/mx.c
212212-+++ b/mx.c
213213-@@ -776,6 +776,53 @@ static int sync_mailbox (CONTEXT *ctx, int *index_hint)
214214- return rc;
215215- }
216216-217217-+/* move deleted mails to the trash folder */
218218-+static int trash_append (CONTEXT *ctx)
219219-+{
220220-+ CONTEXT *ctx_trash;
221221-+ int i = 0;
222222-+ struct stat st, stc;
223223-+
224224-+ if (!TrashPath || !ctx->deleted ||
225225-+ (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
226226-+ return 0;
227227-+
228228-+ for (;i < ctx->msgcount && (!ctx->hdrs[i]->deleted ||
229229-+ ctx->hdrs[i]->appended); i++);
230230-+ if (i == ctx->msgcount)
231231-+ return 0; /* nothing to be done */
232232-+
233233-+ if (mutt_save_confirm (TrashPath, &st) != 0)
234234-+ {
235235-+ mutt_error _("message(s) not deleted");
236236-+ return -1;
237237-+ }
238238-+
239239-+ if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
240240-+ && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
241241-+ return 0; /* we are in the trash folder: simple sync */
242242-+
243243-+ if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL)
244244-+ {
245245-+ for (i = 0 ; i < ctx->msgcount ; i++)
246246-+ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended
247247-+ && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1)
248248-+ {
249249-+ mx_close_mailbox (ctx_trash, NULL);
250250-+ return -1;
251251-+ }
252252-+
253253-+ mx_close_mailbox (ctx_trash, NULL);
254254-+ }
255255-+ else
256256-+ {
257257-+ mutt_error _("Can't open trash folder");
258258-+ return -1;
259259-+ }
260260-+
261261-+ return 0;
262262-+}
263263-+
264264- /* save changes and close mailbox */
265265- int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
266266- {
267267-@@ -912,6 +959,7 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
268268- if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0)
269269- {
270270- mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1);
271271-+ mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1);
272272- }
273273- else
274274- {
275275-@@ -936,6 +984,14 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
276276- return 0;
277277- }
278278-279279-+ /* copy mails to the trash before expunging */
280280-+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath))
281281-+ if (trash_append (ctx) != 0)
282282-+ {
283283-+ ctx->closing = 0;
284284-+ return -1;
285285-+ }
286286-+
287287- #ifdef USE_IMAP
288288- /* allow IMAP to preserve the deleted flag across sessions */
289289- if (ctx->magic == M_IMAP)
290290-@@ -1133,6 +1189,12 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
291291- msgcount = ctx->msgcount;
292292- deleted = ctx->deleted;
293293-294294-+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath))
295295-+ {
296296-+ if (trash_append (ctx) == -1)
297297-+ return -1;
298298-+ }
299299-+
300300- #ifdef USE_IMAP
301301- if (ctx->magic == M_IMAP)
302302- rc = imap_sync_mailbox (ctx, purge, index_hint);
303303-diff --git a/postpone.c b/postpone.c
304304-index a703161..7a4cbb1 100644
305305---- a/postpone.c
306306-+++ b/postpone.c
307307-@@ -277,6 +277,9 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size
308308- /* finished with this message, so delete it. */
309309- mutt_set_flag (PostContext, h, M_DELETE, 1);
310310-311311-+ /* and consider it saved, so that it won't be moved to the trash folder */
312312-+ mutt_set_flag (PostContext, h, M_APPENDED, 1);
313313-+
314314- /* update the count for the status display */
315315- PostCount = PostContext->msgcount - PostContext->deleted;
316316-