NeoMutt  2020-06-26-89-g172cd3
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, int flag, bool bf, bool upd_mbox)
 Set a flag on an email. More...
 
void mutt_emails_set_flag (struct Mailbox *m, struct EmailList *el, int flag, bool bf)
 Set flag on messages. More...
 
int mutt_thread_set_flag (struct Email *e, int 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,
int  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.

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

◆ mutt_emails_set_flag()

void mutt_emails_set_flag ( struct Mailbox m,
struct EmailList *  el,
int  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 353 of file flags.c.

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

◆ mutt_thread_set_flag()

int mutt_thread_set_flag ( struct Email e,
int  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 374 of file flags.c.

375 {
376  struct MuttThread *start = NULL;
377  struct MuttThread *cur = e->thread;
378 
379  if ((C_Sort & SORT_MASK) != SORT_THREADS)
380  {
381  mutt_error(_("Threading is not enabled"));
382  return -1;
383  }
384 
385  if (!subthread)
386  while (cur->parent)
387  cur = cur->parent;
388  start = cur;
389 
390  if (cur->message && (cur != e->thread))
391  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
392 
393  cur = cur->child;
394  if (!cur)
395  goto done;
396 
397  while (true)
398  {
399  if (cur->message && (cur != e->thread))
400  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
401 
402  if (cur->child)
403  cur = cur->child;
404  else if (cur->next)
405  cur = cur->next;
406  else
407  {
408  while (!cur->next)
409  {
410  cur = cur->parent;
411  if (cur == start)
412  goto done;
413  }
414  cur = cur->next;
415  }
416  }
417 done:
418  cur = e->thread;
419  if (cur->message)
420  mutt_set_flag(Context->mailbox, cur->message, flag, bf);
421  return 0;
422 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The "current" mailbox.
Definition: context.h:37
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:68
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
#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:58
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
Sort by email threads.
Definition: sort2.h:56
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:85
+ 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 432 of file flags.c.

433 {
434  if (!m || !el || STAILQ_EMPTY(el))
435  return -1;
436 
437  int flag;
438  struct KeyEvent event;
439 
441  "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
443  mutt_refresh();
444 
445  do
446  {
447  event = mutt_getch();
448  } while (event.ch == -2);
449  int i = event.ch;
450  if (i < 0)
451  {
453  return -1;
454  }
455 
457 
458  switch (i)
459  {
460  case 'd':
461  case 'D':
462  if (!bf)
463  mutt_emails_set_flag(m, el, MUTT_PURGE, bf);
464  flag = MUTT_DELETE;
465  break;
466 
467  case 'N':
468  case 'n':
469  flag = MUTT_NEW;
470  break;
471 
472  case 'o':
473  case 'O':
474  mutt_emails_set_flag(m, el, MUTT_READ, !bf);
475  flag = MUTT_OLD;
476  break;
477 
478  case 'r':
479  case 'R':
480  flag = MUTT_REPLIED;
481  break;
482 
483  case '*':
484  flag = MUTT_TAG;
485  break;
486 
487  case '!':
488  flag = MUTT_FLAG;
489  break;
490 
491  default:
492  mutt_beep(false);
493  return -1;
494  }
495 
496  mutt_emails_set_flag(m, el, flag, bf);
497  return 0;
498 }
void mutt_emails_set_flag(struct Mailbox *m, struct EmailList *el, int flag, bool bf)
Set flag on messages.
Definition: flags.c:353
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:216
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
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:97
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:194
Old messages.
Definition: mutt.h:94
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:106
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:61
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:187
#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:395
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function: