NeoMutt  2024-10-02-7-gd3e66a
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mview.c File Reference

View of a 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 "mview.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 mview.c:

Go to the source code of this file.

Functions

void mview_free (struct MailboxView **ptr)
 Free a MailboxView.
 
struct MailboxViewmview_new (struct Mailbox *m, struct Notify *parent)
 Create a new MailboxView.
 
static void mview_clean (struct MailboxView *mv)
 Release memory and initialize a MailboxView.
 
void mview_update (struct MailboxView *mv)
 Update the MailboxView's message counts.
 
static void update_tables (struct MailboxView *mv)
 Update a MailboxView's internal tables.
 
int mview_mailbox_observer (struct NotifyCallback *nc)
 Notification that a Mailbox has changed - Implements observer_t -.
 
bool message_is_tagged (struct Email *e)
 Is a message in the index tagged (and within limit)
 
int ea_add_tagged (struct EmailArray *ea, struct MailboxView *mv, struct Email *e, bool use_tagged)
 Get an array of the tagged Emails.
 
struct Emailmutt_get_virt_email (struct Mailbox *m, int vnum)
 Get a virtual Email.
 
bool mview_has_limit (const struct MailboxView *mv)
 Is a limit active?
 
struct Mailboxmview_mailbox (struct MailboxView *mv)
 Wrapper to get the mailbox in a MailboxView, or NULL.
 
static struct MuttThreadtop_of_thread (struct Email *e)
 Find the first email in the current thread.
 
bool mutt_limit_current_thread (struct MailboxView *mv, struct Email *e)
 Limit the email view to the current thread.
 

Detailed Description

View of a Mailbox.

Authors
  • Richard Russon
  • 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 mview.c.

Function Documentation

◆ mview_free()

void mview_free ( struct MailboxView **  ptr)

Free a MailboxView.

Parameters
[out]ptrMailboxView to free

Definition at line 50 of file mview.c.

51{
52 if (!ptr || !*ptr)
53 return;
54
55 struct MailboxView *mv = *ptr;
56
57 struct EventMview ev_m = { mv };
58 mutt_debug(LL_NOTIFY, "NT_MVIEW_DELETE: %p\n", (void *) mv);
60
61 if (mv->mailbox)
62 {
64
65 // Disconnect the Emails before freeing the Threads
66 for (int i = 0; i < mv->mailbox->msg_count; i++)
67 {
68 struct Email *e = mv->mailbox->emails[i];
69 if (!e)
70 continue;
71 e->thread = NULL;
72 e->threaded = false;
73 }
74 }
75
77 notify_free(&mv->notify);
78 FREE(&mv->pattern);
80
81 *ptr = NULL;
82 FREE(&mv);
83}
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:778
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
int mview_mailbox_observer(struct NotifyCallback *nc)
Notification that a Mailbox has changed - Implements observer_t -.
Definition: mview.c:325
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
#define FREE(x)
Definition: memory.h:45
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition: notify.c:230
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
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:75
void mutt_thread_ctx_free(struct ThreadsContext **ptr)
Finalize a threading context.
Definition: mutt_thread.c:368
@ NT_MVIEW_DELETE
The Mview is about to be destroyed.
Definition: mview.h:63
@ NT_MVIEW
MailboxView has changed, NotifyMview, EventMview.
Definition: notify_type.h:50
The envelope/body of an email.
Definition: email.h:39
bool threaded
Used for threading.
Definition: email.h:108
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
An Event that happened to an MailboxView.
Definition: mview.h:71
struct MailboxView * mv
The MailboxView this Event relates to.
Definition: mview.h:72
View of a Mailbox.
Definition: mview.h:40
struct Notify * notify
Notifications: NotifyMview, EventMview.
Definition: mview.h:52
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:43
struct ThreadsContext * threads
Threads context.
Definition: mview.h:44
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:51
char * pattern
Limit pattern string.
Definition: mview.h:42
int msg_count
Total number of messages.
Definition: mailbox.h:88
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mview_new()

struct MailboxView * mview_new ( struct Mailbox m,
struct Notify parent 
)

Create a new MailboxView.

