NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
flags.c File Reference

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

#include "config.h"
#include <stdbool.h>
#include <stdio.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 "color/lib.h"
#include "index/lib.h"
#include "key/lib.h"
#include "mutt_thread.h"
#include "protos.h"
+ Include dependency graph for flags.c:

Go to the source code of this file.

Functions

void mutt_set_flag (struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
 Set a flag on an email.
 
void mutt_emails_set_flag (struct Mailbox *m, struct EmailArray *ea, enum MessageType flag, bool bf)
 Set flag on messages.
 
int mutt_thread_set_flag (struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool subthread)
 Set a flag on an entire thread.
 
int mw_change_flag (struct Mailbox *m, struct EmailArray *ea, bool bf)
 Change the flag on a Message -.
 

Detailed Description

Manipulate the flags in an email header.

Authors
  • Michael R. Elkins
  • Richard Russon
  • Fabrice Bellet
  • Mehdi Abaakouk
  • Pietro Cerutti

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()

void mutt_set_flag ( 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 56 of file flags.c.

58{
59 if (!m || !e)
60 return;
61
62 bool changed = e->changed;
63 int deleted = m->msg_deleted;
64 int tagged = m->msg_tagged;
65 int flagged = m->msg_flagged;
66 int update = false;
67
68 if (m->readonly && (flag != MUTT_TAG))
69 return; /* don't modify anything if we are read-only */
70
71 switch (flag)
72 {
73 case MUTT_DELETE:
74 {
75 if (!(m->rights & MUTT_ACL_DELETE))
76 return;
77
78 if (bf)
79 {
80 const bool c_flag_safe = cs_subset_bool(NeoMutt->sub, "flag_safe");
81 if (!e->deleted && !m->readonly && (!e->flagged || !c_flag_safe))
82 {
83 e->deleted = true;
84 update = true;
85 if (upd_mbox)
86 m->msg_deleted++;
87 /* deleted messages aren't treated as changed elsewhere so that the
88 * purge-on-sync option works correctly. This isn't applicable here */
89 if (m->type == MUTT_IMAP)
90 {
91 e->changed = true;
92 if (upd_mbox)
93 m->changed = true;
94 }
95 }
96 }
97 else if (e->deleted)
98 {
99 e->deleted = false;
100 update = true;
101 if (upd_mbox)
102 m->msg_deleted--;
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 /* 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 {
133 e->purge = false;
134 }
135 break;
136 }
137 case MUTT_NEW:
138 {
139 if (!(m->rights & MUTT_ACL_SEEN))
140 return;
141
142 if (bf)
143 {
144 if (e->read || e->old)
145 {
146 update = true;
147 e->old = false;
148 if (upd_mbox)
149 m->msg_new++;
150 if (e->read)
151 {
152 e->read = false;
153 if (upd_mbox)
154 m->msg_unread++;
155 }
156 e->changed = true;
157 if (upd_mbox)
158 m->changed = true;
159 }
160 }
161 else if (!e->read)
162 {
163 update = true;
164 if (!e->old)
165 if (upd_mbox)
166 m->msg_new--;
167 e->read = true;
168 if (upd_mbox)
169 m->msg_unread--;
170 e->changed = true;
171 if (upd_mbox)
172 m->changed = true;
173 }
174 break;
175 }
176 case MUTT_OLD:
177 {
178 if (!(m->rights & MUTT_ACL_SEEN))
179 return;
180
181 if (bf)
182 {
183 if (!e->old)
184 {
185 update = true;
186 e->old = true;
187 if (!e->read)
188 if (upd_mbox)
189 m->msg_new--;
190 e->changed = true;
191 if (upd_mbox)
192 m->changed = true;
193 }
194 }
195 else if (e->old)
196 {
197 update = true;
198 e->old = false;
199 if (!e->read)
200 if (upd_mbox)
201 m->msg_new++;
202 e->changed = true;
203 if (upd_mbox)
204 m->changed = true;
205 }
206 break;
207 }
208 case MUTT_READ:
209 {
210 if (!(m->rights & MUTT_ACL_SEEN))
211 return;
212
213 if (bf)
214 {
215 if (!e->read)
216 {
217 update = true;
218 e->read = true;
219 if (upd_mbox)
220 m->msg_unread--;
221 if (!e->old)
222 if (upd_mbox)
223 m->msg_new--;
224 e->changed = true;
225 if (upd_mbox)
226 m->changed = true;
227 }
228 }
229 else if (e->read)
230 {
231 update = true;
232 e->read = false;
233 if (upd_mbox)
234 m->msg_unread++;
235 if (!e->old)
236 if (upd_mbox)
237 m->msg_new++;
238 e->changed = true;
239 if (upd_mbox)
240 m->changed = true;
241 }
242 break;
243 }
244 case MUTT_REPLIED:
245 {
246 if (!(m->rights & MUTT_ACL_WRITE))
247 return;
248
249 if (bf)
250 {
251 if (!e->replied)
252 {
253 update = true;
254 e->replied = true;
255 if (!e->read)
256 {
257 e->read = true;
258 if (upd_mbox)
259 m->msg_unread--;
260 if (!e->old)
261 if (upd_mbox)
262 m->msg_new--;
263 }
264 e->changed = true;
265 if (upd_mbox)
266 m->changed = true;
267 }
268 }
269 else if (e->replied)
270 {
271 update = true;
272 e->replied = false;
273 e->changed = true;
274 if (upd_mbox)
275 m->changed = true;
276 }
277 break;
278 }
279 case MUTT_FLAG:
280 {
281 if (!(m->rights & MUTT_ACL_WRITE))
282 return;
283
284 if (bf)
285 {
286 if (!e->flagged)
287 {
288 update = true;
289 e->flagged = bf;
290 if (upd_mbox)
291 m->msg_flagged++;
292 e->changed = true;
293 if (upd_mbox)
294 m->changed = true;
295 }
296 }
297 else if (e->flagged)
298 {
299 update = true;
300 e->flagged = false;
301 if (upd_mbox)
302 m->msg_flagged--;
303 e->changed = true;
304 if (upd_mbox)
305 m->changed = true;
306 }
307 break;
308 }
309 case MUTT_TAG:
310 {
311 if (bf)
312 {
313 if (!e->tagged)
314 {
315 update = true;
316 e->tagged = true;
317 if (upd_mbox)
318 m->msg_tagged++;
319 }
320 }
321 else if (e->tagged)
322 {
323 update = true;
324 e->tagged = false;
325 if (upd_mbox)
326 m->msg_tagged--;
327 }
328 break;
329 }
330 default:
331 {
332 break;
333 }
334 }
335
336 if (update)
337 {
338 email_set_color(m, e);
339 struct EventMailbox ev_m = { m };
341 }
342
343 /* if the message status has changed, we need to invalidate the cached
344 * search results so that any future search will match the current status
345 * of this message and not what it was at the time it was last searched. */
346 if (e->searched && ((changed != e->changed) || (deleted != m->msg_deleted) ||
347 (tagged != m->msg_tagged) || (flagged != m->msg_flagged)))
348 {
349 e->searched = false;
350 }
351}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition mailbox.h:185
#define MUTT_ACL_DELETE
Delete a message.
Definition mailbox.h:63
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition mailbox.h:71
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition mailbox.h:48
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition mailbox.h:70
void email_set_color(struct Mailbox *m, struct Email *e)
Select an Index colour for an Email.
Definition dlg_index.c:1405
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
@ MUTT_READ
Messages that have been read.
Definition mutt.h:73
@ MUTT_OLD
Old messages.
Definition mutt.h:71
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:77
@ MUTT_TAG
Tagged messages.
Definition mutt.h:80
@ MUTT_FLAG
Flagged messages.
Definition mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:75
@ MUTT_NEW
New messages.
Definition mutt.h:70
@ MUTT_REPLIED
Messages that have been replied to.
Definition mutt.h:72
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition notify_type.h:49
bool searched
Email has been searched.
Definition email.h:105
bool read
Email is read.
Definition email.h:50
bool purge
Skip trash folder when deleting.
Definition email.h:79
bool old
Email is seen, but unread.
Definition email.h:49
bool changed
Email has been edited.
Definition email.h:77
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
bool deleted
Email is deleted.
Definition email.h:78
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition email.h:53
bool tagged
Email is tagged.
Definition email.h:107
An Event that happened to a Mailbox.
Definition mailbox.h:199
bool changed
Mailbox has been modified.
Definition mailbox.h:110
int msg_new
Number of new messages.
Definition mailbox.h:92
AclFlags rights
ACL bits, see AclFlags.
Definition mailbox.h:119
enum MailboxType type
Mailbox type.
Definition mailbox.h:102
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition mailbox.h:145
int msg_deleted
Number of deleted messages.
Definition mailbox.h:93
int msg_flagged
Number of flagged messages.
Definition mailbox.h:90
bool readonly
Don't allow changes to the mailbox.
Definition mailbox.h:116
int msg_tagged
How many messages are tagged?
Definition mailbox.h:94
int msg_unread
Number of unread messages.
Definition mailbox.h:89
Container for Accounts, Notifications.
Definition neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
+ 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 EmailArray * ea,
enum MessageType flag,
bool bf )

Set flag on messages.

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

Definition at line 360 of file flags.c.

362{
363 if (!m || !ea || ARRAY_EMPTY(ea))
364 return;
365
366 struct Email **ep = NULL;
367 ARRAY_FOREACH(ep, ea)
368 {
369 struct Email *e = *ep;
370 mutt_set_flag(m, e, flag, bf, true);
371 }
372}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:56
The envelope/body of an email.
Definition email.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_set_flag()

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

Set a flag on an entire thread.

Parameters
mMailbox
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 384 of file flags.c.

386{
387 struct MuttThread *start = NULL;
388 struct MuttThread *cur = e->thread;
389
390 if (!mutt_using_threads())
391 {
392 mutt_error(_("Threading is not enabled"));
393 return -1;
394 }
395
396 if (!subthread)
397 while (cur->parent)
398 cur = cur->parent;
399
400 start = cur;
401
402 if (cur->message && (cur != e->thread))
403 mutt_set_flag(m, cur->message, flag, bf, true);
404
405 cur = cur->child;
406 if (!cur)
407 goto done;
408
409 while (true)
410 {
411 if (cur->message && (cur != e->thread))
412 mutt_set_flag(m, cur->message, flag, bf, true);
413
414 if (cur->child)
415 {
416 cur = cur->child;
417 }
418 else if (cur->next)
419 {
420 cur = cur->next;
421 }
422 else
423 {
424 while (!cur->next)
425 {
426 cur = cur->parent;
427 if (cur == start)
428 goto done;
429 }
430 cur = cur->next;
431 }
432 }
433done:
434 cur = e->thread;
435 if (cur->message)
436 mutt_set_flag(m, cur->message, flag, bf, true);
437 return 0;
438}
#define mutt_error(...)
Definition logging2.h:93
#define _(a)
Definition message.h:28
#define mutt_using_threads()
struct MuttThread * thread
Thread of Emails.
Definition email.h:119
An Email conversation.
Definition thread.h:34
struct MuttThread * parent
Parent of this Thread.
Definition thread.h:44
struct MuttThread * child
Child of this Thread.
Definition thread.h:45
struct Email * message
Email this Thread refers to.
Definition thread.h:49
struct MuttThread * next
Next sibling Thread.
Definition thread.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function: