NeoMutt  2018-07-16 +2481-68dcde
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/mutt.h"
32 #include "email/lib.h"
33 #include "core/lib.h"
34 #include "context.h"
35 #include "globals.h"
36 #include "mutt_header.h"
37 #include "mutt_thread.h"
38 #include "mx.h"
39 #include "ncrypt/ncrypt.h"
40 #include "pattern.h"
41 #include "score.h"
42 #include "sort.h"
43 
48 void ctx_free(struct Context **ptr)
49 {
50  if (!ptr || !*ptr)
51  return;
52 
53  struct Context *ctx = *ptr;
54 
55  struct EventContext ev_ctx = { ctx };
57 
58  if (ctx->mailbox)
60 
61  notify_free(&ctx->notify);
62 
63  FREE(ptr);
64 }
65 
70 struct Context *ctx_new(void)
71 {
72  struct Context *ctx = mutt_mem_calloc(1, sizeof(struct Context));
73 
74  ctx->notify = notify_new(ctx, NT_CONTEXT);
76 
77  return ctx;
78 }
79 
84 void ctx_cleanup(struct Context *ctx)
85 {
86  FREE(&ctx->pattern);
88  if (ctx->mailbox)
90 
91  struct Notify *notify = ctx->notify;
92  memset(ctx, 0, sizeof(struct Context));
93  ctx->notify = notify;
94 }
95 
102 void ctx_update(struct Context *ctx)
103 {
104  if (!ctx || !ctx->mailbox)
105  return;
106 
107  struct Mailbox *m = ctx->mailbox;
108 
110  mutt_hash_free(&m->id_hash);
111 
112  /* reset counters */
113  m->msg_unread = 0;
114  m->msg_flagged = 0;
115  m->msg_new = 0;
116  m->msg_deleted = 0;
117  m->msg_tagged = 0;
118  m->vcount = 0;
119  m->changed = false;
120 
121  mutt_clear_threads(ctx);
122 
123  struct Email *e = NULL;
124  for (int msgno = 0; msgno < m->msg_count; msgno++)
125  {
126  e = m->emails[msgno];
127 
128  if (WithCrypto)
129  {
130  /* NOTE: this _must_ be done before the check for mailcap! */
131  e->security = crypt_query(e->content);
132  }
133 
134  if (!ctx->pattern)
135  {
136  m->v2r[m->vcount] = msgno;
137  e->vnum = m->vcount++;
138  }
139  else
140  e->vnum = -1;
141  e->msgno = msgno;
142 
143  if (e->env->supersedes)
144  {
145  struct Email *e2 = NULL;
146 
147  if (!m->id_hash)
148  m->id_hash = mutt_make_id_hash(m);
149 
150  e2 = mutt_hash_find(m->id_hash, e->env->supersedes);
151  if (e2)
152  {
153  e2->superseded = true;
154  if (C_Score)
155  mutt_score_message(ctx->mailbox, e2, true);
156  }
157  }
158 
159  /* add this message to the hash tables */
160  if (m->id_hash && e->env->message_id)
162  if (m->subj_hash && e->env->real_subj)
164  mutt_label_hash_add(m, e);
165 
166  if (C_Score)
167  mutt_score_message(ctx->mailbox, e, false);
168 
169  if (e->changed)
170  m->changed = true;
171  if (e->flagged)
172  m->msg_flagged++;
173  if (e->deleted)
174  m->msg_deleted++;
175  if (!e->read)
176  {
177  m->msg_unread++;
178  if (!e->old)
179  m->msg_new++;
180  }
181  }
182 
183  mutt_sort_headers(ctx, true); /* rethread from scratch */
184 }
185 
191 void ctx_update_tables(struct Context *ctx, bool committing)
192 {
193  if (!ctx || !ctx->mailbox)
194  return;
195 
196  struct Mailbox *m = ctx->mailbox;
197 
198  int i, j, padding;
199 
200  /* update memory to reflect the new state of the mailbox */
201  m->vcount = 0;
202  ctx->vsize = 0;
203  m->msg_tagged = 0;
204  m->msg_deleted = 0;
205  m->msg_new = 0;
206  m->msg_unread = 0;
207  m->changed = false;
208  m->msg_flagged = 0;
209  padding = mx_msg_padding_size(m);
210  for (i = 0, j = 0; i < m->msg_count; i++)
211  {
212  if (!m->emails[i]->quasi_deleted &&
213  ((committing && (!m->emails[i]->deleted || ((m->magic == MUTT_MAILDIR) && C_MaildirTrash))) ||
214  (!committing && m->emails[i]->active)))
215  {
216  if (i != j)
217  {
218  m->emails[j] = m->emails[i];
219  m->emails[i] = NULL;
220  }
221  m->emails[j]->msgno = j;
222  if (m->emails[j]->vnum != -1)
223  {
224  m->v2r[m->vcount] = j;
225  m->emails[j]->vnum = m->vcount++;
226  struct Body *b = m->emails[j]->content;
227  ctx->vsize += b->length + b->offset - b->hdr_offset + padding;
228  }
229 
230  if (committing)
231  {
232  m->emails[j]->changed = false;
233  m->emails[j]->env->changed = false;
234  }
235  else if (m->emails[j]->changed)
236  m->changed = true;
237 
238  if (!committing || ((m->magic == MUTT_MAILDIR) && C_MaildirTrash))
239  {
240  if (m->emails[j]->deleted)
241  m->msg_deleted++;
242  }
243 
244  if (m->emails[j]->tagged)
245  m->msg_tagged++;
246  if (m->emails[j]->flagged)
247  m->msg_flagged++;
248  if (!m->emails[j]->read)
249  {
250  m->msg_unread++;
251  if (!m->emails[j]->old)
252  m->msg_new++;
253  }
254 
255  j++;
256  }
257  else
258  {
259  if ((m->magic == MUTT_NOTMUCH) || (m->magic == MUTT_MH) ||
260  (m->magic == MUTT_MAILDIR) || (m->magic == MUTT_IMAP))
261  {
262  mailbox_size_sub(m, m->emails[i]);
263  }
264  /* remove message from the hash tables */
265  if (m->subj_hash && m->emails[i]->env->real_subj)
266  mutt_hash_delete(m->subj_hash, m->emails[i]->env->real_subj, m->emails[i]);
267  if (m->id_hash && m->emails[i]->env->message_id)
268  mutt_hash_delete(m->id_hash, m->emails[i]->env->message_id, m->emails[i]);
269  mutt_label_hash_remove(m, m->emails[i]);
270  /* The path mx_mbox_check() -> imap_check_mailbox() ->
271  * imap_expunge_mailbox() -> ctx_update_tables()
272  * can occur before a call to mx_mbox_sync(), resulting in
273  * last_tag being stale if it's not reset here. */
274  if (ctx->last_tag == m->emails[i])
275  ctx->last_tag = NULL;
276  email_free(&m->emails[i]);
277  }
278  }
279  m->msg_count = j;
280 }
281 
286 {
287  if (!nc)
288  return -1;
289  if ((nc->obj_type != NT_MAILBOX) || (nc->event_type != NT_MAILBOX))
290  return 0;
291  struct Context *ctx = (struct Context *) nc->data;
292  if (!ctx)
293  return -1;
294 
295  switch (nc->event_subtype)
296  {
297  case MBN_CLOSED:
298  mutt_clear_threads(ctx);
299  ctx_cleanup(ctx);
300  break;
301  case MBN_INVALID:
302  ctx_update(ctx);
303  break;
304  case MBN_UPDATE:
305  ctx_update_tables(ctx, true);
306  break;
307  case MBN_RESORT:
308  mutt_sort_headers(ctx, true);
309  break;
310  case MBN_UNTAG:
311  if (ctx->last_tag && ctx->last_tag->deleted)
312  ctx->last_tag = NULL;
313  break;
314  }
315 
316  return 0;
317 }
318 
327 bool message_is_visible(struct Context *ctx, int index)
328 {
329  if (!ctx || !ctx->mailbox->emails || (index >= ctx->mailbox->msg_count))
330  return false;
331 
332  return !ctx->pattern || ctx->mailbox->emails[index]->limited;
333 }
334 
343 bool message_is_tagged(struct Context *ctx, int index)
344 {
345  return message_is_visible(ctx, index) && ctx->mailbox->emails[index]->tagged;
346 }
347 
357 int el_add_tagged(struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
358 {
359  int count = 0;
360 
361  if (use_tagged)
362  {
363  if (!ctx || !ctx->mailbox || !ctx->mailbox->emails)
364  return -1;
365 
366  for (size_t i = 0; i < ctx->mailbox->msg_count; i++)
367  {
368  if (!message_is_tagged(ctx, i))
369  continue;
370 
371  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
372  en->email = ctx->mailbox->emails[i];
373  STAILQ_INSERT_TAIL(el, en, entries);
374  count++;
375  }
376  }
377  else
378  {
379  if (!e)
380  return -1;
381 
382  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
383  en->email = e;
384  STAILQ_INSERT_TAIL(el, en, entries);
385  count = 1;
386  }
387 
388  return count;
389 }
390 
398 int el_add_email(struct EmailList *el, struct Email *e)
399 {
400  if (!el || !e)
401  return -1;
402 
403  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
404  en->email = e;
405  STAILQ_INSERT_TAIL(el, en, entries);
406 
407  return 0;
408 }
void ctx_update_tables(struct Context *ctx, bool committing)
Update a Context structure&#39;s internal tables.
Definition: context.c:191
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int ctx_mailbox_observer(struct NotifyCallback *nc)
Watch for changes affecting the Context - Implements observer_t.
Definition: context.c:285
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:444
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:102
Representation of the email&#39;s header.
The envelope/body of an email.
Definition: email.h:39
Data passed to a notification function.
Definition: observer.h:40
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:107
int msg_unread
Number of unread messages.
Definition: mailbox.h:103
Structs that make up an email.
The "currently-open" mailbox.
char * supersedes
Supersedes header.
Definition: envelope.h:70
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:104
intptr_t data
Observer: private to observer.
Definition: observer.h:48
struct Body * content
List of MIME parts.
Definition: email.h:92
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:379
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:169
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
bool changed
Email has been edited.
Definition: email.h:50
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message&#39;s labels to the Hash Table.
Definition: mutt_header.c:370
Mailbox was closed.
Definition: mailbox.h:63
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:387
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message&#39;s labels from the Hash Table.
Definition: mutt_header.c:383
Container for Accounts, Notifications.
Definition: neomutt.h:35
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:89
struct Context * ctx_new(void)
Create a new Context.
Definition: context.c:70
int vcount
The number of virtual messages.
Definition: mailbox.h:113
The body of an email.
Definition: body.h:34
Update internal tables.
Definition: mailbox.h:66
Hundreds of global variables to back the user variables.
struct Notify * notify_new(void *object, enum NotifyType type)
Create a new notifications handler.
Definition: notify.c:54
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
Assorted sorting methods.
int event_subtype
Send: event subtype.
Definition: observer.h:45
bool notify_observer_remove(struct Notify *notify, observer_t callback, intptr_t data)
Remove an observer from an object.
Definition: notify.c:194
bool tagged
Email is tagged.
Definition: email.h:46
bool read
Email is read.
Definition: email.h:53
char * message_id
Message ID.
Definition: envelope.h:69
struct Mailbox * mailbox
Definition: context.h:50
API for mailboxes.
bool old
Email is seen, but unread.
Definition: email.h:52
int event_type
Send: event type.
Definition: observer.h:44
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
bool message_is_visible(struct Context *ctx, int index)
Is a message in the index within limit.
Definition: context.c:327
struct Envelope * env
Envelope information.
Definition: email.h:91
Convenience wrapper for the core headers.
struct Notify * notify
Notifications handler.
Definition: context.h:51
int el_add_email(struct EmailList *el, struct Email *e)
Get a list of the selected Emails.
Definition: context.c:398
bool superseded
Got superseded?
Definition: email.h:55
bool limited
Is this message in a limited view?
Definition: email.h:76
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:50
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:49
off_t vsize
Definition: context.h:38
bool active
Message is not to be removed.
Definition: email.h:61
void mutt_sort_headers(struct Context *ctx, bool init)
Sort emails by their headers.
Definition: sort.c:362
Create/manipulate threading in emails.
void ctx_update(struct Context *ctx)
Update the Context&#39;s message counts.
Definition: context.c:102
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
A mailbox.
Definition: mailbox.h:92
Clear the &#39;last-tagged&#39; pointer.
Definition: mailbox.h:67
WHERE bool C_MaildirTrash
Config: Use the maildir &#39;trashed&#39; flag, rather than deleting.
Definition: globals.h:247
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: context.h:40
Email list needs resorting.
Definition: mailbox.h:65
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: pattern.c:1334
&#39;MH&#39; Mailbox type
Definition: mailbox.h:49
Notification API.
Definition: notify.c:40
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:108
int vnum
Virtual message number.
Definition: email.h:89
API for encryption/signing of emails.
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:41
void ctx_cleanup(struct Context *ctx)
Release memory and initialize a Context object.
Definition: context.c:84
struct Hash * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1437
void mutt_clear_threads(struct Context *ctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:602
Routines for adding user scores to emails.
The Context is about to be destroyed.
Definition: context.h:68
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:69
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
Context has changed.
Definition: notify_type.h:38
Email list was changed.
Definition: mailbox.h:64
bool flagged
Marked important?
Definition: email.h:45
int msg_new
Number of new messages.
Definition: mailbox.h:106
struct Hash * subj_hash
Hash table by subject.
Definition: mailbox.h:139
bool deleted
Email is deleted.
Definition: email.h:47
struct Email * email
Email in the list.
Definition: email.h:122
int obj_type
Notify: type of object event happened on.
Definition: observer.h:43
#define IP
Definition: set.h:144
#define FREE(x)
Definition: memory.h:40
Mailbox has changed.
Definition: notify_type.h:35
WHERE bool C_Score
Config: Use message scoring.
Definition: globals.h:257
List of Emails.
Definition: email.h:120
bool changed
Mailbox has been modified.
Definition: mailbox.h:125
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:48
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1462
struct Notify * notify
Notifications handler.
Definition: mailbox.h:150
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
An Event that happened to an Context.
Definition: context.h:57
void mailbox_size_sub(struct Mailbox *m, const struct Email *e)
Subtract an email&#39;s size from the total size of a Mailbox.
Definition: mailbox.c:183
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:357
void mutt_hash_free(struct Hash **ptr)
free_hdata a hash table
Definition: hash.c:472
struct HashElem * mutt_hash_insert(struct Hash *table, const char *strkey, void *data)
Add a new element to the Hash table (with string keys)
Definition: hash.c:352
Match patterns to emails.
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:41
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
bool notify_send(struct Notify *notify, int type, int subtype, intptr_t data)
Send out a notification message.
Definition: notify.c:145
char * pattern
Limit pattern string.
Definition: context.h:39
#define WithCrypto
Definition: ncrypt.h:160
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:696
struct Hash * id_hash
Hash table by msg id.
Definition: mailbox.h:138
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: context.c:343
struct Email * last_tag
Last tagged msg (used to link threads)
Definition: context.h:41
int msgno
Number displayed to the user.
Definition: email.h:88