Parameters
mMailbox
parentNotification parent
Return values
ptrNew MailboxView

Definition at line 91 of file mview.c.

92{
93 if (!m)
94 return NULL;
95
96 struct MailboxView *mv = mutt_mem_calloc(1, sizeof(struct MailboxView));
97
98 mv->notify = notify_new();
99 notify_set_parent(mv->notify, parent);
100 struct EventMview ev_m = { mv };
101 mutt_debug(LL_NOTIFY, "NT_MVIEW_ADD: %p\n", (void *) mv);
103 // If the Mailbox is closed, mv->mailbox must be set to NULL
105
106 mv->mailbox = m;
108 mv->msg_in_pager = -1;
109 mv->collapsed = false;
111
112 return mv;
113}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
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:191
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:62
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:95
struct ThreadsContext * mutt_thread_ctx_init(struct MailboxView *mv)
Initialize a threading context.
Definition: mutt_thread.c:357
void mview_update(struct MailboxView *mv)
Update the MailboxView's message counts.
Definition: mview.c:139
@ NT_MVIEW_ADD
The Mview has been opened.
Definition: mview.h:62
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
bool collapsed
Are all threads collapsed?
Definition: mview.h:49
int msg_in_pager
Message currently shown in the pager.
Definition: mview.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mview_clean()

static void mview_clean ( struct MailboxView mv)
static

Release memory and initialize a MailboxView.

Parameters
mvMailboxView to cleanup

Definition at line 119 of file mview.c.

120{
121 FREE(&mv->pattern);
123 if (mv->mailbox)
125
126 struct Notify *notify = mv->notify;
127 struct Mailbox *m = mv->mailbox;
128 memset(mv, 0, sizeof(struct MailboxView));
129 mv->notify = notify;
130 mv->mailbox = m;
131}
A mailbox.
Definition: mailbox.h:79
Notification API.
Definition: notify.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mview_update()

void mview_update ( struct MailboxView mv)

Update the MailboxView's message counts.

Parameters
mvMailbox View

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

Definition at line 139 of file mview.c.

140{
141 if (!mv || !mv->mailbox)
142 return;
143
144 struct Mailbox *m = mv->mailbox;
145
148
149 /* reset counters */
150 m->msg_unread = 0;
151 m->msg_flagged = 0;
152 m->msg_new = 0;
153 m->msg_deleted = 0;
154 m->msg_tagged = 0;
155 m->vcount = 0;
156 m->changed = false;
157
159
160 const bool c_score = cs_subset_bool(NeoMutt->sub, "score");
161 struct Email *e = NULL;
162 for (int msgno = 0; msgno < m->msg_count; msgno++)
163 {
164 e = m->emails[msgno];
165 if (!e)
166 continue;
167
168 if (WithCrypto)
169 {
170 /* NOTE: this _must_ be done before the check for mailcap! */
171 e->security = crypt_query(e->body);
172 }
173
174 if (mview_has_limit(mv))
175 {
176 e->vnum = -1;
177 }
178 else
179 {
180 m->v2r[m->vcount] = msgno;
181 e->vnum = m->vcount++;
182 }
183 e->msgno = msgno;
184
185 if (e->env->supersedes)
186 {
187 struct Email *e2 = NULL;
188
189 if (!m->id_hash)
191
192 e2 = mutt_hash_find(m->id_hash, e->env->supersedes);
193 if (e2)
194 {
195 e2->superseded = true;
196 if (c_score)
197 mutt_score_message(mv->mailbox, e2, true);
198 }
199 }
200
201 /* add this message to the hash tables */
202 if (m->id_hash && e->env->message_id)
204 if (m->subj_hash && e->env->real_subj)
207
208 if (c_score)
209 mutt_score_message(mv->mailbox, e, false);
210
211 if (e->changed)
212 m->changed = true;
213 if (e->flagged)
214 m->msg_flagged++;
215 if (e->deleted)
216 m->msg_deleted++;
217 if (e->tagged)
218 m->msg_tagged++;
219 if (!e->read)
220 {
221 m->msg_unread++;
222 if (!e->old)
223 m->msg_new++;
224 }
225 }
226
227 /* rethread from scratch */
228 mutt_sort_headers(mv, true);
229}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:687
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_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
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:416
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:720
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1702
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:439
#define WithCrypto
Definition: lib.h:116
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:164
void mutt_sort_headers(struct MailboxView *mv, bool init)
Sort emails by their headers.
Definition: sort.c:350
bool read
Email is read.
Definition: email.h:50
struct Envelope * env
Envelope information.
Definition: email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
struct Body * body
List of MIME parts.
Definition: email.h:69
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
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:78
bool tagged
Email is tagged.
Definition: email.h:107
bool superseded
Got superseded?
Definition: email.h:52
char * supersedes
Supersedes header.
Definition: envelope.h:74
char * message_id
Message ID.
Definition: envelope.h:73
char *const real_subj
Offset of the real subject.
Definition: envelope.h:71
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
struct HashTable * subj_hash
Hash Table: "subject" -> Email.
Definition: mailbox.h:124
struct HashTable * id_hash
Hash Table: "message-id" -> Email.
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:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_tables()

