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