NeoMutt  2023-03-22
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 "globals.h" // IWYU pragma: keep
47#include "mutt_logging.h"
48#include "mview.h"
49#include "mx.h"
50#include "opcodes.h"
51#include "protos.h"
52#ifndef USE_FMEMOPEN
53#include <sys/stat.h>
54#endif
55#ifdef USE_IMAP
56#include "imap/lib.h"
57#endif
58
65 // clang-format off
66 [RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0, { 0 } },
67 [RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0, { 0 } },
68 [RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0, { 0 } },
69 [RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0, { 0 } },
70 [RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0, { 0 } },
71 // clang-format on
72};
73
85typedef bool (*eat_arg_t)(struct Pattern *pat, PatternCompFlags flags,
86 struct Buffer *s, struct Buffer *err);
87
88static struct PatternList *SearchPattern = NULL;
89static char LastSearch[256] = { 0 };
90static char LastSearchExpn[1024] = { 0 };
91
97static void quote_simple(const char *str, struct Buffer *buf)
98{
100 mutt_buffer_addch(buf, '"');
101 while (*str)
102 {
103 if ((*str == '\\') || (*str == '"'))
104 mutt_buffer_addch(buf, '\\');
105 mutt_buffer_addch(buf, *str++);
106 }
107 mutt_buffer_addch(buf, '"');
108}
109
115void mutt_check_simple(struct Buffer *buf, const char *simple)
116{
117 bool do_simple = true;
118
119 for (const char *p = mutt_buffer_string(buf); p && (p[0] != '\0'); p++)
120 {
121 if ((p[0] == '\\') && (p[1] != '\0'))
122 p++;
123 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
124 {
125 do_simple = false;
126 break;
127 }
128 }
129
130 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
131 * equivalences? */
132
133 if (do_simple) /* yup, so spoof a real request */
134 {
135 /* convert old tokens into the new format */
136 if (mutt_istr_equal("all", mutt_buffer_string(buf)) ||
138 mutt_str_equal(".", mutt_buffer_string(buf))) /* ~A is more efficient */
139 {
140 mutt_buffer_strcpy(buf, "~A");
141 }
142 else if (mutt_istr_equal("del", mutt_buffer_string(buf)))
143 mutt_buffer_strcpy(buf, "~D");
144 else if (mutt_istr_equal("flag", mutt_buffer_string(buf)))
145 mutt_buffer_strcpy(buf, "~F");
146 else if (mutt_istr_equal("new", mutt_buffer_string(buf)))
147 mutt_buffer_strcpy(buf, "~N");
148 else if (mutt_istr_equal("old", mutt_buffer_string(buf)))
149 mutt_buffer_strcpy(buf, "~O");
150 else if (mutt_istr_equal("repl", mutt_buffer_string(buf)))
151 mutt_buffer_strcpy(buf, "~Q");
152 else if (mutt_istr_equal("read", mutt_buffer_string(buf)))
153 mutt_buffer_strcpy(buf, "~R");
154 else if (mutt_istr_equal("tag", mutt_buffer_string(buf)))
155 mutt_buffer_strcpy(buf, "~T");
156 else if (mutt_istr_equal("unread", mutt_buffer_string(buf)))
157 mutt_buffer_strcpy(buf, "~U");
158 else
159 {
160 struct Buffer *tmp = mutt_buffer_pool_get();
162 mutt_file_expand_fmt(buf, simple, mutt_buffer_string(tmp));
164 }
165 }
166}
167
174static struct MuttThread *top_of_thread(struct Email *e)
175{
176 if (!e)
177 return NULL;
178
179 struct MuttThread *t = e->thread;
180
181 while (t && t->parent)
182 t = t->parent;
183
184 return t;
185}
186
194bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
195{
196 if (!mv || !mv->mailbox || !e)
197 return false;
198
199 struct Mailbox *m = mv->mailbox;
200
201 struct MuttThread *me = top_of_thread(e);
202 if (!me)
203 return false;
204
205 m->vcount = 0;
206 mv->vsize = 0;
207 mv->collapsed = false;
208
209 for (int i = 0; i < m->msg_count; i++)
210 {
211 e = m->emails[i];
212 if (!e)
213 break;
214
215 e->vnum = -1;
216 e->visible = false;
217 e->collapsed = false;
218 e->num_hidden = 0;
219
220 if (top_of_thread(e) == me)
221 {
222 struct Body *body = e->body;
223
224 e->vnum = m->vcount;
225 e->visible = true;
226 m->v2r[m->vcount] = i;
227 m->vcount++;
228 mv->vsize += (body->length + body->offset - body->hdr_offset);
229 }
230 }
231 return true;
232}
233
242int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
243{
244 int rc = -1;
245 struct Progress *progress = NULL;
246 struct Buffer *buf = mutt_buffer_pool_get();
247
248 mutt_buffer_strcpy(buf, mdata->limit);
249 if (prompt)
250 {
252 false, NULL, NULL, NULL) != 0) ||
254 {
256 return -1;
257 }
258 }
259
260 mutt_message(_("Compiling search pattern..."));
261
262 bool match_all = false;
263 struct PatternList *pat = NULL;
264 char *simple = mutt_buffer_strdup(buf);
265 if (simple)
266 {
268 const char *pbuf = buf->data;
269 while (*pbuf == ' ')
270 pbuf++;
271 match_all = mutt_str_equal(pbuf, "~A");
272
273 struct Buffer err = mutt_buffer_make(0);
274 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
275 if (!pat)
276 {
277 mutt_error("%s", mutt_buffer_string(&err));
279 goto bail;
280 }
281 }
282 else
283 {
284 match_all = true;
285 }
286
287 progress = progress_new(_("Executing command on matching messages..."),
289
290 int vcounter = 0;
291 struct AliasView *avp = NULL;
292 ARRAY_FOREACH(avp, &mdata->ava)
293 {
294 progress_update(progress, ARRAY_FOREACH_IDX, -1);
295
296 if (match_all ||
298 {
299 avp->is_visible = true;
300 vcounter++;
301 }
302 else
303 {
304 avp->is_visible = false;
305 }
306 }
307 progress_free(&progress);
308
309 FREE(&mdata->limit);
310 if (!match_all)
311 {
312 mdata->limit = simple;
313 simple = NULL;
314 }
315
316 if (menu)
317 {
318 menu->max = vcounter;
319 menu_set_index(menu, 0);
320 }
321
323
324 rc = 0;
325
326bail:
328 FREE(&simple);
329 mutt_pattern_free(&pat);
330
331 return rc;
332}
333
342int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
343{
344 if (!mv || !mv->mailbox)
345 return -1;
346
347 struct Mailbox *m = mv->mailbox;
348
349 struct Buffer *err = NULL;
350 int rc = -1;
351 struct Progress *progress = NULL;
352 struct Buffer *buf = mutt_buffer_pool_get();
353
355 if (prompt || (op != MUTT_LIMIT))
356 {
358 false, NULL, NULL, NULL) != 0) ||
360 {
362 return -1;
363 }
364 }
365
366 mutt_message(_("Compiling search pattern..."));
367
368 char *simple = mutt_buffer_strdup(buf);
369 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
370 mutt_check_simple(buf, NONULL(c_simple_search));
371 const char *pbuf = buf->data;
372 while (*pbuf == ' ')
373 pbuf++;
374 const bool match_all = mutt_str_equal(pbuf, "~A");
375
376 err = mutt_buffer_pool_get();
377 struct PatternList *pat = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
378 if (!pat)
379 {
380 mutt_error("%s", mutt_buffer_string(err));
381 goto bail;
382 }
383
384#ifdef USE_IMAP
385 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
386 goto bail;
387#endif
388
389 progress = progress_new(_("Executing command on matching messages..."), MUTT_PROGRESS_READ,
390 (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
391
392 if (op == MUTT_LIMIT)
393 {
394 m->vcount = 0;
395 mv->vsize = 0;
396 mv->collapsed = false;
397 int padding = mx_msg_padding_size(m);
398
399 for (int i = 0; i < m->msg_count; i++)
400 {
401 struct Email *e = m->emails[i];
402 if (!e)
403 break;
404
405 progress_update(progress, i, -1);
406 /* new limit pattern implicitly uncollapses all threads */
407 e->vnum = -1;
408 e->visible = false;
409 e->limit_visited = true;
410 e->collapsed = false;
411 e->num_hidden = 0;
412
413 if (match_all ||
415 {
416 e->vnum = m->vcount;
417 e->visible = true;
418 m->v2r[m->vcount] = i;
419 m->vcount++;
420 struct Body *b = e->body;
421 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
422 }
423 }
424 }
425 else
426 {
427 for (int i = 0; i < m->vcount; i++)
428 {
429 struct Email *e = mutt_get_virt_email(m, i);
430 if (!e)
431 continue;
432 progress_update(progress, i, -1);
434 {
435 switch (op)
436 {
437 case MUTT_UNDELETE:
438 mutt_set_flag(m, e, MUTT_PURGE, false);
439 /* fallthrough */
440 case MUTT_DELETE:
441 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
442 break;
443 case MUTT_TAG:
444 case MUTT_UNTAG:
445 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
446 break;
447 }
448 }
449 }
450 }
451 progress_free(&progress);
452
454
455 if (op == MUTT_LIMIT)
456 {
457 /* drop previous limit pattern */
458 FREE(&mv->pattern);
460
461 if (m->msg_count && !m->vcount)
462 mutt_error(_("No messages matched criteria"));
463
464 /* record new limit pattern, unless match all */
465 if (!match_all)
466 {
467 mv->pattern = simple;
468 simple = NULL; /* don't clobber it */
469 mv->limit_pattern = mutt_pattern_comp(m, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
470 }
471 }
472
473 rc = 0;
474
475bail:
478 FREE(&simple);
479 mutt_pattern_free(&pat);
480
481 return rc;
482}
483
493int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op)
494{
495 struct Progress *progress = NULL;
496 struct Buffer *buf = NULL;
497 int rc = -1;
498
499 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
500 {
501 buf = mutt_buffer_pool_get();
502 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
503 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
504 _("Search for: ") :
505 _("Reverse search for: "),
507 NULL, NULL, NULL) != 0) ||
509 {
510 goto done;
511 }
512
513 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
514 OptSearchReverse = false;
515 else
516 OptSearchReverse = true;
517
518 /* compare the *expanded* version of the search pattern in case
519 * $simple_search has changed while we were searching */
520 struct Buffer *tmp = mutt_buffer_pool_get();
521 mutt_buffer_copy(tmp, buf);
522 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
523 mutt_check_simple(tmp, NONULL(c_simple_search));
524
526 {
527 struct Buffer err;
528 mutt_buffer_init(&err);
529 OptSearchInvalid = true;
532 mutt_message(_("Compiling search pattern..."));
534 err.dsize = 256;
535 err.data = mutt_mem_malloc(err.dsize);
537 if (!SearchPattern)
538 {
541 mutt_error("%s", err.data);
542 FREE(&err.data);
543 LastSearch[0] = '\0';
544 LastSearchExpn[0] = '\0';
545 return -1;
546 }
547 FREE(&err.data);
549 }
550
552 }
553
555 {
556 for (int i = 0; i < m->msg_count; i++)
557 m->emails[i]->searched = false;
558#ifdef USE_IMAP
559 if ((m->type == MUTT_IMAP) && (!imap_search(m, SearchPattern)))
560 return -1;
561#endif
562 OptSearchInvalid = false;
563 }
564
565 int incr = OptSearchReverse ? -1 : 1;
566 if (op == OP_SEARCH_OPPOSITE)
567 incr = -incr;
568
569 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, m->vcount);
570
571 for (int i = cur + incr, j = 0; j != m->vcount; j++)
572 {
573 const char *msg = NULL;
574 progress_update(progress, j, -1);
575 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
576 if (i > m->vcount - 1)
577 {
578 i = 0;
579 if (c_wrap_search)
580 msg = _("Search wrapped to top");
581 else
582 {
583 mutt_message(_("Search hit bottom without finding match"));
584 goto done;
585 }
586 }
587 else if (i < 0)
588 {
589 i = m->vcount - 1;
590 if (c_wrap_search)
591 msg = _("Search wrapped to bottom");
592 else
593 {
594 mutt_message(_("Search hit top without finding match"));
595 goto done;
596 }
597 }
598
599 struct Email *e = mutt_get_virt_email(m, i);
600 if (e->searched)
601 {
602 /* if we've already evaluated this message, use the cached value */
603 if (e->matched)
604 {
606 if (msg && *msg)
607 mutt_message(msg);
608 rc = i;
609 goto done;
610 }
611 }
612 else
613 {
614 /* remember that we've already searched this message */
615 e->searched = true;
617 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
618 if (e->matched > 0)
619 {
621 if (msg && *msg)
622 mutt_message(msg);
623 rc = i;
624 goto done;
625 }
626 }
627
628 if (SigInt)
629 {
630 mutt_error(_("Search interrupted"));
631 SigInt = false;
632 goto done;
633 }
634
635 i += incr;
636 }
637
638 mutt_error(_("Not found"));
639done:
640 progress_free(&progress);
642 return rc;
643}
644
653int mutt_search_alias_command(struct Menu *menu, int cur, int op)
654{
655 struct Progress *progress = NULL;
656 const struct AliasMenuData *mdata = menu->mdata;
657 const struct AliasViewArray *ava = &mdata->ava;
658 struct Buffer *buf = NULL;
659 int rc = -1;
660
661 if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
662 {
663 buf = mutt_buffer_pool_get();
664 mutt_buffer_strcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "");
665 if ((mutt_buffer_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
666 _("Search for: ") :
667 _("Reverse search for: "),
669 NULL, NULL, NULL) != 0) ||
671 {
672 goto done;
673 }
674
675 if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
676 OptSearchReverse = false;
677 else
678 OptSearchReverse = true;
679
680 /* compare the *expanded* version of the search pattern in case
681 * $simple_search has changed while we were searching */
682 struct Buffer *tmp = mutt_buffer_pool_get();
683 mutt_buffer_copy(tmp, buf);
685
687 {
688 struct Buffer err;
689 mutt_buffer_init(&err);
690 OptSearchInvalid = true;
693 mutt_message(_("Compiling search pattern..."));
695 err.dsize = 256;
696 err.data = mutt_mem_malloc(err.dsize);
697 SearchPattern = mutt_pattern_comp(NULL, menu, tmp->data, MUTT_PC_FULL_MSG, &err);
698 if (!SearchPattern)
699 {
701 mutt_error("%s", err.data);
702 FREE(&err.data);
703 LastSearch[0] = '\0';
704 LastSearchExpn[0] = '\0';
705 return -1;
706 }
707 FREE(&err.data);
709 }
710
712 }
713
715 {
716 struct AliasView *av = NULL;
717 ARRAY_FOREACH(av, ava)
718 {
719 av->is_searched = false;
720 }
721
722 OptSearchInvalid = false;
723 }
724
725 int incr = OptSearchReverse ? -1 : 1;
726 if (op == OP_SEARCH_OPPOSITE)
727 incr = -incr;
728
729 progress = progress_new(_("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
730
731 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
732 {
733 const char *msg = NULL;
734 progress_update(progress, j, -1);
735 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
736 if (i > ARRAY_SIZE(ava) - 1)
737 {
738 i = 0;
739 if (c_wrap_search)
740 msg = _("Search wrapped to top");
741 else
742 {
743 mutt_message(_("Search hit bottom without finding match"));
744 goto done;
745 }
746 }
747 else if (i < 0)
748 {
749 i = ARRAY_SIZE(ava) - 1;
750 if (c_wrap_search)
751 msg = _("Search wrapped to bottom");
752 else
753 {
754 mutt_message(_("Search hit top without finding match"));
755 goto done;
756 }
757 }
758
759 struct AliasView *av = ARRAY_GET(ava, i);
760 if (av->is_searched)
761 {
762 /* if we've already evaluated this message, use the cached value */
763 if (av->is_matched)
764 {
766 if (msg && *msg)
767 mutt_message(msg);
768 rc = i;
769 goto done;
770 }
771 }
772 else
773 {
774 /* remember that we've already searched this message */
775 av->is_searched = true;
777 MUTT_MATCH_FULL_ADDRESS, av, NULL);
778 if (av->is_matched > 0)
779 {
781 if (msg && *msg)
782 mutt_message(msg);
783 rc = i;
784 goto done;
785 }
786 }
787
788 if (SigInt)
789 {
790 mutt_error(_("Search interrupted"));
791 SigInt = false;
792 goto done;
793 }
794
795 i += incr;
796 }
797
798 mutt_error(_("Not found"));
799done:
800 progress_free(&progress);
802 return rc;
803}
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:298
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:347
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:500
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:485
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
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:1159
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1037
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:178
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:1143
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:1116
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:1519
bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: globals.c:85
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.c:58
bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: globals.c:86
#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:64
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:84
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:90
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:89
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:85
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:88
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:83
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:65
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
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:1548
API for mailboxes.
All user-callable functions.
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:88
int mutt_search_alias_command(struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:653
bool(* eat_arg_t)(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Definition: pattern.c:85
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:90
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:97
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:89
bool mutt_limit_current_thread(struct MailboxView *mv, struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:194
struct RangeRegex RangeRegexes[]
Set of Regexes for various range types.
Definition: pattern.c:64
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:174
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:242
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:115
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:342
int mutt_search_command(struct Mailbox *m, struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:493
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:104
bool matched
Search matches this Email.
Definition: email.h:101
bool visible
Is this message part of the view?
Definition: email.h:120
bool limit_visited
Has the limit pattern been applied to this message?
Definition: email.h:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:119
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:113
struct MuttThread * thread
Thread of Emails.
Definition: email.h:118
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:70
void * mdata
Private data.
Definition: lib.h:138
int max
Number of entries in the menu.
Definition: lib.h:72
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