static void update_tables ( struct MailboxView mv)
static

Update a MailboxView's internal tables.

Parameters
mvMailbox

Definition at line 235 of file mview.c.

236{
237 if (!mv || !mv->mailbox)
238 return;
239
240 struct Mailbox *m = mv->mailbox;
241
242 int i, j, padding;
243
244 /* update memory to reflect the new state of the mailbox */
245 m->vcount = 0;
246 mv->vsize = 0;
247 m->msg_tagged = 0;
248 m->msg_deleted = 0;
249 m->msg_new = 0;
250 m->msg_unread = 0;
251 m->changed = false;
252 m->msg_flagged = 0;
253 padding = mx_msg_padding_size(m);
254 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
255 for (i = 0, j = 0; i < m->msg_count; i++)
256 {
257 if (!m->emails[i])
258 break;
259 if (!m->emails[i]->quasi_deleted &&
260 (!m->emails[i]->deleted || ((m->type == MUTT_MAILDIR) && c_maildir_trash)))
261 {
262 if (i != j)
263 {
264 m->emails[j] = m->emails[i];
265 m->emails[i] = NULL;
266 }
267 m->emails[j]->msgno = j;
268 if (m->emails[j]->vnum != -1)
269 {
270 m->v2r[m->vcount] = j;
271 m->emails[j]->vnum = m->vcount++;
272 struct Body *b = m->emails[j]->body;
273 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
274 }
275
276 m->emails[j]->changed = false;
277 m->emails[j]->env->changed = false;
278
279 if ((m->type == MUTT_MAILDIR) && c_maildir_trash)
280 {
281 if (m->emails[j]->deleted)
282 m->msg_deleted++;
283 }
284
285 if (m->emails[j]->tagged)
286 m->msg_tagged++;
287 if (m->emails[j]->flagged)
288 m->msg_flagged++;
289 if (!m->emails[j]->read)
290 {
291 m->msg_unread++;
292 if (!m->emails[j]->old)
293 m->msg_new++;
294 }
295
296 j++;
297 }
298 else
299 {
300 if ((m->type == MUTT_NOTMUCH) || (m->type == MUTT_MH) ||
301 (m->type == MUTT_MAILDIR) || (m->type == MUTT_IMAP))
302 {
303 mailbox_size_sub(m, m->emails[i]);
304 }
305 /* remove message from the hash tables */
306 if (m->subj_hash && m->emails[i]->env->real_subj)
308 if (m->id_hash && m->emails[i]->env->message_id)
311
312 if (m->type == MUTT_IMAP)
314
315 mailbox_gc_add(m->emails[i]);
316 m->emails[i] = NULL;
317 }
318 }
319 m->msg_count = j;
320}
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:259
void mailbox_gc_add(struct Email *e)
Add an Email to the garbage-collection set.
Definition: mailbox.c:298
@ 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_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
void imap_notify_delete_email(struct Mailbox *m, struct Email *e)
Inform IMAP that an Email has been deleted.
Definition: imap.c:648
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:429
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1505
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:81
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
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:41
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
+ 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 364 of file mview.c.

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

