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