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