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