NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
context.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <string.h>
31 #include "mutt/lib.h"
32 #include "email/lib.h"
33 #include "core/lib.h"
34 #include "context.h"
35 #include "imap/lib.h"
36 #include "maildir/lib.h"
37 #include "ncrypt/lib.h"
38 #include "pattern/lib.h"
39 #include "mutt_globals.h"
40 #include "mutt_header.h"
41 #include "mutt_thread.h"
42 #include "mx.h"
43 #include "score.h"
44 #include "sort.h"
45 
50 void ctx_free(struct Context **ptr)
51 {
52  if (!ptr || !*ptr)
53  return;
54 
55  struct Context *ctx = *ptr;
56 
57  struct EventContext ev_ctx = { ctx };
59 
60  if (ctx->mailbox)
62 
64  notify_free(&ctx->notify);
65  FREE(&ctx->pattern);
67 
68  FREE(ptr);
69 }
70 
76 struct Context *ctx_new(struct Mailbox *m)
77 {
78  struct Context *ctx = mutt_mem_calloc(1, sizeof(struct Context));
79 
80  ctx->notify = notify_new();
82  ctx->mailbox = m;
83  ctx->threads = mutt_thread_ctx_init(m);
84 
85  return ctx;
86 }
87 
92 static void ctx_cleanup(struct Context *ctx)
93 {
94  FREE(&ctx->pattern);
96  if (ctx->mailbox)
98 
99  struct Notify *notify = ctx->notify;
100  struct Mailbox *m = ctx->mailbox;
101  memset(ctx, 0, sizeof(struct Context));
102  ctx->notify = notify;
103  ctx->mailbox = m;
104 }
105 
112 void ctx_update(struct Context *ctx)
113 {
114  if (!ctx || !ctx->mailbox)
115  return;
116 
117  struct Mailbox *m = ctx->mailbox;
118 
120  mutt_hash_free(&m->id_hash);
121 
122  /* reset counters */
123  m->msg_unread = 0;
124  m->msg_flagged = 0;
125  m->msg_new = 0;
126  m->msg_deleted = 0;
127  m->msg_tagged = 0;
128  m->vcount = 0;
129  m->changed = false;
130 
132 
133  struct Email *e = NULL;
134  for (int msgno = 0; msgno < m->msg_count; msgno++)
135  {
136  e = m->emails[msgno];
137  if (!e)
138  continue;
139 
140  if (WithCrypto)
141  {
142  /* NOTE: this _must_ be done before the check for mailcap! */
143  e->security = crypt_query(e->body);
144  }
145 
146  if (ctx_has_limit(ctx))
147  {
148  e->vnum = -1;
149  }
150  else
151  {
152  m->v2r[m->vcount] = msgno;
153  e->vnum = m->vcount++;
154  }
155  e->msgno = msgno;
156 
157  if (e->env->supersedes)
158  {
159  struct Email *e2 = NULL;
160 
161  if (!m->id_hash)
162  m->id_hash = mutt_make_id_hash(m);
163 
164  e2 = mutt_hash_find(m->id_hash, e->env->supersedes);
165  if (e2)
166  {
167  e2->superseded = true;
168  if (C_Score)
169  mutt_score_message(ctx->mailbox, e2, true);
170  }
171  }
172 
173  /* add this message to the hash tables */
174  if (m->id_hash && e->env->message_id)
176  if (m->subj_hash && e->env->real_subj)
178  mutt_label_hash_add(m, e);
179 
180  if (C_Score)
181  mutt_score_message(ctx->mailbox, e, false);
182 
183  if (e->changed)
184  m->changed = true;
185  if (e->flagged)
186  m->msg_flagged++;
187  if (e->deleted)
188  m->msg_deleted++;
189  if (e->tagged)
190  m->msg_tagged++;
191  if (!e->read)
192  {
193  m->msg_unread++;
194  if (!e->old)
195  m->msg_new++;
196  }
197  }
198 
199  /* rethread from scratch */
200  mutt_sort_headers(ctx->mailbox, ctx->threads, true, &ctx->vsize);
201 }
202 
207 static void update_tables(struct Context *ctx)
208 {
209  if (!ctx || !ctx->mailbox)
210  return;
211 
212  struct Mailbox *m = ctx->mailbox;
213 
214  int i, j, padding;
215 
216  /* update memory to reflect the new state of the mailbox */
217  m->vcount = 0;
218  ctx->vsize = 0;
219  m->msg_tagged = 0;
220  m->msg_deleted = 0;
221  m->msg_new = 0;
222  m->msg_unread = 0;
223  m->changed = false;
224  m->msg_flagged = 0;
225  padding = mx_msg_padding_size(m);
226  for (i = 0, j = 0; i < m->msg_count; i++)
227  {
228  if (!m->emails[i])
229  break;
230  if (!m->emails[i]->quasi_deleted &&
231  (!m->emails[i]->deleted || ((m->type == MUTT_MAILDIR) && C_MaildirTrash)))
232  {
233  if (i != j)
234  {
235  m->emails[j] = m->emails[i];
236  m->emails[i] = NULL;
237  }
238  m->emails[j]->msgno = j;
239  if (m->emails[j]->vnum != -1)
240  {
241  m->v2r[m->vcount] = j;
242  m->emails[j]->vnum = m->vcount++;
243  struct Body *b = m->emails[j]->body;
244  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
245  }
246 
247  m->emails[j]->changed = false;
248  m->emails[j]->env->changed = false;
249 
250  if ((m->type == MUTT_MAILDIR) && C_MaildirTrash)
251  {
252  if (m->emails[j]->deleted)
253  m->msg_deleted++;
254  }
255 
256  if (m->emails[j]->tagged)
257  m->msg_tagged++;
258  if (m->emails[j]->flagged)
259  m->msg_flagged++;
260  if (!m->emails[j]->read)
261  {
262  m->msg_unread++;
263  if (!m->emails[j]->old)
264  m->msg_new++;
265  }
266 
267  j++;
268  }
269  else
270  {
271  if ((m->type == MUTT_NOTMUCH) || (m->type == MUTT_MH) ||
272  (m->type == MUTT_MAILDIR) || (m->type == MUTT_IMAP))
273  {
274  mailbox_size_sub(m, m->emails[i]);
275  }
276  /* remove message from the hash tables */
277  if (m->subj_hash && m->emails[i]->env->real_subj)
278  mutt_hash_delete(m->subj_hash, m->emails[i]->env->real_subj, m->emails[i]);
279  if (m->id_hash && m->emails[i]->env->message_id)
280  mutt_hash_delete(m->id_hash, m->emails[i]->env->message_id, m->emails[i]);
281  mutt_label_hash_remove(m, m->emails[i]);
282 
283 #ifdef USE_IMAP
284  if (m->type == MUTT_IMAP)
286 #endif
287 
288  mailbox_gc_add(m->emails[i]);
289  m->emails[i] = NULL;
290  }
291  }
292  m->msg_count = j;
293 }
294 
299 {
300  if (!nc->global_data)
301  return -1;
302  if (nc->event_type != NT_MAILBOX)
303  return 0;
304 
305  struct Context *ctx = nc->global_data;
306 
307  switch (nc->event_subtype)
308  {
309  case NT_MAILBOX_CLOSED:
311  ctx_cleanup(ctx);
312  break;
313  case NT_MAILBOX_INVALID:
314  ctx_update(ctx);
315  break;
316  case NT_MAILBOX_UPDATE:
317  update_tables(ctx);
318  break;
319  case NT_MAILBOX_RESORT:
320  mutt_sort_headers(ctx->mailbox, ctx->threads, true, &ctx->vsize);
321  break;
322  }
323 
324  return 0;
325 }
326 
335 bool message_is_tagged(struct Context *ctx, struct Email *e)
336 {
337  return e->visible && e->tagged;
338 }
339 
349 int el_add_tagged(struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
350 {
351  int count = 0;
352 
353  if (use_tagged)
354  {
355  if (!ctx || !ctx->mailbox || !ctx->mailbox->emails)
356  return -1;
357 
358  struct Mailbox *m = ctx->mailbox;
359  for (size_t i = 0; i < m->msg_count; i++)
360  {
361  e = m->emails[i];
362  if (!e)
363  break;
364  if (!message_is_tagged(ctx, e))
365  continue;
366 
367  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
368  en->email = e;
369  STAILQ_INSERT_TAIL(el, en, entries);
370  count++;
371  }
372  }
373  else
374  {
375  if (!e)
376  return -1;
377 
378  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
379  en->email = e;
380  STAILQ_INSERT_TAIL(el, en, entries);
381  count = 1;
382  }
383 
384  return count;
385 }
386 
397 struct Email *mutt_get_virt_email(struct Mailbox *m, int vnum)
398 {
399  if (!m || !m->emails || !m->v2r)
400  return NULL;
401 
402  if ((vnum < 0) || (vnum >= m->vcount))
403  return NULL;
404 
405  int inum = m->v2r[vnum];
406  if ((inum < 0) || (inum >= m->msg_count))
407  return NULL;
408 
409  return m->emails[inum];
410 }
411 
418 bool ctx_has_limit(const struct Context *ctx)
419 {
420  return ctx && ctx->pattern;
421 }
422 
429 struct Mailbox *ctx_mailbox(struct Context *ctx)
430 {
431  return ctx ? ctx->mailbox : NULL;
432 }
Body::hdr_offset
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
ctx_free
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:50
Mailbox::subj_hash
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
mutt_get_virt_email
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:397
Email::msgno
int msgno
Number displayed to the user.
Definition: email.h:87
imap_notify_delete_email
void imap_notify_delete_email(struct Mailbox *m, struct Email *e)
Inform IMAP that an Email has been deleted.
Definition: imap.c:651
el_add_tagged
int el_add_tagged(struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
Get a list of the tagged Emails.
Definition: context.c:349
ctx_has_limit
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:418
lib.h
NotifyCallback
Data passed to a notification function.
Definition: observer.h:39
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
mutt_hash_delete
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
Mailbox
A mailbox.
Definition: mailbox.h:81
Envelope::message_id
char * message_id
Message ID.
Definition: envelope.h:69
Mailbox::v2r
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
mutt_thread_ctx_init
struct ThreadsContext * mutt_thread_ctx_init(struct Mailbox *m)
Initialize a threading context.
Definition: mutt_thread.c:288
Mailbox::emails
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
mutt_pattern_free
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1029
NT_MAILBOX_INVALID
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:173
Envelope::supersedes
char * supersedes
Supersedes header.
Definition: envelope.h:70
Body::offset
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
ctx_mailbox
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:429
EventContext
An Event that happened to an Context.
Definition: context.h:68
Mailbox::msg_deleted
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
Body
The body of an email.
Definition: body.h:34
Mailbox::notify
struct Notify * notify
Notifications handler.
Definition: mailbox.h:144
NeoMutt::notify
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Context::vsize
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:40
message_is_tagged
bool message_is_tagged(struct Context *ctx, struct Email *e)
Is a message in the index tagged (and within limit)
Definition: context.c:335
Context::notify
struct Notify * notify
Notifications handler.
Definition: context.h:51
EmailNode::email
struct Email * email
Email in the list.
Definition: email.h:127
Context
The "current" mailbox.
Definition: context.h:38
mutt_globals.h
FREE
#define FREE(x)
Definition: memory.h:40
EmailNode
List of Emails.
Definition: email.h:125
mutt_score_message
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:173
mutt_header.h
Envelope::real_subj
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
Mailbox::vcount
int vcount
The number of virtual messages.
Definition: mailbox.h:102
notify_send
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152
Context::threads
struct ThreadsContext * threads
Threads context.
Definition: context.h:43
mutt_hash_find
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:354
ctx_new
struct Context * ctx_new(struct Mailbox *m)
Create a new Context.
Definition: context.c:76
C_Score
WHERE bool C_Score
Config: Use message scoring.
Definition: mutt_globals.h:159
notify_new
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:49
mutt_sort_headers
void mutt_sort_headers(struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
Sort emails by their headers.
Definition: sort.c:367
Email::old
bool old
Email is seen, but unread.
Definition: email.h:50
NT_MAILBOX
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:42
mutt_thread_ctx_free
void mutt_thread_ctx_free(struct ThreadsContext **tctx)
Finalize a threading context.
Definition: mutt_thread.c:301
crypt_query
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:687
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
Envelope::changed
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
NT_MAILBOX_UPDATE
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:176
Email::visible
bool visible
Is this message part of the view?
Definition: email.h:74
lib.h
Email::tagged
bool tagged
Email is tagged.
Definition: email.h:44
notify_observer_remove
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:207
Body::length
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Mailbox::changed
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
lib.h
mutt_label_hash_add
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:380
Mailbox::msg_count
int msg_count
Total number of messages.
Definition: mailbox.h:91
mutt_hash_insert
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:327
NotifyCallback::global_data
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
MUTT_NOTMUCH
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:54
MUTT_IMAP
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
Context::mailbox
struct Mailbox * mailbox
Definition: context.h:50
MUTT_MH
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:50
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
ctx_update
void ctx_update(struct Context *ctx)
Update the Context's message counts.
Definition: context.c:112
Mailbox::msg_flagged
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
Email::flagged
bool flagged
Marked important?
Definition: email.h:43
Email::security
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:39
lib.h
lib.h
WithCrypto
#define WithCrypto
Definition: lib.h:123
Context::limit_pattern
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: context.h:42
lib.h
lib.h
Email::deleted
bool deleted
Email is deleted.
Definition: email.h:45
ctx_cleanup
static void ctx_cleanup(struct Context *ctx)
Release memory and initialize a Context object.
Definition: context.c:92
Notify
Notification API.
Definition: notify.c:39
mutt_thread.h
sort.h
mutt_make_id_hash
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1518
mutt_label_hash_remove
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:393
STAILQ_INSERT_TAIL
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:386
NeoMutt
Container for Accounts, Notifications.
Definition: neomutt.h:36
NT_CONTEXT
@ NT_CONTEXT
Context has changed, NotifyContext, EventContext.
Definition: notify_type.h:38
notify_free
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:62
C_MaildirTrash
bool C_MaildirTrash
Config: Use the maildir 'trashed' flag, rather than deleting.
Definition: config.c:42
Email::vnum
int vnum
Virtual message number.
Definition: email.h:88
context.h
NT_CONTEXT_CLOSE
@ NT_CONTEXT_CLOSE
The Context is about to be destroyed.
Definition: context.h:62
mailbox_size_sub
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:210
notify_set_parent
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:82
mailbox_gc_add
void mailbox_gc_add(struct Email *e)
Add an Email to the garbage-collection set.
Definition: mailbox.c:242
Mailbox::msg_unread
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
Mailbox::msg_tagged
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
Context::pattern
char * pattern
Limit pattern string.
Definition: context.h:41
MUTT_MAILDIR
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:51
score.h
update_tables
static void update_tables(struct Context *ctx)
Update a Context structure's internal tables.
Definition: context.c:207
NotifyCallback::event_subtype
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
mx.h
NotifyCallback::event_type
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
ctx_mailbox_observer
int ctx_mailbox_observer(struct NotifyCallback *nc)
Watch for changes affecting the Context - Implements observer_t.
Definition: context.c:298
Email
The envelope/body of an email.
Definition: email.h:37
NT_MAILBOX_CLOSED
@ NT_MAILBOX_CLOSED
Mailbox was closed.
Definition: mailbox.h:172
Mailbox::msg_new
int msg_new
Number of new messages.
Definition: mailbox.h:95
mutt_clear_threads
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:637
mx_msg_padding_size
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1554
NT_MAILBOX_RESORT
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:174
Email::superseded
bool superseded
Got superseded?
Definition: email.h:53
Email::read
bool read
Email is read.
Definition: email.h:51
Mailbox::id_hash
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
Email::quasi_deleted
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:47
mutt_hash_free
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
Email::changed
bool changed
Email has been edited.
Definition: email.h:48
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91