NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
mview.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <string.h>
31#include "mutt/lib.h"
32#include "config/lib.h"
33#include "email/lib.h"
34#include "core/lib.h"
35#include "mview.h"
36#include "imap/lib.h"
37#include "ncrypt/lib.h"
38#include "pattern/lib.h"
39#include "mutt_header.h"
40#include "mutt_thread.h"
41#include "mx.h"
42#include "score.h"
43#include "sort.h"
44
49void mview_free(struct MailboxView **ptr)
50{
51 if (!ptr || !*ptr)
52 return;
53
54 struct MailboxView *mv = *ptr;
55
56 struct EventMview ev_m = { mv };
57 mutt_debug(LL_NOTIFY, "NT_MVIEW_DELETE: %p\n", mv);
59
60 if (mv->mailbox)
62
65 FREE(&mv->pattern);
67
68 FREE(&mv);
69 *ptr = NULL;
70}
71
77struct MailboxView *mview_new(struct Mailbox *m)
78{
79 if (!m)
80 return NULL;
81
82 struct MailboxView *mv = mutt_mem_calloc(1, sizeof(struct MailboxView));
83
84 mv->notify = notify_new();
86 struct EventMview ev_m = { mv };
87 mutt_debug(LL_NOTIFY, "NT_MVIEW_ADD: %p\n", mv);
89 // If the Mailbox is closed, mv->mailbox must be set to NULL
91
92 mv->mailbox = m;
94 mv->msg_in_pager = -1;
95 mv->collapsed = false;
97
98 return mv;
99}
100
105static void ctx_cleanup(struct MailboxView *mv)
106{
107 FREE(&mv->pattern);
109 if (mv->mailbox)
111
112 struct Notify *notify = mv->notify;
113 struct Mailbox *m = mv->mailbox;
114 memset(mv, 0, sizeof(struct MailboxView));
115 mv->notify = notify;
116 mv->mailbox = m;
117}
118
125void mview_update(struct MailboxView *mv)
126{
127 if (!mv || !mv->mailbox)
128 return;
129
130 struct Mailbox *m = mv->mailbox;
131
134
135 /* reset counters */
136 m->msg_unread = 0;
137 m->msg_flagged = 0;
138 m->msg_new = 0;
139 m->msg_deleted = 0;
140 m->msg_tagged = 0;
141 m->vcount = 0;
142 m->changed = false;
143
145
146 const bool c_score = cs_subset_bool(NeoMutt->sub, "score");
147 struct Email *e = NULL;
148 for (int msgno = 0; msgno < m->msg_count; msgno++)
149 {
150 e = m->emails[msgno];
151 if (!e)
152 continue;
153
154 if (WithCrypto)
155 {
156 /* NOTE: this _must_ be done before the check for mailcap! */
157 e->security = crypt_query(e->body);
158 }
159
160 if (mview_has_limit(mv))
161 {
162 e->vnum = -1;
163 }
164 else
165 {
166 m->v2r[m->vcount] = msgno;
167 e->vnum = m->vcount++;
168 }
169 e->msgno = msgno;
170
171 if (e->env->supersedes)
172 {
173 struct Email *e2 = NULL;
174
175 if (!m->id_hash)
177
178 e2 = mutt_hash_find(m->id_hash, e->env->supersedes);
179 if (e2)
180 {
181 e2->superseded = true;
182 if (c_score)
183 mutt_score_message(mv->mailbox, e2, true);
184 }
185 }
186
187 /* add this message to the hash tables */
188 if (m->id_hash && e->env->message_id)
190 if (m->subj_hash && e->env->real_subj)
193
194 if (c_score)
195 mutt_score_message(mv->mailbox, e, false);
196
197 if (e->changed)
198 m->changed = true;
199 if (e->flagged)
200 m->msg_flagged++;
201 if (e->deleted)
202 m->msg_deleted++;
203 if (e->tagged)
204 m->msg_tagged++;
205 if (!e->read)
206 {
207 m->msg_unread++;
208 if (!e->old)
209 m->msg_new++;
210 }
211 }
212
213 /* rethread from scratch */
214 mutt_sort_headers(mv->mailbox, mv->threads, true, &mv->vsize);
215}
216
221static void update_tables(struct MailboxView *mv)
222{
223 if (!mv || !mv->mailbox)
224 return;
225
226 struct Mailbox *m = mv->mailbox;
227
228 int i, j, padding;
229
230 /* update memory to reflect the new state of the mailbox */
231 m->vcount = 0;
232 mv->vsize = 0;
233 m->msg_tagged = 0;
234 m->msg_deleted = 0;
235 m->msg_new = 0;
236 m->msg_unread = 0;
237 m->changed = false;
238 m->msg_flagged = 0;
239 padding = mx_msg_padding_size(m);
240 for (i = 0, j = 0; i < m->msg_count; i++)
241 {
242 if (!m->emails[i])
243 break;
244 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
245 if (!m->emails[i]->quasi_deleted &&
246 (!m->emails[i]->deleted || ((m->type == MUTT_MAILDIR) && c_maildir_trash)))
247 {
248 if (i != j)
249 {
250 m->emails[j] = m->emails[i];
251 m->emails[i] = NULL;
252 }
253 m->emails[j]->msgno = j;
254 if (m->emails[j]->vnum != -1)
255 {
256 m->v2r[m->vcount] = j;
257 m->emails[j]->vnum = m->vcount++;
258 struct Body *b = m->emails[j]->body;
259 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
260 }
261
262 m->emails[j]->changed = false;
263 m->emails[j]->env->changed = false;
264
265 if ((m->type == MUTT_MAILDIR) && c_maildir_trash)
266 {
267 if (m->emails[j]->deleted)
268 m->msg_deleted++;
269 }
270
271 if (m->emails[j]->tagged)
272 m->msg_tagged++;
273 if (m->emails[j]->flagged)
274 m->msg_flagged++;
275 if (!m->emails[j]->read)
276 {
277 m->msg_unread++;
278 if (!m->emails[j]->old)
279 m->msg_new++;
280 }
281
282 j++;
283 }
284 else
285 {
286 if ((m->type == MUTT_NOTMUCH) || (m->type == MUTT_MH) ||
287 (m->type == MUTT_MAILDIR) || (m->type == MUTT_IMAP))
288 {
289 mailbox_size_sub(m, m->emails[i]);
290 }
291 /* remove message from the hash tables */
292 if (m->subj_hash && m->emails[i]->env->real_subj)
294 if (m->id_hash && m->emails[i]->env->message_id)
297
298#ifdef USE_IMAP
299 if (m->type == MUTT_IMAP)
301#endif
302
303 mailbox_gc_add(m->emails[i]);
304 m->emails[i] = NULL;
305 }
306 }
307 m->msg_count = j;
308}
309
314{
315 if (nc->event_type != NT_MAILBOX)
316 return 0;
317 if (!nc->global_data)
318 return -1;
319
320 struct MailboxView *mv = nc->global_data;
321
322 switch (nc->event_subtype)
323 {
326 ctx_cleanup(mv);
327 break;
329 mview_update(mv);
330 break;
332 update_tables(mv);
333 break;
335 mutt_sort_headers(mv->mailbox, mv->threads, true, &mv->vsize);
336 break;
337 default:
338 return 0;
339 }
340
341 mutt_debug(LL_DEBUG5, "mailbox done\n");
342 return 0;
343}
344
353{
354 return e->visible && e->tagged;
355}
356
366int el_add_tagged(struct EmailList *el, struct MailboxView *mv, struct Email *e, bool use_tagged)
367{
368 int count = 0;
369
370 if (use_tagged)
371 {
372 if (!mv || !mv->mailbox || !mv->mailbox->emails)
373 return -1;
374
375 struct Mailbox *m = mv->mailbox;
376 for (int i = 0; i < m->msg_count; i++)
377 {
378 e = m->emails[i];
379 if (!e)
380 break;
381 if (!message_is_tagged(e))
382 continue;
383
384 struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
385 en->email = e;
386 STAILQ_INSERT_TAIL(el, en, entries);
387 count++;
388 }
389 }
390 else
391 {
392 if (!e)
393 return -1;
394
395 struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
396 en->email = e;
397 STAILQ_INSERT_TAIL(el, en, entries);
398 count = 1;
399 }
400
401 return count;
402}
403
414struct Email *mutt_get_virt_email(struct Mailbox *m, int vnum)
415{
416 if (!m || !m->emails || !m->v2r)
417 return NULL;
418
419 if ((vnum < 0) || (vnum >= m->vcount))
420 return NULL;
421
422 int inum = m->v2r[vnum];
423 if ((inum < 0) || (inum >= m->msg_count))
424 return NULL;
425
426 return m->emails[inum];
427}
428
435bool mview_has_limit(const struct MailboxView *mv)
436{
437 return mv && mv->pattern;
438}
439
447{
448 return mv ? mv->mailbox : NULL;
449}
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:675
Structs that make up an email.
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
int mview_mailbox_observer(struct NotifyCallback *nc)
Notification that a Mailbox has changed - Implements observer_t -.
Definition: mview.c:313
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:335
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
IMAP network mailbox.
void imap_notify_delete_email(struct Mailbox *m, struct Email *e)
Inform IMAP that an Email has been deleted.
Definition: imap.c:654
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
void mailbox_size_sub(struct Mailbox *m, const struct Email *e)
Subtract an email's size from the total size of a Mailbox.
Definition: mailbox.c:247
void mailbox_gc_add(struct Email *e)
Add an Email to the garbage-collection set.
Definition: mailbox.c:282
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:177
@ NT_MAILBOX_DELETE
Mailbox is about to be deleted.
Definition: mailbox.h:170
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:176
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:178
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:47
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition: notify.c:228
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:93
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:396
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:383
Representation of the email's header.
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:708
void mutt_thread_ctx_free(struct ThreadsContext **tctx)
Finalize a threading context.
Definition: mutt_thread.c:365
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1651
struct ThreadsContext * mutt_thread_ctx_init(struct Mailbox *m)
Initialize a threading context.
Definition: mutt_thread.c:352
Create/manipulate threading in emails.
int el_add_tagged(struct EmailList *el, struct MailboxView *mv, struct Email *e, bool use_tagged)
Get a list of the tagged Emails.
Definition: mview.c:366
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:414
static void ctx_cleanup(struct MailboxView *mv)
Release memory and initialize a MailboxView.
Definition: mview.c:105
struct Mailbox * mview_mailbox(struct MailboxView *mv)
Wrapper to get the mailbox in a MailboxView, or NULL.
Definition: mview.c:446
static void update_tables(struct MailboxView *mv)
Update a MailboxView's internal tables.
Definition: mview.c:221
void mview_free(struct MailboxView **ptr)
Free a MailboxView.
Definition: mview.c:49
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: mview.c:352
struct MailboxView * mview_new(struct Mailbox *m)
Create a new MailboxView.
Definition: mview.c:77
void mview_update(struct MailboxView *mv)
Update the MailboxView's message counts.
Definition: mview.c:125
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:435
The "currently-open" mailbox.
@ NT_MVIEW_DELETE
The Mview is about to be destroyed.
Definition: mview.h:61
@ NT_MVIEW_ADD
The Mview has been opened.
Definition: mview.h:60
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1549
API for mailboxes.
API for encryption/signing of emails.
#define WithCrypto
Definition: lib.h:116
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
@ NT_MVIEW
MailboxView has changed, NotifyMview, EventMview.
Definition: notify_type.h:50
Match patterns to emails.
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:159
Routines for adding user scores to emails.
void mutt_sort_headers(struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
Sort emails by their headers.
Definition: sort.c:356
Assorted sorting methods.
The body of an email.
Definition: body.h:36
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:80
List of Emails.
Definition: email.h:131
struct Email * email
Email in the list.
Definition: email.h:132
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
bool visible
Is this message part of the view?
Definition: email.h:121
struct Envelope * env
Envelope information.
Definition: email.h:66
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
bool old
Email is seen, but unread.
Definition: email.h:47
bool changed
Email has been edited.
Definition: email.h:75
bool flagged
Marked important?
Definition: email.h:45
int vnum
Virtual message number.
Definition: email.h:114
int msgno
Number displayed to the user.
Definition: email.h:111
bool deleted
Email is deleted.
Definition: email.h:76
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:103
bool tagged
Email is tagged.
Definition: email.h:107
bool superseded
Got superseded?
Definition: email.h:50
char * supersedes
Supersedes header.
Definition: envelope.h:74
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:92
char * message_id
Message ID.
Definition: envelope.h:73
char * real_subj
Offset of the real subject.
Definition: envelope.h:71
An Event that happened to an MailboxView.
Definition: mview.h:69
struct MailboxView * mv
The MailboxView this Event relates to.
Definition: mview.h:70
The "current" mailbox.
Definition: mview.h:38
bool collapsed
Are all threads collapsed?
Definition: mview.h:47
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:39
struct Notify * notify
Notifications: NotifyMview, EventMview.
Definition: mview.h:50
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:41
struct ThreadsContext * threads
Threads context.
Definition: mview.h:42
int msg_in_pager
Message currently shown in the pager.
Definition: mview.h:43
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:49
char * pattern
Limit pattern string.
Definition: mview.h:40
A mailbox.
Definition: mailbox.h:79
int vcount
The number of virtual messages.
Definition: mailbox.h:99
bool changed
Mailbox has been modified.
Definition: mailbox.h:110
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
int msg_new
Number of new messages.
Definition: mailbox.h:92
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:124
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:144
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:123
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:93
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:90
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:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Data passed to a notification function.
Definition: observer.h:34
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:36
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:37
void * global_data
Data from notify_observer_add()
Definition: observer.h:39
Notification API.
Definition: notify.c:51