]> git.llucax.com Git - software/mutt-debian.git/blob - flags.c
upstream/528233-readonly-open.patch: open attachments in read-only (Closes: 528233)
[software/mutt-debian.git] / flags.c
1 /*
2  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
3  * 
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  * 
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  * 
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */ 
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24 #include "mutt_curses.h"
25 #include "sort.h"
26 #include "mx.h"
27
28 void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
29 {
30   int changed = h->changed;
31   int deleted = ctx->deleted;
32   int tagged = ctx->tagged;
33   int flagged = ctx->flagged;
34   int update = 0;
35
36   if (ctx->readonly && flag != M_TAG)
37     return; /* don't modify anything if we are read-only */
38
39   switch (flag)
40   {
41     case M_DELETE:
42
43       if (!mutt_bit_isset(ctx->rights,M_ACL_DELETE))
44         return;
45
46       if (bf)
47       {
48         if (!h->deleted && !ctx->readonly)
49         {
50           h->deleted = 1;
51           update = 1;
52           if (upd_ctx) ctx->deleted++;
53 #ifdef USE_IMAP
54           /* deleted messages aren't treated as changed elsewhere so that the
55            * purge-on-sync option works correctly. This isn't applicable here */
56           if (ctx && ctx->magic == M_IMAP)
57           {
58             h->changed = 1;
59             if (upd_ctx) ctx->changed = 1;
60           }
61 #endif
62         }
63       }
64       else if (h->deleted)
65       {
66         h->deleted = 0;
67         update = 1;
68         if (upd_ctx) ctx->deleted--;
69 #ifdef USE_IMAP
70         /* see my comment above */
71         if (ctx->magic == M_IMAP) 
72         {
73           h->changed = 1;
74           if (upd_ctx) ctx->changed = 1;
75         }
76 #endif
77         /* 
78          * If the user undeletes a message which is marked as
79          * "trash" in the maildir folder on disk, the folder has
80          * been changed, and is marked accordingly.  However, we do
81          * _not_ mark the message itself changed, because trashing
82          * is checked in specific code in the maildir folder
83          * driver. 
84          */
85         if (ctx->magic == M_MAILDIR && upd_ctx && h->trash)
86           ctx->changed = 1;
87       }
88       break;
89
90     case M_NEW:
91
92       if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN))
93         return;
94
95       if (bf)
96       {
97         if (h->read || h->old)
98         {
99           update = 1;
100           h->old = 0;
101           if (upd_ctx) ctx->new++;
102           if (h->read)
103           {
104             h->read = 0;
105             if (upd_ctx) ctx->unread++;
106           }
107           h->changed = 1;
108           if (upd_ctx) ctx->changed = 1;
109         }
110       }
111       else if (!h->read)
112       {
113         update = 1;
114         if (!h->old)
115           if (upd_ctx) ctx->new--;
116         h->read = 1;
117         if (upd_ctx) ctx->unread--;
118         h->changed = 1;
119         if (upd_ctx) ctx->changed = 1;
120       }
121       break;
122
123     case M_OLD:
124
125       if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN))
126         return;
127
128       if (bf)
129       {
130         if (!h->old)
131         {
132           update = 1;
133           h->old = 1;
134           if (!h->read)
135             if (upd_ctx) ctx->new--;
136           h->changed = 1;
137           if (upd_ctx) ctx->changed = 1;
138         }
139       }
140       else if (h->old)
141       {
142         update = 1;
143         h->old = 0;
144         if (!h->read)
145           if (upd_ctx) ctx->new++;
146         h->changed = 1;
147         if (upd_ctx) ctx->changed = 1;
148       }
149       break;
150
151     case M_READ:
152
153       if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN))
154         return;
155
156       if (bf)
157       {
158         if (!h->read)
159         {
160           update = 1;
161           h->read = 1;
162           if (upd_ctx) ctx->unread--;
163           if (!h->old)
164             if (upd_ctx) ctx->new--;
165           h->changed = 1;
166           if (upd_ctx) ctx->changed = 1;
167         }
168       }
169       else if (h->read)
170       {
171         update = 1;
172         h->read = 0;
173         if (upd_ctx) ctx->unread++;
174         if (!h->old)
175           if (upd_ctx) ctx->new++;
176         h->changed = 1;
177         if (upd_ctx) ctx->changed = 1;
178       }
179       break;
180
181     case M_REPLIED:
182
183       if (!mutt_bit_isset(ctx->rights,M_ACL_WRITE))
184         return;
185
186       if (bf)
187       {
188         if (!h->replied)
189         {
190           update = 1;
191           h->replied = 1;
192           if (!h->read)
193           {
194             h->read = 1;
195             if (upd_ctx) ctx->unread--;
196             if (!h->old)
197               if (upd_ctx) ctx->new--;
198           }
199           h->changed = 1;
200           if (upd_ctx) ctx->changed = 1;
201         }
202       }
203       else if (h->replied)
204       {
205         update = 1;
206         h->replied = 0;
207         h->changed = 1;
208         if (upd_ctx) ctx->changed = 1;
209       }
210       break;
211
212     case M_FLAG:
213
214       if (!mutt_bit_isset(ctx->rights,M_ACL_WRITE))
215         return;
216
217       if (bf)
218       {
219         if (!h->flagged)
220         {
221           update = 1;
222           h->flagged = bf;
223           if (upd_ctx) ctx->flagged++;
224           h->changed = 1;
225           if (upd_ctx) ctx->changed = 1;
226         }
227       }
228       else if (h->flagged)
229       {
230         update = 1;
231         h->flagged = 0;
232         if (upd_ctx) ctx->flagged--;
233         h->changed = 1;
234         if (upd_ctx) ctx->changed = 1;
235       }
236       break;
237
238     case M_TAG:
239       if (bf)
240       {
241         if (!h->tagged)
242         {
243           update = 1;
244           h->tagged = 1;
245           if (upd_ctx) ctx->tagged++;
246         }
247       }
248       else if (h->tagged)
249       {
250         update = 1;
251         h->tagged = 0;
252         if (upd_ctx) ctx->tagged--;
253       }
254       break;
255   }
256
257   if (update)
258     mutt_set_header_color(ctx, h);
259
260   /* if the message status has changed, we need to invalidate the cached
261    * search results so that any future search will match the current status
262    * of this message and not what it was at the time it was last searched.
263    */
264   if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged || flagged != ctx->flagged))
265     h->searched = 0;
266 }
267
268 void mutt_tag_set_flag (int flag, int bf)
269 {
270   int j;
271
272   for (j = 0; j < Context->vcount; j++)
273     if (Context->hdrs[Context->v2r[j]]->tagged)
274       mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], flag, bf);
275 }
276 int mutt_thread_set_flag (HEADER *hdr, int flag, int bf, int subthread)
277 {
278   THREAD *start, *cur = hdr->thread;
279   
280   if ((Sort & SORT_MASK) != SORT_THREADS)
281   {
282     mutt_error _("Threading is not enabled.");
283     return (-1);
284   }
285
286   if (!subthread)
287     while (cur->parent)
288       cur = cur->parent;
289   start = cur;
290   
291   if (cur->message)
292     mutt_set_flag (Context, cur->message, flag, bf);
293
294   if ((cur = cur->child) == NULL)
295     return (0);
296
297   FOREVER
298   {
299     if (cur->message)
300       mutt_set_flag (Context, cur->message, flag, bf);
301
302     if (cur->child)
303       cur = cur->child;
304     else if (cur->next)
305       cur = cur->next;
306     else 
307     {
308       while (!cur->next)
309       {
310         cur = cur->parent;
311         if (cur == start)
312           return (0);
313       }
314       cur = cur->next;
315     }
316   }
317   /* not reached */
318 }
319
320 int mutt_change_flag (HEADER *h, int bf)
321 {
322   int i, flag;
323   event_t event;
324
325   mvprintw (LINES - 1, 0, "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
326   clrtoeol ();
327
328   event = mutt_getch();
329   i = event.ch;
330   if (i < 0)
331   {
332     CLEARLINE (LINES-1);
333     return (-1);
334   }
335
336   CLEARLINE (LINES-1);
337
338   switch (i)
339   {
340     case 'd':
341     case 'D':
342       flag = M_DELETE;
343       break;
344
345     case 'N':
346     case 'n':
347       flag = M_NEW;
348       break;
349
350     case 'o':
351     case 'O':
352       if (h)
353         mutt_set_flag (Context, h, M_READ, !bf);
354       else
355         mutt_tag_set_flag (M_READ, !bf);
356       flag = M_OLD;
357       break;
358
359     case 'r':
360     case 'R':
361       flag = M_REPLIED;
362       break;
363
364     case '*':
365       flag = M_TAG;
366       break;
367
368     case '!':
369       flag = M_FLAG;
370       break;
371
372     default:
373       BEEP ();
374       return (-1);
375   }
376
377   if (h)
378     mutt_set_flag (Context, h, flag, bf);
379   else
380     mutt_tag_set_flag (flag, bf);
381
382   return 0;
383 }