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