NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
context.c File Reference

The "currently-open" mailbox. More...

#include "config.h"
#include <string.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "context.h"
#include "imap/lib.h"
#include "ncrypt/lib.h"
#include "pattern/lib.h"
#include "mutt_header.h"
#include "mutt_thread.h"
#include "mx.h"
#include "score.h"
#include "sort.h"
+ Include dependency graph for context.c:

Go to the source code of this file.

Functions

void ctx_free (struct Context **ptr)
 Free a Context. More...
 
struct Contextctx_new (struct Mailbox *m)
 Create a new Context. More...
 
static void ctx_cleanup (struct Context *ctx)
 Release memory and initialize a Context object. More...
 
void ctx_update (struct Context *ctx)
 Update the Context's message counts. More...
 
static void update_tables (struct Context *ctx)
 Update a Context structure's internal tables. More...
 
int ctx_mailbox_observer (struct NotifyCallback *nc)
 Notification that a Mailbox has changed - Implements observer_t -. More...
 
bool message_is_tagged (struct Email *e)
 Is a message in the index tagged (and within limit) More...
 
int el_add_tagged (struct EmailList *el, struct Context *ctx, struct Email *e, bool use_tagged)
 Get a list of the tagged Emails. More...
 
struct Emailmutt_get_virt_email (struct Mailbox *m, int vnum)
 Get a virtual Email. More...
 
bool ctx_has_limit (const struct Context *ctx)
 Is a limit active? More...
 
struct Mailboxctx_mailbox (struct Context *ctx)
 Wrapper to get the mailbox in a Context, or NULL. More...
 

Detailed Description

The "currently-open" mailbox.

Authors
  • Richard Russon

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 context.c.

Function Documentation

◆ ctx_free()

void ctx_free ( struct Context **  ptr)

Free a Context.

Parameters
[out]ptrContext to free

Definition at line 49 of file context.c.

50 {
51  if (!ptr || !*ptr)
52  return;
53 
54  struct Context *ctx = *ptr;
55 
56  struct EventContext ev_c = { ctx };
57  mutt_debug(LL_NOTIFY, "NT_CONTEXT_DELETE: %p\n", ctx);
59 
60  if (ctx->mailbox)
62 
65  FREE(&ctx->pattern);
67 
68  FREE(&ctx);
69  *ptr = NULL;
70 }
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
@ NT_CONTEXT_DELETE
The Context is about to be destroyed.
Definition: context.h:61
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
int ctx_mailbox_observer(struct NotifyCallback *nc)
Notification that a Mailbox has changed - Implements observer_t -.
Definition: context.c:313
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
#define FREE(x)
Definition: memory.h:40
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
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_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
void mutt_thread_ctx_free(struct ThreadsContext **tctx)
Finalize a threading context.
Definition: mutt_thread.c:369
@ NT_CONTEXT
Context has changed, NotifyContext, EventContext.
Definition: notify_type.h:43
The "current" mailbox.
Definition: context.h:38
char * pattern
Limit pattern string.
Definition: context.h:40
struct Mailbox * mailbox
Current Mailbox.
Definition: context.h:49
struct ThreadsContext * threads
Threads context.
Definition: context.h:42
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: context.h:41
struct Notify * notify
Notifications: NotifyContext, EventContext.
Definition: context.h:50
An Event that happened to an Context.
Definition: context.h:69
struct Context * ctx
The Context this Event relates to.
Definition: context.h:70
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:148
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ctx_new()

struct Context* ctx_new ( struct Mailbox m)

Create a new Context.

Parameters
mMailbox
Return values
ptrNew Context

Definition at line 77 of file context.c.

78 {
79  if (!m)
80  return NULL;
81 
82  struct Context *ctx = mutt_mem_calloc(1, sizeof(struct Context));
83 
84  ctx->notify = notify_new();
86  struct EventContext ev_c = { ctx };
87  mutt_debug(LL_NOTIFY, "NT_CONTEXT_ADD: %p\n", ctx);
89  // If the Mailbox is closed, ctx->mailbox must be set to NULL
91 
92  ctx->mailbox = m;
94  ctx->msg_in_pager = -1;
95  ctx->collapsed = false;
96  ctx_update(ctx);
97 
98  return ctx;
99 }
void ctx_update(struct Context *ctx)
Update the Context's message counts.
Definition: context.c:125
@ NT_CONTEXT_ADD
The Context has been opened.
Definition: context.h:60
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
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
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:93
struct ThreadsContext * mutt_thread_ctx_init(struct Mailbox *m)
Initialize a threading context.
Definition: mutt_thread.c:356
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:48
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:43
bool collapsed
Are all threads collapsed?
Definition: context.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ctx_cleanup()

static void ctx_cleanup ( struct Context ctx)
static

Release memory and initialize a Context object.

Parameters
ctxContext to cleanup

Definition at line 105 of file context.c.

106 {
107  FREE(&ctx->pattern);
109  if (ctx->mailbox)
111 
112  struct Notify *notify = ctx->notify;
113  struct Mailbox *m = ctx->mailbox;
114  memset(ctx, 0, sizeof(struct Context));
115  ctx->notify = notify;
116  ctx->mailbox = m;
117 }
A mailbox.
Definition: mailbox.h:82
Notification API.
Definition: notify.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ctx_update()

void ctx_update ( struct Context ctx)

Update the Context's message counts.

Parameters
ctxMailbox

this routine is called to update the counts in the context structure

Definition at line 125 of file context.c.

