NeoMutt  2021-02-05
Teaching an old dog new tricks
DOXYGEN
flags.c File Reference

Manipulate the flags in an email header. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "context.h"
#include "index.h"
#include "keymap.h"
#include "mutt_globals.h"
#include "mutt_menu.h"
#include "protos.h"
#include "sort.h"
+ Include dependency graph for flags.c:

Go to the source code of this file.

Functions

void mutt_set_flag_update (struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
 Set a flag on an email. More...
 
void mutt_emails_set_flag (struct Mailbox *m, struct EmailList *el, enum MessageType flag, bool bf)
 Set flag on messages. More...
 
int mutt_thread_set_flag (struct Email *e, enum MessageType flag, bool bf, bool subthread)
 Set a flag on an entire thread. More...
 
int mutt_change_flag (struct Mailbox *m, struct EmailList *el, bool bf)
 Change the flag on a Message. More...
 

Detailed Description

Manipulate the flags in an email header.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file flags.c.

Function Documentation

◆ mutt_set_flag_update()

void mutt_set_flag_update ( struct Mailbox m,
struct Email e,
enum MessageType  flag,
bool  bf,
bool  upd_mbox 
)

Set a flag on an email.

Parameters
mMailbox
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
upd_mboxtrue: update the Mailbox

Definition at line 54 of file flags.c.

56 {
57  if (!m || !e)
58  return;
59 
60  bool changed = e->changed;
61  int deleted = m->msg_deleted;
62  int tagged = m->msg_tagged;
63  int flagged = m->msg_flagged;
64  int update = false;
65 
66  if (m->readonly && (flag != MUTT_TAG))
67  return; /* don't modify anything if we are read-only */
68 
69  switch (flag)
70  {
71  case MUTT_DELETE:
72 
73  if (!(m->rights & MUTT_ACL_DELETE))
74  return;
75 
76  if (bf)
77  {
78  if (!e->deleted && !m->readonly && (!e->flagged || !C_FlagSafe))
79  {
80  e->deleted = true;
81  update = true;
82  if (upd_mbox)
83  m->msg_deleted++;
84 #ifdef USE_IMAP
85  /* deleted messages aren't treated as changed elsewhere so that the
86  * purge-on-sync option works correctly. This isn't applicable here */
87  if (m->type == MUTT_IMAP)
88  {
89  e->changed = true;
90  if (upd_mbox)
91  m->changed = true;
92  }
93 #endif
94  }
95  }
96  else if (e->deleted)
97  {
98  e->deleted = false;
99  update = true;
100  if (upd_mbox)
101  m->msg_deleted--;
102 #ifdef USE_IMAP
103  /* see my comment above */
104  if (m->type == MUTT_IMAP)
105  {
106  e->changed = true;
107  if (upd_mbox)
108  m->changed = true;
109  }
110 #endif
111  /* If the user undeletes a message which is marked as
112  * "trash" in the maildir folder on disk, the folder has
113  * been changed, and is marked accordingly. However, we do
114  * _not_ mark the message itself changed, because trashing
115  * is checked in specific code in the maildir folder
116  * driver. */
117  if ((m->type == MUTT_MAILDIR) && upd_mbox && e->trash)
118  m->changed = true;
119  }
120  break;
121 
122  case MUTT_PURGE:
123 
124  if (!(m->rights & MUTT_ACL_DELETE))
125  return;
126 
127  if (bf)
128  {
129  if (!e->purge && !m->readonly)
130  e->purge = true;
131  }
132  else if (e->purge)
133  e->purge = false;
134  break;
135 
136  case MUTT_NEW:
137 
138  if (!(m->rights & MUTT_ACL_SEEN))
139  return;
140 
141  if (bf)
142  {
143  if (e->read || e->old)
144  {
145  update = true;
146  e->old = false;
147  if (upd_mbox)
148  m->msg_new++;
149  if (e->read)
150  {
151  e->read = false;
152  if (upd_mbox)
153  m->msg_unread++;
154  }
155  e->changed = true;
156  if (upd_mbox)
157  m->changed = true;
158  }
159  }
160  else if (!e->read)
161  {
162  update = true;
163  if (!e->old)
164  if (upd_mbox)
165  m->msg_new--;
166  e->read = true;
167  if (upd_mbox)
168  m->msg_unread--;
169  e->changed = true;
170  if (upd_mbox)
171  m->changed = true;
172  }
173  break;
174 
175  case MUTT_OLD:
176 
177  if (!(m->rights & MUTT_ACL_SEEN))
178  return;
179 
180  if (bf)
181  {
182  if (!e->old)
183  {
184  update = true;
185  e->old = true;
186  if (!e->read)
187  if (upd_mbox)
188  m->msg_new--;
189  e->changed = true;
190  if (upd_mbox)
191  m->changed = true;
192  }
193  }
194  else if (e->old)
195  {
196  update = true;
197  e->old = false;
198  if (!e->read)
199  if (upd_mbox)
200  m->msg_new++;
201  e->changed = true;
202  if (upd_mbox)
203  m->changed = true;
204  }
205  break;
206 
207  case MUTT_READ:
208 
209  if (!(m->rights & MUTT_ACL_SEEN))
210  return;
211 
212  if (bf)
213  {
214  if (!e->read)
215  {
216  update = true;
217  e->read = true;
218  if (upd_mbox)
219  m->msg_unread--;
220  if (!e->old)
221  if (upd_mbox)
222  m->msg_new--;
223  e->changed = true;
224  if (upd_mbox)
225  m->changed = true;
226  }
227  }
228  else if (e->read)
229  {
230  update = true;
231  e->read = false;
232  if (upd_mbox)
233  m->msg_unread++;
234  if (!e->old)
235  if (upd_mbox)
236  m->msg_new++;
237  e->changed = true;
238  if (upd_mbox)
239  m->changed = true;
240  }
241  break;
242 
243  case MUTT_REPLIED:
244 
245  if (!(m->rights & MUTT_ACL_WRITE))
246  return;
247 
248  if (bf)
249  {
250  if (!e->replied)
251  {
252  update = true;
253  e->replied = true;
254  if (!e->read)
255  {
256  e->read = true;
257  if (upd_mbox)
258  m->msg_unread--;
259  if (!e->old)
260  if (upd_mbox)
261  m->msg_new--;
262  }
263  e->changed = true;
264  if (upd_mbox)
265  m->changed = true;
266  }
267  }
268  else if (e->replied)
269  {
270  update = true;
271  e->replied = false;
272  e->changed = true;
273  if (upd_mbox)
274  m->changed = true;
275  }
276  break;
277 
278  case MUTT_FLAG:
279 
280  if (!(m->rights & MUTT_ACL_WRITE))
281  return;
282 
283  if (bf)
284  {
285  if (!e->flagged)
286  {
287  update = true;
288  e->flagged = bf;
289  if (upd_mbox)
290  m->msg_flagged++;
291  e->changed = true;
292  if (upd_mbox)
293  m->changed = true;
294  }
295  }
296  else if (e->flagged)
297  {
298  update = true;
299  e->flagged = false;
300  if (upd_mbox)
301  m->msg_flagged--;
302  e->changed = true;
303  if (upd_mbox)
304  m->changed = true;
305  }
306  break;
307 
308  case MUTT_TAG:
309  if (bf)
310  {
311  if (!e->tagged)
312  {
313  update = true;
314  e->tagged = true;
315  if (upd_mbox)
316  m->msg_tagged++;
317  }
318  }
319  else if (e->tagged)
320  {
321  update = true;
322  e->tagged = false;
323  if (upd_mbox)
324  m->msg_tagged--;
325  }
326  break;
327 
328  default:
329  break;
330  }
331 
332  if (update)
333  {
334  mutt_set_header_color(m, e);
335  }
336 
337  /* if the message status has changed, we need to invalidate the cached
338  * search results so that any future search will match the current status
339  * of this message and not what it was at the time it was last searched. */
340  if (e->searched && ((changed != e->changed) || (deleted != m->msg_deleted) ||
341  (tagged != m->msg_tagged) || (flagged != m->msg_flagged)))
342  {
343  e->searched = false;
344  }
345 }
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
Flagged messages.
Definition: mutt.h:102
bool changed
Email has been edited.
Definition: email.h:48
Messages to be purged (bypass trash)
Definition: mutt.h:100
bool searched
Email has been searched.
Definition: email.h:67
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Messages that have been replied to.
Definition: mutt.h:95
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:60
Old messages.
Definition: mutt.h:94
Messages to be deleted.
Definition: mutt.h:98
Tagged messages.
Definition: mutt.h:103
New messages.
Definition: mutt.h:93
Messages that have been read.
Definition: mutt.h:96
WHERE bool C_FlagSafe
Config: Protect flagged messages from deletion.
Definition: mutt_globals.h:146
bool purge
Skip trash folder when deleting.
Definition: email.h:46
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
void mutt_set_header_color(struct Mailbox *m, struct Email *e)
Select a colour for a message.
Definition: index.c:3962
bool flagged
Marked important?
Definition: email.h:43
int msg_new
Number of new messages.
Definition: mailbox.h:95
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_emails_set_flag()

void mutt_emails_set_flag ( struct Mailbox m,
struct EmailList *  el,
enum MessageType  flag,
bool  bf 
)

Set flag on messages.

Parameters
mMailbox
elList of Emails to flag
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag

Definition at line 354 of file flags.c.

356 {
357  if (!m || !el || STAILQ_EMPTY(el))
358  return;
359 
360  struct EmailNode *en = NULL;
361  STAILQ_FOREACH(en, el, entries)
362  {
363  mutt_set_flag(m, en->email, flag, bf);
364  }
365 }
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Email * email
Email in the list.
Definition: email.h:127
#define STAILQ_EMPTY(head)
Definition: queue.h:345
List of Emails.
Definition: email.h:125
+ Here is the caller graph for this function:

◆ mutt_thread_set_flag()

int mutt_thread_set_flag ( struct Email e,
enum MessageType  flag,
bool  bf,
bool  subthread 
)

Set a flag on an entire thread.

Parameters
eEmail
flagFlag to set, e.g. MUTT_DELETE
bftrue: set the flag; false: clear the flag
subthreadIf true apply to all of the thread
Return values
0Success
-1Failure

Definition at line 376 of file flags.c.

377 {
378  struct MuttThread *start = NULL;
379  struct MuttThread *cur = e->thread;
380 
381  if ((C_Sort & SORT_MASK) != SORT_THREADS)
382  {
383  mutt_error(_("Threading is not enabled"));
384  return -1;
385  }
386 
387  if (!subthread)
388  while (cur->parent)
389  cur = cur->parent;
390  start = cur;
391 
392  if (cur->message && (cur != e->thread))
393  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
394 
395  cur = cur->child;
396  if (!cur)
397  goto done;
398 
399  while (true)
400  {
401  if (cur->message && (cur != e->thread))
402  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
403 
404  if (cur->child)
405  cur = cur->child;
406  else if (cur->next)
407  cur = cur->next;
408  else
409  {
410  while (!cur->next)
411  {
412  cur = cur->parent;
413  if (cur == start)
414  goto done;
415  }
416  cur = cur->next;
417  }
418  }
419 done:
420  cur = e->thread;
421  if (cur->message)
422  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
423  return 0;
424 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The "current" mailbox.
Definition: context.h:38
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
#define _(a)
Definition: message.h:28
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct Mailbox * mailbox
Definition: context.h:50
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
Sort by email threads.
Definition: sort2.h:51
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
An Email conversation.
Definition: thread.h:34
#define mutt_error(...)
Definition: logging.h:84
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
+ Here is the caller graph for this function:

◆ mutt_change_flag()

int mutt_change_flag ( struct Mailbox m,
struct EmailList *  el,
bool  bf 
)

Change the flag on a Message.

Parameters
mMailbox
elList of Emails to change
bftrue: set the flag; false: clear the flag
Return values
0Success
-1Failure

Definition at line 434 of file flags.c.

435 {
436  if (!m || !el || STAILQ_EMPTY(el))
437  return -1;
438 
439  enum MessageType flag = MUTT_NONE;
440  struct KeyEvent event;
441 
443  "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
445  mutt_refresh();
446 
447  do
448  {
449  event = mutt_getch();
450  } while (event.ch == -2);
451  int i = event.ch;
452  if (i < 0)
453  {
455  return -1;
456  }
457 
459 
460  switch (i)
461  {
462  case 'd':
463  case 'D':
464  if (!bf)
465  mutt_emails_set_flag(m, el, MUTT_PURGE, bf);
466  flag = MUTT_DELETE;
467  break;
468 
469  case 'N':
470  case 'n':
471  flag = MUTT_NEW;
472  break;
473 
474  case 'o':
475  case 'O':
476  mutt_emails_set_flag(m, el, MUTT_READ, !bf);
477  flag = MUTT_OLD;
478  break;
479 
480  case 'r':
481  case 'R':
482  flag = MUTT_REPLIED;
483  break;
484 
485  case '*':
486  flag = MUTT_TAG;
487  break;
488 
489  case '!':
490  flag = MUTT_FLAG;
491  break;
492 
493  default:
494  mutt_beep(false);
495  return -1;
496  }
497 
498  mutt_emails_set_flag(m, el, flag, bf);
499  return 0;
500 }
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, enum MessageType flag, bool bf)
Set flag on messages.
Definition: flags.c:354
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
No messages.
Definition: mutt.h:92
Messages to be purged (bypass trash)
Definition: mutt.h:100
Messages that have been replied to.
Definition: mutt.h:95
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
MessageType
To set flags or match patterns.
Definition: mutt.h:89
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:232
Old messages.
Definition: mutt.h:94
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
Messages to be deleted.
Definition: mutt.h:98
Tagged messages.
Definition: mutt.h:103
New messages.
Definition: mutt.h:93
Messages that have been read.
Definition: mutt.h:96
An event such as a keypress.
Definition: keymap.h:63
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:189
#define STAILQ_EMPTY(head)
Definition: queue.h:345
int mutt_window_mvprintw(struct MuttWindow *win, int col, int row, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:415
+ Here is the call graph for this function:
+ Here is the caller graph for this function: