NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
pattern.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <stddef.h>
33#include <stdbool.h>
34#include "private.h"
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "email/lib.h"
38#include "core/lib.h"
39#include "alias/gui.h" // IWYU pragma: keep
40#include "alias/lib.h"
41#include "mutt.h"
42#include "lib.h"
43#include "enter/lib.h"
44#include "menu/lib.h"
45#include "progress/lib.h"
46#include "mutt_globals.h"
47#include "mutt_logging.h"
48#include "mview.h"
49#include "mx.h"
50#include "opcodes.h"
51#include "options.h"
52#include "protos.h"
53#ifndef USE_FMEMOPEN
54#include <sys/stat.h>
55#endif
56#ifdef USE_IMAP
57#include "imap/lib.h"
58#endif
59
66 // clang-format off
67 [RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0, { 0 } },
68 [RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0, { 0 } },
69 [RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0, { 0 } },
70 [RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0, { 0 } },
71 [RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0, { 0 } },
72 // clang-format on
73};
74
86typedef bool (*eat_arg_t)(struct Pattern *pat, PatternCompFlags flags,
87 struct Buffer *s, struct Buffer *err);
88
89static struct PatternList *SearchPattern = NULL;
90static char LastSearch[256] = { 0 };
91static char LastSearchExpn[1024] = { 0 };
92
98static void quote_simple(const char *str, struct Buffer *buf)
99{
101 mutt_buffer_addch(buf, '"');
102 while (*str)
103 {
104 if ((*str == '\\') || (*str == '"'))
105 mutt_buffer_addch(buf, '\\');
106 mutt_buffer_addch(buf, *str++);
107 }
108 mutt_buffer_addch(buf, '"');
109}
110
116void mutt_check_simple(struct Buffer *buf, const char *simple)
117{
118 bool do_simple = true;
119
120 for (const char *p = mutt_buffer_string(buf); p && (p[0] != '\0'); p++)
121 {
122 if ((p[0] == '\\') && (p[1] != '\0'))
123 p++;
124 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
125 {
126 do_simple = false;
127 break;
128 }
129 }
130
131 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
132 * equivalences? */
133
134 if (do_simple) /* yup, so spoof a real request */
135 {
136 /* convert old tokens into the new format */
137 if (mutt_istr_equal("all", mutt_buffer_string(buf)) ||
139 mutt_str_equal(".", mutt_buffer_string(buf))) /* ~A is more efficient */
140 {
141 mutt_buffer_strcpy(buf, "~A");
142 }
143 else if (mutt_istr_equal("del", mutt_buffer_string(buf)))
144 mutt_buffer_strcpy(buf, "~D");
145 else if (mutt_istr_equal("flag", mutt_buffer_string(buf)))
146 mutt_buffer_strcpy(buf, "~F");
147 else if (mutt_istr_equal("new", mutt_buffer_string(buf)))
148 mutt_buffer_strcpy(buf, "~N");
149 else if (mutt_istr_equal("old", mutt_buffer_string(buf)))
150 mutt_buffer_strcpy(buf, "~O");
151 else if (mutt_istr_equal("repl", mutt_buffer_string(buf)))
152 mutt_buffer_strcpy(buf, "~Q");
153 else if (mutt_istr_equal("read", mutt_buffer_string(buf)))
154 mutt_buffer_strcpy(buf, "~R");
155 else if (mutt_istr_equal("tag", mutt_buffer_string(buf)))
156 mutt_buffer_strcpy(buf, "~T");
157 else if (mutt_istr_equal("unread", mutt_buffer_string(buf)))
158 mutt_buffer_strcpy(buf, "~U");
159 else
160 {
161 struct Buffer *tmp = mutt_buffer_pool_get();
163 mutt_file_expand_fmt(buf, simple, mutt_buffer_string(tmp));
165 }
166 }
167}
168
175static struct MuttThread *top_of_thread(struct Email *e)
176{
177 if (!e)
178 return NULL;
179
180 struct MuttThread *t = e->thread;
181
182 while (t && t->parent)
183 t = t->parent;
184
185 return t;
186}
187
195bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
196{
197 if (!mv || !mv->mailbox || !e)
198 return false;
199
200 struct Mailbox *m = mv->mailbox;
201
202 struct MuttThread *me = top_of_thread(e);
203 if (!me)
204 return false;
205
206 m->vcount = 0;
207 mv->vsize = 0;
208 mv->collapsed = false;
209
210 for (int i = 0; i < m->msg_count; i++)
211 {
212 e = m->emails[i];
213 if (!e)
214 break;
215
216 e->vnum = -1;
217 e->visible = false;
218 e->collapsed = false;
219 e->num_hidden = 0;
220
221 if (top_of_thread(e) == me)
222 {
223 struct Body *body = e->body;
224
225 e->vnum = m->vcount;
226 e->visible = true;
227 m->v2r[m->vcount] = i;
228 m->vcount++;
229 mv->vsize += (body->length + body->offset - body->hdr_offset);
230 }
231 }
232 return true;
233}
234
243int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
244{
245 int rc = -1;
246 struct Progress *progress = NULL;
247 struct Buffer *buf = mutt_buffer_pool_get();
248
249 mutt_buffer_strcpy(buf, mdata->limit);
250 if (prompt)
251 {
253 false, NULL, NULL, NULL) != 0) ||
255 {
257 return -1;
258 }
259 }
260
261 mutt_message(_("Compiling search pattern..."));
262
263 bool match_all = false;
264 struct PatternList *pat = NULL;
265 char *simple = mutt_buffer_strdup(buf);
266 if (simple)
267 {
269 const char *pbuf = buf->data;
270 while (*pbuf == ' ')
271 pbuf++;
272 match_all = mutt_str_equal(pbuf, "~A");
273
274 struct Buffer err = mutt_buffer_make(0);
275 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
276 if (!pat)
277 {
278 mutt_error("%s", mutt_buffer_string(&err));
280 goto bail;
281 }
282 }
283 else
284 {
285 match_all = true;
286 }
287
288 progress = progress_new(_("Executing command on matching messages..."),
290
291 int vcounter = 0;
292 struct AliasView *avp = NULL;
293 ARRAY_FOREACH(avp, &mdata->ava)
294 {
295 progress_update(progress, ARRAY_FOREACH_IDX, -1);
296
297 if (match_all ||
299 {
300 avp->is_visible = true;
301 vcounter++;
302 }
303 else
304 {
305 avp->is_visible = false;
306 }
307 }
308 progress_free(&progress);
309
310 FREE(&mdata->limit);
311 if (!match_all)
312 {
313 mdata->limit = simple;
314 simple = NULL;
315 }
316
317 if (menu)
318 {
319 menu->max = vcounter;
320 menu_set_index(menu, 0);
321 }
322
324
325 rc = 0;
326
327bail:
329 FREE(&simple);
330 mutt_pattern_free(&pat);
331
332 return rc;
333}
334
343int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
344{
345 if (!mv || !mv->mailbox)
346 return -1;
347
348 struct Mailbox *m = mv->mailbox;
349
350 struct Buffer *err = NULL;
351 int rc = -1;
352 struct Progress *progress = NULL;
353 struct Buffer *buf = mutt_buffer_pool_get();
354
356 if (prompt || (op != MUTT_LIMIT))
357 {
359 false, NULL, NULL, NULL) != 0) ||
361 {
363 return -1;
364 }
365 }
366
367 mutt_message(_("Compiling search pattern..."));
368
369 char *simple = mutt_buffer_strdup(buf);
370 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
371 mutt_check_simple(buf, NONULL(c_simple_search));
372 const char *pbuf = buf->data;
373 while (*pbuf == ' ')
374 pbuf++;
375 const bool match_all = mutt_str_equal(pbuf, "~A");
376
377 err = mutt_buffer_pool_get();
378 struct PatternList *pat = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
379 if (!pat)
380 {
381 mutt_error("%s", mutt_buffer_string(err));
382 goto bail;
383 }
384
385#ifdef USE_IMAP
386 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
387 goto bail;
388#endif
389
390 progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
391 (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
392
393 if (op == MUTT_LIMIT)
394 {
395 m->vcount = 0;
396 mv->vsize = 0;
397 mv->collapsed = false;
398 int padding = mx_msg_padding_size(m);
399
400 for (int i = 0; i < m->msg_count; i++)
401 {
402 struct Email *e = m->emails[i];
403 if (!e)
404 break;
405
406 progress_update(progress, i, -1);
407 /* new limit pattern implicitly uncollapses all threads */
408 e->vnum = -1;
409 e->visible = false;
410 e->collapsed = false;
411 e->num_hidden = 0;
412 if (match_all ||
414 {
415 e->vnum = m->vcount;
416 e->visible = true;
417 m->v2r[m->vcount] = i;
418 m->vcount++;
419 struct Body *b = e->body;
420 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
421 }
422 }
423 }
424 else
425 {
426 for (int i = 0; i < m->vcount; i++)
427 {
428 struct Email *e = mutt_get_virt_email(m, i);
429 if (!e)
430 continue;
431 progress_update(progress, i, -1);
433 {
434 switch (op)
435 {
436 case MUTT_UNDELETE:
437 mutt_set_flag(m, e, MUTT_PURGE, false);
438 /* fallthrough */
439 case MUTT_DELETE:
440 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
441 break;
442 case MUTT_TAG:
443 case MUTT_UNTAG:
444 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
445 break;
446 }
447 }
448 }
449 }
450 progress_free(&progress);
451
453
454 if (op == MUTT_LIMIT)
455 {
456 /* drop previous limit pattern */
457 FREE(&mv->pattern);
459
460 if (m->msg_count && !m->vcount)
461 mutt_error(_("No messages matched criteria"));
462
463 /* record new limit pattern, unless match all */
464 if (!match_all)
465 {
466 mv->pattern = simple;
467 simple = NULL; /* don't clobber it */
468 mv->limit_pattern = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
469 }
470 }
471
472 rc = 0;
473
474bail:
477 FREE(&simple);
478 mutt_pattern_free(&pat);
479
480 return rc;
481}
482
492int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op)
493{
494 struct Progress *progress = NULL;
495 struct Buffer *buf = NULL;
496 int rc = -1;
497
498 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
499 {
500 buf = mutt_buffer_pool_get();
501 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
502 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
503 _("Search for: ") :
504 _("Reverse search for: "),
506 NULL, NULL, NULL) != 0) ||
508 {
509 goto done;
510 }
511
512 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
513 OptSearchReverse = false;
514 else
515 OptSearchReverse = true;
516
517 /* compare the *expanded* version of the search pattern in case
518 * $simple_search has changed while we were searching */
519 struct Buffer *tmp = mutt_buffer_pool_get();
520 mutt_buffer_copy(tmp, buf);
521 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
522 mutt_check_simple(tmp, NONULL(c_simple_search));
523
525 {
526 struct Buffer err;
527 mutt_buffer_init(&err);
528 OptSearchInvalid = true;
531 mutt_message(_("Compiling search pattern..."));
533 err.dsize = 256;
534 err.data = mutt_mem_malloc(err.dsize);
536 if (!SearchPattern)
537 {
540 mutt_error("%s", err.data);
541 FREE(&err.data);
542 LastSearch[0] = '\0';
543 LastSearchExpn[0] = '\0';
544 return -1;
545 }
546 FREE(&err.data);
548 }
549
551 }
552
554 {
555 for (int i = 0; i < m->msg_count; i++)
556 m->emails[i]->searched = false;
557#ifdef USE_IMAP
558 if ((m->type == MUTT_IMAP) && (!imap_search(m, SearchPattern)))
559 return -1;
560#endif
561 OptSearchInvalid = false;
562 }
563
564 int incr = OptSearchReverse ? -1 : 1;
565 if (op == OP_SEARCH_OPPOSITE)
566 incr = -incr;
567
568 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, m->vcount);
569
570 for (int i = cur + incr, j = 0; j != m->vcount; j++)
571 {
572 const char *msg = NULL;
573 progress_update(progress, j, -1);
574 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
575 if (i > m->vcount - 1)
576 {
577 i = 0;
578 if (c_wrap_search)
579 msg = _("Search wrapped to top");
580 else
581 {
582 mutt_message(_("Search hit bottom without finding match"));
583 goto done;
584 }
585 }
586 else if (i < 0)
587 {
588 i = m->vcount - 1;
589 if (c_wrap_search)
590 msg = _("Search wrapped to bottom");
591 else
592 {
593 mutt_message(_("Search hit top without finding match"));
594 goto done;
595 }
596 }
597
598 struct Email *e = mutt_get_virt_email(m, i);
599 if (e->searched)
600 {
601 /* if we've already evaluated this message, use the cached value */
602 if (e->matched)
603 {
605 if (msg && *msg)
606 mutt_message(msg);
607 rc = i;
608 goto done;
609 }
610 }
611 else
612 {
613 /* remember that we've already searched this message */
614 e->searched = true;
616 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
617 if (e->matched > 0)
618 {
620 if (msg && *msg)
621 mutt_message(msg);
622 rc = i;
623 goto done;
624 }
625 }
626
627 if (SigInt)
628 {
629 mutt_error(_("Search interrupted"));
630 SigInt = false;
631 goto done;
632 }
633
634 i += incr;
635 }
636
637 mutt_error(_("Not found"));
638done:
639 progress_free(&progress);
641 return rc;
642}
643
652int mutt_search_alias_command(struct Menu *menu, int cur, int op)
653{
654 struct Progress *progress = NULL;
655 const struct AliasMenuData *mdata = menu->mdata;
656 const struct AliasViewArray *ava = &mdata->ava;
657 struct Buffer *buf = NULL;
658 int rc = -1;
659
660 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
661 {
662 buf = mutt_buffer_pool_get();
663 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
664 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
665 _("Search for: ") :
666 _("Reverse search for: "),
668 NULL, NULL, NULL) != 0) ||
670 {
671 goto done;
672 }
673
674 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
675 OptSearchReverse = false;
676 else
677 OptSearchReverse = true;
678
679 /* compare the *expanded* version of the search pattern in case
680 * $simple_search has changed while we were searching */
681 struct Buffer *tmp = mutt_buffer_pool_get();
682 mutt_buffer_copy(tmp, buf);
684
686 {
687 struct Buffer err;
688 mutt_buffer_init(&err);
689 OptSearchInvalid = true;
692 mutt_message(_("Compiling search pattern..."));
694 err.dsize = 256;
695 err.data = mutt_mem_malloc(err.dsize);
696 SearchPattern = mutt_pattern_comp(NULL, menu, tmp->data, MUTT_PC_FULL_MSG, &err);
697 if (!SearchPattern)
698 {
700 mutt_error("%s", err.data);
701 FREE(&err.data);
702 LastSearch[0] = '\0';
703 LastSearchExpn[0] = '\0';
704 return -1;
705 }
706 FREE(&err.data);
708 }
709
711 }
712
714 {
715 struct AliasView *av = NULL;
716 ARRAY_FOREACH(av, ava)
717 {
718 av->is_searched = false;
719 }
720
721 OptSearchInvalid = false;
722 }
723
724 int incr = OptSearchReverse ? -1 : 1;
725 if (op == OP_SEARCH_OPPOSITE)
726 incr = -incr;
727
728 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
729
730 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
731 {
732 const char *msg = NULL;
733 progress_update(progress, j, -1);
734 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
735 if (i > ARRAY_SIZE(ava) - 1)
736 {
737 i = 0;
738 if (c_wrap_search)
739 msg = _("Search wrapped to top");
740 else
741 {
742 mutt_message(_("Search hit bottom without finding match"));
743 goto done;
744 }
745 }
746 else if (i < 0)
747 {
748 i = ARRAY_SIZE(ava) - 1;
749 if (c_wrap_search)
750 msg = _("Search wrapped to bottom");
751 else
752 {
753 mutt_message(_("Search hit top without finding match"));
754 goto done;
755 }
756 }
757
758 struct AliasView *av = ARRAY_GET(ava, i);
759 if (av->is_searched)
760 {
761 /* if we've already evaluated this message, use the cached value */
762 if (av->is_matched)
763 {
765 if (msg && *msg)
766 mutt_message(msg);
767 rc = i;
768 goto done;
769 }
770 }
771 else
772 {
773 /* remember that we've already searched this message */
774 av->is_searched = true;
776 MUTT_MATCH_FULL_ADDRESS, av, NULL);
777 if (av->is_matched > 0)
778 {
780 if (msg && *msg)
781 mutt_message(msg);
782 rc = i;
783 goto done;
784 }
785 }
786
787 if (SigInt)
788 {
789 mutt_error(_("Search interrupted"));
790 SigInt = false;
791 goto done;
792 }
793
794 i += incr;
795 }
796
797 mutt_error(_("Not found"));
798done:
799 progress_free(&progress);
801 return rc;
802}
Email Aliases.
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:108
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:52
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1160
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
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.
Structs that make up an email.
Enter a string.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
bool mutt_pattern_alias_exec(struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Match a pattern against an alias.
Definition: exec.c:1134
bool mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:1107
void mutt_file_expand_fmt(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1503
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
Shared code for the Alias and Query Dialogs.
IMAP network mailbox.
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition: search.c:229
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
GUI present the user with a selectable list.
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:168
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:652
Many unsorted constants and some structs.
#define MUTT_COMP_PATTERN
Pattern mode (in pattern dialog)
Definition: mutt.h:61
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:96
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:102
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:101
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:97
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:100
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:95
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
Hundreds of global variables to back the user variables.
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:69
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
NeoMutt Logging.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: mview.c:414
The "currently-open" mailbox.
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.
All user-callable functions.
Handling of global boolean variables.
bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: options.h:57
bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: options.h:58
uint8_t PatternCompFlags
Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
Definition: lib.h:60
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:62
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:99
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:58
#define RANGE_GT_RX
Definition: private.h:106
#define RANGE_ABS_RX
Definition: private.h:102
#define RANGE_LT_RX
Definition: private.h:105
#define RANGE_BARE_RX
Definition: private.h:109
#define RANGE_REL_RX
Definition: private.h:98
@ RANGE_K_REL
Relative range.
Definition: private.h:86
@ RANGE_K_ABS
Absolute range.
Definition: private.h:87
@ RANGE_K_LT
Less-than range.
Definition: private.h:88
@ RANGE_K_BARE
Single symbol.
Definition: private.h:90
@ RANGE_K_GT
Greater-than range.
Definition: private.h:89
static struct PatternList * SearchPattern
current search pattern
Definition: pattern.c:89
int mutt_search_alias_command(struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:652
bool(* eat_arg_t)(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Definition: pattern.c:86
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:91
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:98
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:90
bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:195
struct RangeRegex RangeRegexes[]
Set of Regexes for various range types.
Definition: pattern.c:65
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:175
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:243
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:116
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:343
int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:492
static unsigned char * pbuf
Cached PGP data packet.
Definition: pgppacket.c:38
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Progress bar.
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: lib.h:49
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:86
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:73
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:118
Prototypes for many functions.
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:63
#define SLIST_FIRST(head)
Definition: queue.h:229
GUI display the mailboxes in a side panel.
Key value store.
#define NONULL(x)
Definition: string2.h:37
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
char * limit
Limit being used.
Definition: gui.h:58
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:53
struct Menu * menu
Menu.
Definition: gui.h:56
GUI data wrapping an Alias.
Definition: gui.h:36
bool is_visible
Is visible?
Definition: gui.h:43
bool is_matched
Search matches this Alias.
Definition: gui.h:40
bool is_searched
Alias has been searched.
Definition: gui.h:39
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
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
bool searched
Email has been searched.
Definition: email.h:105
bool matched
Search matches this Email.
Definition: email.h:102
bool visible
Is this message part of the view?
Definition: email.h:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
struct Body * body
List of MIME parts.
Definition: email.h:67
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:122
int vnum
Virtual message number.
Definition: email.h:114
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
The "current" mailbox.
Definition: mview.h:38
bool collapsed
Are all threads collapsed?
Definition: mview.h:47
struct Menu * menu
Needed for pattern compilation.
Definition: mview.h:45
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:39
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:41
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
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
Definition: lib.h:69
void * mdata
Private data.
Definition: lib.h:137
int max
Number of entries in the menu.
Definition: lib.h:71
An Email conversation.
Definition: thread.h:35
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A simple (non-regex) pattern.
Definition: lib.h:70
Regular expression representing a range.
Definition: private.h:73