126 {
127  if (!ctx || !ctx->mailbox)
128  return;
129 
130  struct Mailbox *m = ctx->mailbox;
131 
133  mutt_hash_free(&m->id_hash);
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 (ctx_has_limit(ctx))
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)
176  m->id_hash = mutt_make_id_hash(m);
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(ctx->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)
192  mutt_label_hash_add(m, e);
193 
194  if (c_score)
195  mutt_score_message(ctx->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(ctx->mailbox, ctx->threads, true, &ctx->vsize);
215 }
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:433
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:692
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
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
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:379
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:714
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1658
#define WithCrypto
Definition: lib.h:113
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:160
void mutt_sort_headers(struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
Sort emails by their headers.
Definition: sort.c:356
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
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 tagged
Email is tagged.
Definition: email.h:107
bool superseded
Got superseded?
Definition: email.h:50
char * supersedes
Supersedes header.
Definition: envelope.h:72
char * message_id
Message ID.
Definition: envelope.h:71
char * real_subj
Offset of the real subject.
Definition: envelope.h:69
int vcount
The number of virtual messages.
Definition: mailbox.h:102
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
int msg_new
Number of new messages.
Definition: mailbox.h:95
int msg_count
Total number of messages.
Definition: mailbox.h:91
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_tables()

static void update_tables ( struct Context ctx)
static

Update a Context structure's internal tables.

Parameters
ctxMailbox

Definition at line 221 of file context.c.

222 {
223  if (!ctx || !ctx->mailbox)
224  return;
225 
226  struct Mailbox *m = ctx->mailbox;
227 
228  int i, j, padding;
229 
230  /* update memory to reflect the new state of the mailbox */
231  m->vcount = 0;
232  ctx->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  ctx->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)
293  mutt_hash_delete(m->subj_hash, m->emails[i]->env->real_subj, m->emails[i]);
294  if (m->id_hash && m->emails[i]->env->message_id)
295  mutt_hash_delete(m->id_hash, m->emails[i]->env->message_id, m->emails[i]);
296  mutt_label_hash_remove(m, m->emails[i]);
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 }
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
void imap_notify_delete_email(struct Mailbox *m, struct Email *e)
Inform IMAP that an Email has been deleted.
Definition: imap.c:656
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:236
void mailbox_gc_add(struct Email *e)
Add an Email to the garbage-collection set.
Definition: mailbox.c:271
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:54
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:50
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:51
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:392
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1543
The body of an email.
Definition: body.h:35
LOFF_T offset
offset where the actual data begins
Definition: body.h:51
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:79
bool quasi_deleted
Deleted from neomutt, but not modified on disk.
Definition: email.h:103
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:90
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ message_is_tagged()

bool message_is_tagged ( struct Email e)

Is a message in the index tagged (and within limit)

Parameters
eEmail
Return values
trueThe message is both tagged and within limit

If a limit is in effect, the message must be visible within it.

Definition at line 350 of file context.c.

351 {
352  return e->visible && e->tagged;
353 }
bool visible
Is this message part of the view?
Definition: email.h:121
+ Here is the caller graph for this function:

◆ 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.

Parameters
elEmpty EmailList to populate
ctxCurrent Mailbox
eCurrent Email
use_taggedUse tagged Emails
Return values
numNumber of selected emails
-1Error

Definition at line 364 of file context.c.

365 {
366  int count = 0;
367 
368  if (use_tagged)
369  {
370  if (!ctx || !ctx->mailbox || !ctx->mailbox->emails)
371  return -1;
372 
373  struct Mailbox *m = ctx->mailbox;
374  for (size_t i = 0; i < m->msg_count; i++)
375  {
376  e = m->emails[i];
377  if (!e)
378  break;
379  if (!message_is_tagged(e))
380  continue;
381 
382  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
383  en->email = e;
384  STAILQ_INSERT_TAIL(el, en, entries);
385  count++;
386  }
387  }
388  else
389  {
390  if (!e)
391  return -1;
392 
393  struct EmailNode *en = mutt_mem_calloc(1, sizeof(*en));
394  en->email = e;
395  STAILQ_INSERT_TAIL(el, en, entries);
396  count = 1;
397  }
398 
399  return count;
400 }
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: context.c:350
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
List of Emails.
Definition: email.h:131
struct Email * email
Email in the list.
Definition: email.h:132
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_virt_email()

struct Email* mutt_get_virt_email ( struct Mailbox m,
int  vnum 
)

Get a virtual Email.

Parameters
mMailbox
vnumVirtual index number
Return values
ptrEmail
NULLNo Email selected, or bad index values

This safely gets the result of the following:

  • mailbox->emails[mailbox->v2r[vnum]]

Definition at line 412 of file context.c.

413 {
414  if (!m || !m->emails || !m->v2r)
415  return NULL;
416 
417  if ((vnum < 0) || (vnum >= m->vcount))
418  return NULL;
419 
420  int inum = m->v2r[vnum];
421  if ((inum < 0) || (inum >= m->msg_count))
422  return NULL;
423 
424  return m->emails[inum];
425 }
+ Here is the caller graph for this function:

◆ ctx_has_limit()

bool ctx_has_limit ( const struct Context ctx)

Is a limit active?

Parameters
ctxContext
Return values
trueA limit is active
falseNo limit is active

Definition at line 433 of file context.c.

434 {
435  return ctx && ctx->pattern;
436 }
+ Here is the caller graph for this function:

◆ ctx_mailbox()

struct Mailbox* ctx_mailbox ( struct Context ctx)

Wrapper to get the mailbox in a Context, or NULL.

Parameters
ctxContext
Return values
ptrThe mailbox in the Context
NULLContext is NULL or doesn't have a mailbox

Definition at line 444 of file context.c.

445 {
446  return ctx ? ctx->mailbox : NULL;
447 }
+ Here is the caller graph for this function: