NeoMutt  2024-02-01-35-geee02f
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pattern.c
Go to the documentation of this file.
1
33#include "config.h"
34#include <stddef.h>
35#include <stdbool.h>
36#include "private.h"
37#include "mutt/lib.h"
38#include "config/lib.h"
39#include "email/lib.h"
40#include "core/lib.h"
41#include "alias/gui.h" // IWYU pragma: keep
42#include "alias/lib.h"
43#include "gui/lib.h"
44#include "mutt.h"
45#include "lib.h"
46#include "editor/lib.h"
47#include "history/lib.h"
48#include "imap/lib.h"
49#include "menu/lib.h"
50#include "progress/lib.h"
51#include "mutt_logging.h"
52#include "mview.h"
53#include "mx.h"
54#include "protos.h"
55#include "search_state.h"
56#ifndef USE_FMEMOPEN
57#include <sys/stat.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
94static void quote_simple(const char *str, struct Buffer *buf)
95{
96 buf_reset(buf);
97 buf_addch(buf, '"');
98 while (*str)
99 {
100 if ((*str == '\\') || (*str == '"'))
101 buf_addch(buf, '\\');
102 buf_addch(buf, *str++);
103 }
104 buf_addch(buf, '"');
105}
106
112void mutt_check_simple(struct Buffer *buf, const char *simple)
113{
114 bool do_simple = true;
115
116 for (const char *p = buf_string(buf); p && (p[0] != '\0'); p++)
117 {
118 if ((p[0] == '\\') && (p[1] != '\0'))
119 {
120 p++;
121 }
122 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
123 {
124 do_simple = false;
125 break;
126 }
127 }
128
129 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
130 * equivalences? */
131
132 if (do_simple) /* yup, so spoof a real request */
133 {
134 /* convert old tokens into the new format */
135 if (mutt_istr_equal("all", buf_string(buf)) || mutt_str_equal("^", buf_string(buf)) ||
136 mutt_str_equal(".", buf_string(buf))) /* ~A is more efficient */
137 {
138 buf_strcpy(buf, "~A");
139 }
140 else if (mutt_istr_equal("del", buf_string(buf)))
141 {
142 buf_strcpy(buf, "~D");
143 }
144 else if (mutt_istr_equal("flag", buf_string(buf)))
145 {
146 buf_strcpy(buf, "~F");
147 }
148 else if (mutt_istr_equal("new", buf_string(buf)))
149 {
150 buf_strcpy(buf, "~N");
151 }
152 else if (mutt_istr_equal("old", buf_string(buf)))
153 {
154 buf_strcpy(buf, "~O");
155 }
156 else if (mutt_istr_equal("repl", buf_string(buf)))
157 {
158 buf_strcpy(buf, "~Q");
159 }
160 else if (mutt_istr_equal("read", buf_string(buf)))
161 {
162 buf_strcpy(buf, "~R");
163 }
164 else if (mutt_istr_equal("tag", buf_string(buf)))
165 {
166 buf_strcpy(buf, "~T");
167 }
168 else if (mutt_istr_equal("unread", buf_string(buf)))
169 {
170 buf_strcpy(buf, "~U");
171 }
172 else
173 {
174 struct Buffer *tmp = buf_pool_get();
175 quote_simple(buf_string(buf), tmp);
176 mutt_file_expand_fmt(buf, simple, buf_string(tmp));
177 buf_pool_release(&tmp);
178 }
179 }
180}
181
190int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
191{
192 int rc = -1;
193 struct Progress *progress = NULL;
194 struct Buffer *buf = buf_pool_get();
195
196 buf_strcpy(buf, mdata->limit);
197 if (prompt)
198 {
199 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
200 buf_is_empty(buf))
201 {
202 buf_pool_release(&buf);
203 return -1;
204 }
205 }
206
207 mutt_message(_("Compiling search pattern..."));
208
209 bool match_all = false;
210 struct PatternList *pat = NULL;
211 char *simple = buf_strdup(buf);
212 if (simple)
213 {
215 const char *pbuf = buf->data;
216 while (*pbuf == ' ')
217 pbuf++;
218 match_all = mutt_str_equal(pbuf, "~A");
219
220 struct Buffer err = buf_make(0);
221 pat = mutt_pattern_comp(NULL, menu, buf->data, MUTT_PC_FULL_MSG, &err);
222 if (!pat)
223 {
224 mutt_error("%s", buf_string(&err));
225 buf_dealloc(&err);
226 goto bail;
227 }
228 }
229 else
230 {
231 match_all = true;
232 }
233
234 progress = progress_new(MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
235 progress_set_message(progress, _("Executing command on matching messages..."));
236
237 int vcounter = 0;
238 struct AliasView *avp = NULL;
239 ARRAY_FOREACH(avp, &mdata->ava)
240 {
241 progress_update(progress, ARRAY_FOREACH_IDX, -1);
242
243 if (match_all ||
245 {
246 avp->is_visible = true;
247 vcounter++;
248 }
249 else
250 {
251 avp->is_visible = false;
252 }
253 }
254 progress_free(&progress);
255
256 FREE(&mdata->limit);
257 if (!match_all)
258 {
259 mdata->limit = simple;
260 simple = NULL;
261 }
262
263 if (menu)
264 {
265 menu->max = vcounter;
266 menu_set_index(menu, 0);
267 }
268
270
271 rc = 0;
272
273bail:
274 buf_pool_release(&buf);
275 FREE(&simple);
276 mutt_pattern_free(&pat);
277
278 return rc;
279}
280
289int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
290{
291 if (!mv || !mv->mailbox)
292 return -1;
293
294 struct Mailbox *m = mv->mailbox;
295
296 struct Buffer *err = NULL;
297 int rc = -1;
298 struct Progress *progress = NULL;
299 struct Buffer *buf = buf_pool_get();
300
301 buf_strcpy(buf, mv->pattern);
302 if (prompt || (op != MUTT_LIMIT))
303 {
304 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
305 buf_is_empty(buf))
306 {
307 buf_pool_release(&buf);
308 return -1;
309 }
310 }
311
312 mutt_message(_("Compiling search pattern..."));
313
314 char *simple = buf_strdup(buf);
315 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
316 mutt_check_simple(buf, NONULL(c_simple_search));
317 const char *pbuf = buf->data;
318 while (*pbuf == ' ')
319 pbuf++;
320 const bool match_all = mutt_str_equal(pbuf, "~A");
321
322 err = buf_pool_get();
323 struct PatternList *pat = mutt_pattern_comp(mv, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
324 if (!pat)
325 {
326 mutt_error("%s", buf_string(err));
327 goto bail;
328 }
329
330 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
331 goto bail;
332
333 progress = progress_new(MUTT_PROGRESS_READ, (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
334 progress_set_message(progress, _("Executing command on matching messages..."));
335
336 if (op == MUTT_LIMIT)
337 {
338 m->vcount = 0;
339 mv->vsize = 0;
340 mv->collapsed = false;
341 int padding = mx_msg_padding_size(m);
342
343 for (int i = 0; i < m->msg_count; i++)
344 {
345 struct Email *e = m->emails[i];
346 if (!e)
347 break;
348
349 progress_update(progress, i, -1);
350 /* new limit pattern implicitly uncollapses all threads */
351 e->vnum = -1;
352 e->visible = false;
353 e->limit_visited = true;
354 e->collapsed = false;
355 e->num_hidden = 0;
356
357 if (match_all ||
359 {
360 e->vnum = m->vcount;
361 e->visible = true;
362 m->v2r[m->vcount] = i;
363 m->vcount++;
364 struct Body *b = e->body;
365 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
366 }
367 }
368 }
369 else
370 {
371 for (int i = 0; i < m->vcount; i++)
372 {
373 struct Email *e = mutt_get_virt_email(m, i);
374 if (!e)
375 continue;
376 progress_update(progress, i, -1);
378 {
379 switch (op)
380 {
381 case MUTT_UNDELETE:
382 mutt_set_flag(m, e, MUTT_PURGE, false, true);
384
385 case MUTT_DELETE:
386 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE), true);
387 break;
388 case MUTT_TAG:
389 case MUTT_UNTAG:
390 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG), true);
391 break;
392 }
393 }
394 }
395 }
396 progress_free(&progress);
397
399
400 if (op == MUTT_LIMIT)
401 {
402 /* drop previous limit pattern */
403 FREE(&mv->pattern);
405
406 if (m->msg_count && !m->vcount)
407 mutt_error(_("No messages matched criteria"));
408
409 /* record new limit pattern, unless match all */
410 if (!match_all)
411 {
412 mv->pattern = simple;
413 simple = NULL; /* don't clobber it */
414 mv->limit_pattern = mutt_pattern_comp(mv, mv->menu, buf->data, MUTT_PC_FULL_MSG, err);
415 }
416 }
417
418 rc = 0;
419
420bail:
421 buf_pool_release(&buf);
422 buf_pool_release(&err);
423 FREE(&simple);
424 mutt_pattern_free(&pat);
425
426 return rc;
427}
428
439int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur,
440 struct SearchState *state, SearchFlags flags)
441{
442 struct Progress *progress = NULL;
443 int rc = -1;
444 struct Mailbox *m = mv ? mv->mailbox : NULL;
445 if (!m)
446 return -1;
447 bool pattern_changed = false;
448
449 if (buf_is_empty(state->string) || (flags & SEARCH_PROMPT))
450 {
451 if ((mw_get_field((state->reverse) ? _("Reverse search for: ") : _("Search for: "),
453 &CompletePatternOps, NULL) != 0) ||
454 buf_is_empty(state->string))
455 {
456 goto done;
457 }
458
459 /* compare the *expanded* version of the search pattern in case
460 * $simple_search has changed while we were searching */
461 struct Buffer *tmp = buf_pool_get();
462 buf_copy(tmp, state->string);
463 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
464 mutt_check_simple(tmp, NONULL(c_simple_search));
465 if (!buf_str_equal(tmp, state->string_expn))
466 {
467 mutt_pattern_free(&state->pattern);
468 buf_copy(state->string_expn, tmp);
469 buf_pool_release(&tmp);
470 }
471 }
472
473 if (!state->pattern)
474 {
475 mutt_message(_("Compiling search pattern..."));
476 mutt_pattern_free(&state->pattern);
477 struct Buffer *err = buf_pool_get();
478 state->pattern = mutt_pattern_comp(mv, menu, state->string_expn->data,
479 MUTT_PC_FULL_MSG, err);
480 pattern_changed = true;
481 if (!state->pattern)
482 {
483 mutt_error("%s", buf_string(err));
484 buf_free(&err);
485 buf_reset(state->string);
486 buf_reset(state->string_expn);
487 return -1;
488 }
489 buf_free(&err);
491 }
492
493 if (pattern_changed)
494 {
495 for (int i = 0; i < m->msg_count; i++)
496 m->emails[i]->searched = false;
497 if ((m->type == MUTT_IMAP) && (!imap_search(m, state->pattern)))
498 return -1;
499 }
500
501 int incr = state->reverse ? -1 : 1;
502 if (flags & SEARCH_OPPOSITE)
503 incr = -incr;
504
505 progress = progress_new(MUTT_PROGRESS_READ, m->vcount);
506 progress_set_message(progress, _("Searching..."));
507
508 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
509 for (int i = cur + incr, j = 0; j != m->vcount; j++)
510 {
511 const char *msg = NULL;
512 progress_update(progress, j, -1);
513 if (i > m->vcount - 1)
514 {
515 i = 0;
516 if (c_wrap_search)
517 {
518 msg = _("Search wrapped to top");
519 }
520 else
521 {
522 mutt_message(_("Search hit bottom without finding match"));
523 goto done;
524 }
525 }
526 else if (i < 0)
527 {
528 i = m->vcount - 1;
529 if (c_wrap_search)
530 {
531 msg = _("Search wrapped to bottom");
532 }
533 else
534 {
535 mutt_message(_("Search hit top without finding match"));
536 goto done;
537 }
538 }
539
540 struct Email *e = mutt_get_virt_email(m, i);
541 if (!e)
542 goto done;
543
544 if (e->searched)
545 {
546 /* if we've already evaluated this message, use the cached value */
547 if (e->matched)
548 {
550 if (msg && *msg)
551 mutt_message("%s", msg);
552 rc = i;
553 goto done;
554 }
555 }
556 else
557 {
558 /* remember that we've already searched this message */
559 e->searched = true;
561 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
562 if (e->matched)
563 {
565 if (msg && *msg)
566 mutt_message("%s", msg);
567 rc = i;
568 goto done;
569 }
570 }
571
572 if (SigInt)
573 {
574 mutt_error(_("Search interrupted"));
575 SigInt = false;
576 goto done;
577 }
578
579 i += incr;
580 }
581
582 mutt_error(_("Not found"));
583done:
584 progress_free(&progress);
585 return rc;
586}
587
597int mutt_search_alias_command(struct Menu *menu, int cur,
598 struct SearchState *state, SearchFlags flags)
599{
600 struct Progress *progress = NULL;
601 const struct AliasMenuData *mdata = menu->mdata;
602 const struct AliasViewArray *ava = &mdata->ava;
603 int rc = -1;
604 bool pattern_changed = false;
605
606 if (buf_is_empty(state->string) || flags & SEARCH_PROMPT)
607 {
608 if ((mw_get_field((flags & OP_SEARCH_REVERSE) ? _("Reverse search for: ") : _("Search for: "),
610 &CompletePatternOps, NULL) != 0) ||
611 buf_is_empty(state->string))
612 {
613 goto done;
614 }
615
616 /* compare the *expanded* version of the search pattern in case
617 * $simple_search has changed while we were searching */
618 struct Buffer *tmp = buf_pool_get();
619 buf_copy(tmp, state->string);
621 if (!buf_str_equal(tmp, state->string_expn))
622 {
623 mutt_pattern_free(&state->pattern);
624 buf_copy(state->string_expn, tmp);
625 buf_pool_release(&tmp);
626 }
627 }
628
629 if (!state->pattern)
630 {
631 mutt_message(_("Compiling search pattern..."));
632 struct Buffer *err = buf_pool_get();
633 state->pattern = mutt_pattern_comp(NULL, menu, state->string_expn->data,
634 MUTT_PC_FULL_MSG, err);
635 pattern_changed = true;
636 if (!state->pattern)
637 {
638 mutt_error("%s", buf_string(err));
639 buf_free(&err);
640 buf_reset(state->string);
641 buf_reset(state->string_expn);
642 return -1;
643 }
644 buf_free(&err);
646 }
647
648 if (pattern_changed)
649 {
650 struct AliasView *av = NULL;
651 ARRAY_FOREACH(av, ava)
652 {
653 av->is_searched = false;
654 }
655 }
656
657 int incr = state->reverse ? -1 : 1;
658 if (flags & SEARCH_OPPOSITE)
659 incr = -incr;
660
662 progress_set_message(progress, _("Searching..."));
663
664 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
665 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
666 {
667 const char *msg = NULL;
668 progress_update(progress, j, -1);
669 if (i > ARRAY_SIZE(ava) - 1)
670 {
671 i = 0;
672 if (c_wrap_search)
673 {
674 msg = _("Search wrapped to top");
675 }
676 else
677 {
678 mutt_message(_("Search hit bottom without finding match"));
679 goto done;
680 }
681 }
682 else if (i < 0)
683 {
684 i = ARRAY_SIZE(ava) - 1;
685 if (c_wrap_search)
686 {
687 msg = _("Search wrapped to bottom");
688 }
689 else
690 {
691 mutt_message(_("Search hit top without finding match"));
692 goto done;
693 }
694 }
695
696 struct AliasView *av = ARRAY_GET(ava, i);
697 if (av->is_searched)
698 {
699 /* if we've already evaluated this message, use the cached value */
700 if (av->is_matched)
701 {
703 if (msg && *msg)
704 mutt_message("%s", msg);
705 rc = i;
706 goto done;
707 }
708 }
709 else
710 {
711 /* remember that we've already searched this message */
712 av->is_searched = true;
714 MUTT_MATCH_FULL_ADDRESS, av, NULL);
715 if (av->is_matched)
716 {
718 if (msg && *msg)
719 mutt_message("%s", msg);
720 rc = i;
721 goto done;
722 }
723 }
724
725 if (SigInt)
726 {
727 mutt_error(_("Search interrupted"));
728 SigInt = false;
729 goto done;
730 }
731
732 i += incr;
733 }
734
735 mutt_error(_("Not found"));
736done:
737 progress_free(&progress);
738 return rc;
739}
Email Aliases.
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:109
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:394
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:75
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:336
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:258
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition: buffer.c:702
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:618
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:588
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:905
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:777
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
Edit a string.
Structs that make up an email.
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:1160
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:1133
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:1512
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:57
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:274
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
Convenience wrapper for the gui headers.
Shared code for the Alias and Query Dialogs.
Read/write command history from/to a file.
@ HC_PATTERN
Patterns.
Definition: lib.h:55
IMAP network mailbox.
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition: search.c:227
#define FREE(x)
Definition: memory.h:45
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:173
Convenience wrapper for the library headers.
#define FALLTHROUGH
Definition: lib.h:111
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
Many unsorted constants and some structs.
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition: mutt.h:76
@ MUTT_LIMIT
Messages in limited view.
Definition: mutt.h:82
@ MUTT_UNTAG
Messages to be un-tagged.
Definition: mutt.h:81
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:77
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:80
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:75
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:57
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:418
View of a Mailbox.
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1503
API for mailboxes.
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition: complete.c:82
uint8_t PatternCompFlags
Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
Definition: lib.h:67
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:69
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:106
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:63
#define RANGE_GT_RX
Definition: private.h:109
#define RANGE_ABS_RX
Definition: private.h:105
#define RANGE_LT_RX
Definition: private.h:108
#define RANGE_BARE_RX
Definition: private.h:112
#define RANGE_REL_RX
Definition: private.h:101
@ RANGE_K_REL
Relative range.
Definition: private.h:89
@ RANGE_K_ABS
Absolute range.
Definition: private.h:90
@ RANGE_K_LT
Less-than range.
Definition: private.h:91
@ RANGE_K_BARE
Single symbol.
Definition: private.h:93
@ RANGE_K_GT
Greater-than range.
Definition: private.h:92
bool(* eat_arg_t)(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Definition: pattern.c:86
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:94
int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition: pattern.c:439
struct RangeRegex RangeRegexes[]
Set of Regexes for various range types.
Definition: pattern.c:65
int mutt_search_alias_command(struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition: pattern.c:597
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:190
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:112
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:289
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
Progress Bar.
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: lib.h:82
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:80
Prototypes for many functions.
#define SLIST_FIRST(head)
Definition: queue.h:229
Holds state of a search.
#define SEARCH_OPPOSITE
Search in the opposite direction.
Definition: search_state.h:46
uint8_t SearchFlags
Flags for a specific search, e.g. SEARCH_PROMPT.
Definition: search_state.h:43
#define SEARCH_PROMPT
Ask for search input.
Definition: search_state.h:45
GUI display the mailboxes in a side panel.
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition: signal.c:63
Key value store.
#define NONULL(x)
Definition: string2.h:37
AliasView array wrapper with Pattern information -.
Definition: gui.h:54
char * limit
Limit being used.
Definition: gui.h:60
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:55
struct Menu * menu
Menu.
Definition: gui.h:58
GUI data wrapping an Alias.
Definition: gui.h:38
bool is_visible
Is visible?
Definition: gui.h:45
bool is_matched
Search matches this Alias.
Definition: gui.h:42
bool is_searched
Alias has been searched.
Definition: gui.h:41
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:36
char * data
Pointer to data.
Definition: buffer.h:37
The envelope/body of an email.
Definition: email.h:39
bool searched
Email has been searched.
Definition: email.h:108
bool matched
Search matches this Email.
Definition: email.h:105
bool visible
Is this message part of the view?
Definition: email.h:124
bool limit_visited
Has the limit pattern been applied to this message?
Definition: email.h:125
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:123
struct Body * body
List of MIME parts.
Definition: email.h:69
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:126
int vnum
Virtual message number.
Definition: email.h:117
View of a Mailbox.
Definition: mview.h:40
bool collapsed
Are all threads collapsed?
Definition: mview.h:49
struct Menu * menu
Needed for pattern compilation.
Definition: mview.h:47
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:41
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: mview.h:43
struct Mailbox * mailbox
Current Mailbox.
Definition: mview.h:51
char * pattern
Limit pattern string.
Definition: mview.h:42
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:135
int max
Number of entries in the menu.
Definition: lib.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
A simple (non-regex) pattern.
Definition: lib.h:77
Regular expression representing a range.
Definition: private.h:76
Holds state of a search.
Definition: search_state.h:36
struct Buffer * string
search string
Definition: search_state.h:38
struct Buffer * string_expn
expanded search string
Definition: search_state.h:39
bool reverse
search backwards
Definition: search_state.h:40
struct PatternList * pattern
compiled search pattern
Definition: search_state.h:37