NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pattern.c
Go to the documentation of this file.
1
26
32
33#include "config.h"
34#include <stdbool.h>
35#include <stddef.h>
36#include "mutt/lib.h"
37#include "config/lib.h"
38#include "email/lib.h"
39#include "core/lib.h"
40#include "alias/gui.h" // IWYU pragma: keep
41#include "alias/lib.h"
42#include "gui/lib.h"
43#include "mutt.h"
44#include "lib.h"
45#include "editor/lib.h"
46#include "history/lib.h"
47#include "imap/lib.h"
48#include "menu/lib.h"
49#include "progress/lib.h"
50#include "mutt_logging.h"
51#include "mx.h"
52#include "search_state.h"
53
65typedef bool (*eat_arg_t)(struct Pattern *pat, PatternCompFlags flags,
66 struct Buffer *s, struct Buffer *err);
67
73static void quote_simple(const char *str, struct Buffer *buf)
74{
75 buf_reset(buf);
76 buf_addch(buf, '"');
77 while (*str)
78 {
79 if ((*str == '\\') || (*str == '"'))
80 buf_addch(buf, '\\');
81 buf_addch(buf, *str++);
82 }
83 buf_addch(buf, '"');
84}
85
91void mutt_check_simple(struct Buffer *buf, const char *simple)
92{
93 bool do_simple = true;
94
95 for (const char *p = buf_string(buf); p && (p[0] != '\0'); p++)
96 {
97 if ((p[0] == '\\') && (p[1] != '\0'))
98 {
99 p++;
100 }
101 else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
102 {
103 do_simple = false;
104 break;
105 }
106 }
107
108 /* XXX - is mutt_istr_cmp() right here, or should we use locale's
109 * equivalences? */
110
111 if (do_simple) /* yup, so spoof a real request */
112 {
113 /* convert old tokens into the new format */
114 if (mutt_istr_equal("all", buf_string(buf)) || mutt_str_equal("^", buf_string(buf)) ||
115 mutt_str_equal(".", buf_string(buf))) /* ~A is more efficient */
116 {
117 buf_strcpy(buf, "~A");
118 }
119 else if (mutt_istr_equal("del", buf_string(buf)))
120 {
121 buf_strcpy(buf, "~D");
122 }
123 else if (mutt_istr_equal("flag", buf_string(buf)))
124 {
125 buf_strcpy(buf, "~F");
126 }
127 else if (mutt_istr_equal("new", buf_string(buf)))
128 {
129 buf_strcpy(buf, "~N");
130 }
131 else if (mutt_istr_equal("old", buf_string(buf)))
132 {
133 buf_strcpy(buf, "~O");
134 }
135 else if (mutt_istr_equal("repl", buf_string(buf)))
136 {
137 buf_strcpy(buf, "~Q");
138 }
139 else if (mutt_istr_equal("read", buf_string(buf)))
140 {
141 buf_strcpy(buf, "~R");
142 }
143 else if (mutt_istr_equal("tag", buf_string(buf)))
144 {
145 buf_strcpy(buf, "~T");
146 }
147 else if (mutt_istr_equal("unread", buf_string(buf)))
148 {
149 buf_strcpy(buf, "~U");
150 }
151 else
152 {
153 struct Buffer *tmp = buf_pool_get();
154 quote_simple(buf_string(buf), tmp);
155 mutt_file_expand_fmt(buf, simple, buf_string(tmp));
156 buf_pool_release(&tmp);
157 }
158 }
159}
160
170int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata,
171 enum PatternAlias action, struct Menu *menu)
172{
173 int rc = -1;
174 struct Progress *progress = NULL;
175 struct Buffer *buf = buf_pool_get();
176
177 buf_strcpy(buf, mdata->limit);
178 if (prompt)
179 {
180 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
181 buf_is_empty(buf))
182 {
183 buf_pool_release(&buf);
184 return -1;
185 }
186 }
187
188 mutt_message(_("Compiling search pattern..."));
189
190 /* Compile the pattern string; "~A" means match-all. If the simple string
191 * was expanded into a pattern, compile it for evaluation. */
192 bool match_all = false;
193 struct PatternList *pat = NULL;
194 char *simple = buf_strdup(buf);
195 if (simple)
196 {
198 const char *pbuf = buf->data;
199 while (*pbuf == ' ')
200 pbuf++;
201 match_all = mutt_str_equal(pbuf, "~A");
202
203 struct Buffer *err = buf_pool_get();
204 pat = mutt_pattern_comp(NULL, buf->data, MUTT_PC_FULL_MSG, err);
205 if (!pat)
206 {
207 mutt_error("%s", buf_string(err));
208 buf_pool_release(&err);
209 goto bail;
210 }
211 buf_pool_release(&err);
212 }
213 else
214 {
215 match_all = true;
216 }
217
218 progress = progress_new(MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
219 progress_set_message(progress, _("Executing command on matching messages..."));
220
221 /* Apply the action (tag, untag, or filter visibility) to each alias
222 * that matches the compiled pattern */
223 int vcounter = 0;
224 struct AliasView *avp = NULL;
225 ARRAY_FOREACH(avp, &mdata->ava)
226 {
227 progress_update(progress, ARRAY_FOREACH_IDX_avp, -1);
228
229 if (match_all ||
231 {
232 switch (action)
233 {
234 case PAA_TAG:
235 avp->is_tagged = true;
236 break;
237 case PAA_UNTAG:
238 avp->is_tagged = false;
239 break;
240 case PAA_VISIBLE:
241 avp->is_visible = true;
242 vcounter++;
243 break;
244 }
245 }
246 else
247 {
248 switch (action)
249 {
250 case PAA_TAG:
251 case PAA_UNTAG:
252 // Do nothing
253 break;
254 case PAA_VISIBLE:
255 avp->is_visible = false;
256 break;
257 }
258 }
259 }
260 progress_free(&progress);
261
262 FREE(&mdata->limit);
263 if (!match_all)
264 {
265 mdata->limit = simple;
266 simple = NULL;
267 }
268
269 if (menu && (action == PAA_VISIBLE))
270 {
271 menu->max = vcounter;
272 menu_set_index(menu, 0);
273 }
274
276
277 rc = 0;
278
279bail:
280 buf_pool_release(&buf);
281 FREE(&simple);
282 mutt_pattern_free(&pat);
283
284 return rc;
285}
286
295int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
296{
297 if (!mv || !mv->mailbox)
298 return -1;
299
300 struct Mailbox *m = mv->mailbox;
301
302 struct Buffer *err = NULL;
303 int rc = -1;
304 struct Progress *progress = NULL;
305 struct Buffer *buf = buf_pool_get();
306 bool interrupted = false;
307
308 buf_strcpy(buf, mv->pattern);
309 if (prompt || (op != MUTT_LIMIT))
310 {
311 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
312 buf_is_empty(buf))
313 {
314 buf_pool_release(&buf);
315 return -1;
316 }
317 }
318
319 mutt_message(_("Compiling search pattern..."));
320
321 char *simple = buf_strdup(buf);
322 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
323 mutt_check_simple(buf, NONULL(c_simple_search));
324 const char *pbuf = buf->data;
325 while (*pbuf == ' ')
326 pbuf++;
327 const bool match_all = mutt_str_equal(pbuf, "~A");
328
329 err = buf_pool_get();
330 struct PatternList *pat = mutt_pattern_comp(mv, buf->data, MUTT_PC_FULL_MSG, err);
331 if (!pat)
332 {
333 mutt_error("%s", buf_string(err));
334 goto bail;
335 }
336
337 if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
338 goto bail;
339
340 progress = progress_new(MUTT_PROGRESS_READ, (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
341 progress_set_message(progress, _("Executing command on matching messages..."));
342
343 if (op == MUTT_LIMIT)
344 {
345 m->vcount = 0;
346 mv->vsize = 0;
347 mv->collapsed = false;
348 int padding = mx_msg_padding_size(m);
349
350 for (int i = 0; i < m->msg_count; i++)
351 {
352 struct Email *e = m->emails[i];
353 if (!e)
354 break;
355
356 if (SigInt)
357 {
358 interrupted = true;
359 SigInt = false;
360 break;
361 }
362 progress_update(progress, i, -1);
363 /* new limit pattern implicitly uncollapses all threads */
364 e->vnum = -1;
365 e->visible = false;
366 e->limit_visited = true;
367 e->collapsed = false;
368 e->num_hidden = 0;
369
370 if (match_all ||
372 {
373 e->vnum = m->vcount;
374 e->visible = true;
375 m->v2r[m->vcount] = i;
376 m->vcount++;
377 struct Body *b = e->body;
378 mv->vsize += b->length + b->offset - b->hdr_offset + padding;
379 }
380 }
381 }
382 else
383 {
384 for (int i = 0; i < m->vcount; i++)
385 {
386 struct Email *e = mutt_get_virt_email(m, i);
387 if (!e)
388 continue;
389
390 if (SigInt)
391 {
392 interrupted = true;
393 SigInt = false;
394 break;
395 }
396 progress_update(progress, i, -1);
398 {
399 switch (op)
400 {
401 case MUTT_UNDELETE:
402 mutt_set_flag(m, e, MUTT_PURGE, false, true);
404
405 case MUTT_DELETE:
406 mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE), true);
407 break;
408 case MUTT_TAG:
409 case MUTT_UNTAG:
410 mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG), true);
411 break;
412
413 default:
414 break;
415 }
416 }
417 }
418 }
419 progress_free(&progress);
420
422
423 if (op == MUTT_LIMIT)
424 {
425 /* drop previous limit pattern */
426 FREE(&mv->pattern);
428
429 if (m->msg_count && !m->vcount)
430 mutt_error(_("No messages matched criteria"));
431
432 /* record new limit pattern, unless match all */
433 if (!match_all)
434 {
435 mv->pattern = simple;
436 simple = NULL; /* don't clobber it */
438 }
439 }
440
441 if (interrupted)
442 mutt_error(_("Search interrupted"));
443
444 rc = 0;
445
446bail:
447 buf_pool_release(&buf);
448 buf_pool_release(&err);
449 FREE(&simple);
450 mutt_pattern_free(&pat);
451
452 return rc;
453}
454
465int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur,
466 struct SearchState *state, SearchFlags flags)
467{
468 struct Progress *progress = NULL;
469 int rc = -1;
470 struct Mailbox *m = mv ? mv->mailbox : NULL;
471 if (!m)
472 return -1;
473 bool pattern_changed = false;
474
475 if (buf_is_empty(state->string) || (flags & SEARCH_PROMPT))
476 {
477 if ((mw_get_field((state->reverse) ? _("Reverse search for: ") : _("Search for: "),
479 &CompletePatternOps, NULL) != 0) ||
480 buf_is_empty(state->string))
481 {
482 goto done;
483 }
484
485 /* compare the *expanded* version of the search pattern in case
486 * $simple_search has changed while we were searching */
487 struct Buffer *tmp = buf_pool_get();
488 buf_copy(tmp, state->string);
489 const char *const c_simple_search = cs_subset_string(NeoMutt->sub, "simple_search");
490 mutt_check_simple(tmp, NONULL(c_simple_search));
491 if (!buf_str_equal(tmp, state->string_expn))
492 {
493 mutt_pattern_free(&state->pattern);
494 buf_copy(state->string_expn, tmp);
495 buf_pool_release(&tmp);
496 }
497 }
498
499 if (!state->pattern)
500 {
501 mutt_message(_("Compiling search pattern..."));
502 mutt_pattern_free(&state->pattern);
503 struct Buffer *err = buf_pool_get();
504 state->pattern = mutt_pattern_comp(mv, state->string_expn->data, MUTT_PC_FULL_MSG, err);
505 pattern_changed = true;
506 if (!state->pattern)
507 {
508 mutt_error("%s", buf_string(err));
509 buf_free(&err);
510 buf_reset(state->string);
511 buf_reset(state->string_expn);
512 return -1;
513 }
514 buf_free(&err);
516 }
517
518 if (pattern_changed)
519 {
520 for (int i = 0; i < m->msg_count; i++)
521 m->emails[i]->searched = false;
522 if ((m->type == MUTT_IMAP) && (!imap_search(m, state->pattern)))
523 return -1;
524 }
525
526 int incr = state->reverse ? -1 : 1;
527 if (flags & SEARCH_OPPOSITE)
528 incr = -incr;
529
530 progress = progress_new(MUTT_PROGRESS_READ, m->vcount);
531 progress_set_message(progress, _("Searching..."));
532
533 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
534 for (int i = cur + incr, j = 0; j != m->vcount; j++)
535 {
536 const char *msg = NULL;
537 progress_update(progress, j, -1);
538 if (i > m->vcount - 1)
539 {
540 i = 0;
541 if (c_wrap_search)
542 {
543 msg = _("Search wrapped to top");
544 }
545 else
546 {
547 mutt_message(_("Search hit bottom without finding match"));
548 goto done;
549 }
550 }
551 else if (i < 0)
552 {
553 i = m->vcount - 1;
554 if (c_wrap_search)
555 {
556 msg = _("Search wrapped to bottom");
557 }
558 else
559 {
560 mutt_message(_("Search hit top without finding match"));
561 goto done;
562 }
563 }
564
565 struct Email *e = mutt_get_virt_email(m, i);
566 if (!e)
567 goto done;
568
569 if (e->searched)
570 {
571 /* if we've already evaluated this message, use the cached value */
572 if (e->matched)
573 {
575 if (msg && *msg)
576 mutt_message("%s", msg);
577 rc = i;
578 goto done;
579 }
580 }
581 else
582 {
583 /* remember that we've already searched this message */
584 e->searched = true;
586 MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
587 if (e->matched)
588 {
590 if (msg && *msg)
591 mutt_message("%s", msg);
592 rc = i;
593 goto done;
594 }
595 }
596
597 if (SigInt)
598 {
599 mutt_error(_("Search interrupted"));
600 SigInt = false;
601 goto done;
602 }
603
604 i += incr;
605 }
606
607 mutt_error(_("Not found"));
608done:
609 progress_free(&progress);
610 return rc;
611}
612
622int mutt_search_alias_command(struct Menu *menu, int cur,
623 struct SearchState *state, SearchFlags flags)
624{
625 struct Progress *progress = NULL;
626 const struct AliasMenuData *mdata = menu->mdata;
627 const struct AliasViewArray *ava = &mdata->ava;
628 int rc = -1;
629 bool pattern_changed = false;
630
631 if (buf_is_empty(state->string) || flags & SEARCH_PROMPT)
632 {
633 if ((mw_get_field(state->reverse ? _("Reverse search for: ") : _("Search for: "),
635 &CompletePatternOps, NULL) != 0) ||
636 buf_is_empty(state->string))
637 {
638 goto done;
639 }
640
641 /* compare the *expanded* version of the search pattern in case
642 * $simple_search has changed while we were searching */
643 struct Buffer *tmp = buf_pool_get();
644 buf_copy(tmp, state->string);
646 if (!buf_str_equal(tmp, state->string_expn))
647 {
648 mutt_pattern_free(&state->pattern);
649 buf_copy(state->string_expn, tmp);
650 buf_pool_release(&tmp);
651 }
652 }
653
654 if (!state->pattern)
655 {
656 mutt_message(_("Compiling search pattern..."));
657 struct Buffer *err = buf_pool_get();
658 state->pattern = mutt_pattern_comp(NULL, state->string_expn->data, MUTT_PC_FULL_MSG, err);
659 pattern_changed = true;
660 if (!state->pattern)
661 {
662 mutt_error("%s", buf_string(err));
663 buf_free(&err);
664 buf_reset(state->string);
665 buf_reset(state->string_expn);
666 return -1;
667 }
668 buf_free(&err);
670 }
671
672 if (pattern_changed)
673 {
674 struct AliasView *av = NULL;
675 ARRAY_FOREACH(av, ava)
676 {
677 av->is_searched = false;
678 }
679 }
680
681 int incr = state->reverse ? -1 : 1;
682 if (flags & SEARCH_OPPOSITE)
683 incr = -incr;
684
686 progress_set_message(progress, _("Searching..."));
687
688 const bool c_wrap_search = cs_subset_bool(NeoMutt->sub, "wrap_search");
689 for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
690 {
691 const char *msg = NULL;
692 progress_update(progress, j, -1);
693 if (i > ARRAY_SIZE(ava) - 1)
694 {
695 i = 0;
696 if (c_wrap_search)
697 {
698 msg = _("Search wrapped to top");
699 }
700 else
701 {
702 mutt_message(_("Search hit bottom without finding match"));
703 goto done;
704 }
705 }
706 else if (i < 0)
707 {
708 i = ARRAY_SIZE(ava) - 1;
709 if (c_wrap_search)
710 {
711 msg = _("Search wrapped to bottom");
712 }
713 else
714 {
715 mutt_message(_("Search hit top without finding match"));
716 goto done;
717 }
718 }
719
720 struct AliasView *av = ARRAY_GET(ava, i);
721 if (av->is_searched)
722 {
723 /* if we've already evaluated this message, use the cached value */
724 if (av->is_matched)
725 {
727 if (msg && *msg)
728 mutt_message("%s", msg);
729 rc = i;
730 goto done;
731 }
732 }
733 else
734 {
735 /* remember that we've already searched this message */
736 av->is_searched = true;
738 MUTT_MATCH_FULL_ADDRESS, av, NULL);
739 if (av->is_matched)
740 {
742 if (msg && *msg)
743 mutt_message("%s", msg);
744 rc = i;
745 goto done;
746 }
747 }
748
749 if (SigInt)
750 {
751 mutt_error(_("Search interrupted"));
752 SigInt = false;
753 goto done;
754 }
755
756 i += incr;
757 }
758
759 mutt_error(_("Not found"));
760done:
761 progress_free(&progress);
762 return rc;
763}
Email Aliases.
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#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_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition buffer.c:326
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
Definition buffer.c:689
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:607
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition compile.c:964
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition compile.c:836
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
Edit a string.
@ MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:47
Structs that make up an email.
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:1367
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:54
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:502
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
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:60
IMAP network mailbox.
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition search.c:229
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
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:167
Convenience wrapper for the library headers.
#define FALLTHROUGH
Definition lib.h:117
#define _(a)
Definition message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
Many unsorted constants and some structs.
@ MUTT_UNDELETE
Messages to be un-deleted.
Definition mutt.h:95
@ MUTT_LIMIT
Messages in limited view.
Definition mutt.h:101
@ MUTT_UNTAG
Messages to be un-tagged.
Definition mutt.h:100
@ MUTT_PURGE
Messages to be purged (bypass trash).
Definition mutt.h:96
@ MUTT_TAG
Tagged messages.
Definition mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
void mutt_clear_error(void)
Clear the message line (bottom line of screen).
NeoMutt Logging.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition mview.c:378
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size().
Definition mx.c:1510
API for mailboxes.
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition complete.c:98
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:1183
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:1156
Match patterns to emails.
@ MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition lib.h:117
uint8_t PatternCompFlags
Definition lib.h:78
PatternAlias
What to do with the matching Aliases.
Definition lib.h:200
@ PAA_VISIBLE
Set AliasView.is_visible and hide the rest.
Definition lib.h:203
@ PAA_TAG
Set AliasView.is_tagged, but don't touch the others.
Definition lib.h:201
@ PAA_UNTAG
Unset AliasView.is_tagged, but don't touch the others.
Definition lib.h:202
#define MUTT_ALIAS_SIMPLESEARCH
Simple search pattern for aliases (from/to/cc fields).
Definition lib.h:64
@ MUTT_PC_FULL_MSG
Enable body and header matching.
Definition lib.h:74
bool(* eat_arg_t)(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Definition pattern.c:65
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, enum PatternAlias action, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition pattern.c:170
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition pattern.c:73
int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition pattern.c:465
int mutt_search_alias_command(struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition pattern.c:622
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition pattern.c:91
int mutt_pattern_func(struct MailboxView *mv, int op, char *prompt)
Perform some Pattern matching.
Definition pattern.c:295
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
Progress Bar.
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc.
Definition lib.h:84
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
#define SLIST_FIRST(head)
Definition queue.h:227
Holds state of a search.
uint8_t SearchFlags
@ SEARCH_PROMPT
Ask for search input.
@ SEARCH_OPPOSITE
Search in the opposite direction.
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition signal.c:68
#define NONULL(x)
Definition string2.h:44
AliasView array wrapper with Pattern information -.
Definition gui.h:55
char * limit
Limit being used.
Definition gui.h:61
struct AliasViewArray ava
All Aliases/Queries.
Definition gui.h:56
struct Menu * menu
Menu.
Definition gui.h:59
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_tagged
Is it tagged?
Definition gui.h:43
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:81
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: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 limit_visited
Has the limit pattern been applied to this message?
Definition email.h:122
bool collapsed
Is this message part of a collapsed thread?
Definition email.h:120
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:123
int vnum
Virtual message number.
Definition email.h:114
View of a Mailbox.
Definition mview.h:40
bool collapsed
Are all threads collapsed?
Definition mview.h:49
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:81
int vcount
The number of virtual messages.
Definition mailbox.h:101
int * v2r
Mapping from virtual to real msgno.
Definition mailbox.h:100
int msg_count
Total number of messages.
Definition mailbox.h:90
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
Definition lib.h:86
void * mdata
Private data.
Definition lib.h:155
int max
Number of entries in the menu.
Definition lib.h:88
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
A simple (non-regex) pattern.
Definition lib.h:84
Holds state of a search.
struct Buffer * string
search string
struct Buffer * string_expn
expanded search string
bool reverse
search backwards
struct PatternList * pattern
compiled search pattern