◆ ea_add_tagged()

int ea_add_tagged ( struct EmailArray *  ea,
struct MailboxView mv,
struct Email e,
bool  use_tagged 
)

Get an array of the tagged Emails.

Parameters
eaEmpty EmailArray to populate
mvCurrent Mailbox
eCurrent Email
use_taggedUse tagged Emails
Return values
numNumber of selected emails
-1Error

Definition at line 378 of file mview.c.

379{
380 if (use_tagged)
381 {
382 if (!mv || !mv->mailbox || !mv->mailbox->emails)
383 return -1;
384
385 struct Mailbox *m = mv->mailbox;
386 for (int i = 0; i < m->msg_count; i++)
387 {
388 e = m->emails[i];
389 if (!e)
390 break;
391 if (!message_is_tagged(e))
392 continue;
393
394 ARRAY_ADD(ea, e);
395 }
396 }
397 else
398 {
399 if (!e)
400 return -1;
401
402 ARRAY_ADD(ea, e);
403 }
404
405 return ARRAY_SIZE(ea);
406}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:156
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
bool message_is_tagged(struct Email *e)
Is a message in the index tagged (and within limit)
Definition: mview.c:364
+ 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 418 of file mview.c.

419{
420 if (!m || !m->emails || !m->v2r)
421 return NULL;
422
423 if ((vnum < 0) || (vnum >= m->vcount))
424 return NULL;
425
426 int inum = m->v2r[vnum];
427 if ((inum < 0) || (inum >= m->msg_count))
428 return NULL;
429
430 return m->emails[inum];
431}
+ Here is the caller graph for this function:

◆ mview_has_limit()

bool mview_has_limit ( const struct MailboxView mv)

Is a limit active?

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

Definition at line 439 of file mview.c.

440{
441 return mv && mv->pattern;
442}
+ Here is the caller graph for this function:

◆ mview_mailbox()

struct Mailbox * mview_mailbox ( struct MailboxView mv)

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

Parameters
mvMailboxView
Return values
ptrThe mailbox in the MailboxView
NULLMailboxView is NULL or doesn't have a mailbox

Definition at line 450 of file mview.c.

451{
452 return mv ? mv->mailbox : NULL;
453}
+ Here is the caller graph for this function:

◆ top_of_thread()

static struct MuttThread * top_of_thread ( struct Email e)
static

Find the first email in the current thread.

Parameters
eCurrent Email
Return values
ptrSuccess, email found
NULLError

Definition at line 461 of file mview.c.

462{
463 if (!e)
464 return NULL;
465
466 struct MuttThread *t = e->thread;
467
468 while (t && t->parent)
469 t = t->parent;
470
471 return t;
472}
An Email conversation.
Definition: thread.h:34
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:44
+ Here is the caller graph for this function:

◆ mutt_limit_current_thread()

bool mutt_limit_current_thread ( struct MailboxView mv,
struct Email e 
)

Limit the email view to the current thread.

Parameters
mvMailbox View
eEmail
Return values
trueSuccess
falseFailure

Definition at line 481 of file mview.c.

482{
483 if (!mv || !mv->mailbox || !e)
484 return false;
485
486 struct Mailbox *m = mv->mailbox;
487
488 struct MuttThread *me = top_of_thread(e);
489 if (!me)
490 return false;
491
492 m->vcount = 0;
493 mv->vsize = 0;
494 mv->collapsed = false;
495
496 for (int i = 0; i < m->msg_count; i++)
497 {
498 e = m->emails[i];
499 if (!e)
500 break;
501
502 e->vnum = -1;
503 e->visible = false;
504 e->collapsed = false;
505 e->num_hidden = 0;
506
507 if (top_of_thread(e) == me)
508 {
509 struct Body *body = e->body;
510
511 e->vnum = m->vcount;
512 e->visible = true;
513 m->v2r[m->vcount] = i;
514 m->vcount++;
515 mv->vsize += (body->length + body->offset - body->hdr_offset);
516 }
517 }
518 return true;
519}
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: mview.c:461
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function: