NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
pattern.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdbool.h>
33 #include "private.h"
34 #include "mutt/lib.h"
35 #include "email/lib.h"
36 #include "core/lib.h"
37 #include "alias/gui.h"
38 #include "gui/lib.h"
39 #include "mutt.h"
40 #include "lib.h"
41 #include "context.h"
42 #include "mutt_globals.h"
43 #include "mutt_logging.h"
44 #include "mutt_menu.h"
45 #include "mx.h"
46 #include "opcodes.h"
47 #include "options.h"
48 #include "progress.h"
49 #include "protos.h"
50 #ifndef USE_FMEMOPEN
51 #include <sys/stat.h>
52 #endif
53 #ifdef USE_IMAP
54 #include "imap/lib.h"
55 #endif
56 
57 // clang-format off
63 struct RangeRegex range_regexes[] = {
64  [RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0, { 0 } },
65  [RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0, { 0 } },
66  [RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0, { 0 } },
67  [RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0, { 0 } },
68  [RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0, { 0 } },
69 };
70 // clang-format on
71 
80 bool (*eat_arg_t)(struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err);
81 
82 static struct PatternList *SearchPattern = NULL;
83 static char LastSearch[256] = { 0 };
84 static char LastSearchExpn[1024] = { 0 };
85 
91 static void quote_simple(const char *str, struct Buffer *buf)
92 {
93  mutt_buffer_reset(buf);
94  mutt_buffer_addch(buf, '"');
95  while (*str)
96  {
97  if ((*str == '\\') || (*str == '"'))
98  mutt_buffer_addch(buf, '\\');
99  mutt_buffer_addch(buf, *str++);
100  }
101  mutt_buffer_addch(buf, '"');
102 }
103 
109 void mutt_check_simple(struct Buffer *buf, const char *simple)
110 {
111  bool do_simple = true;
112 
113  for (const char *p = mutt_b2s(buf); p && (p[0] != '\0'); p++)
114  {
115  if ((p[0] == '\\') && (p[1] != '\0'))
116  p++;
117  else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
118  {
119  do_simple = false;
120  break;
121  }
122  }
123 
124  /* XXX - is mutt_istr_cmp() right here, or should we use locale's
125  * equivalences? */
126 
127  if (do_simple) /* yup, so spoof a real request */
128  {
129  /* convert old tokens into the new format */
130  if (mutt_istr_equal("all", mutt_b2s(buf)) || mutt_str_equal("^", mutt_b2s(buf)) ||
131  mutt_str_equal(".", mutt_b2s(buf))) /* ~A is more efficient */
132  {
133  mutt_buffer_strcpy(buf, "~A");
134  }
135  else if (mutt_istr_equal("del", mutt_b2s(buf)))
136  mutt_buffer_strcpy(buf, "~D");
137  else if (mutt_istr_equal("flag", mutt_b2s(buf)))
138  mutt_buffer_strcpy(buf, "~F");
139  else if (mutt_istr_equal("new", mutt_b2s(buf)))
140  mutt_buffer_strcpy(buf, "~N");
141  else if (mutt_istr_equal("old", mutt_b2s(buf)))
142  mutt_buffer_strcpy(buf, "~O");
143  else if (mutt_istr_equal("repl", mutt_b2s(buf)))
144  mutt_buffer_strcpy(buf, "~Q");
145  else if (mutt_istr_equal("read", mutt_b2s(buf)))
146  mutt_buffer_strcpy(buf, "~R");
147  else if (mutt_istr_equal("tag", mutt_b2s(buf)))
148  mutt_buffer_strcpy(buf, "~T");
149  else if (mutt_istr_equal("unread", mutt_b2s(buf)))
150  mutt_buffer_strcpy(buf, "~U");
151  else
152  {
153  struct Buffer *tmp = mutt_buffer_pool_get();
154  quote_simple(mutt_b2s(buf), tmp);
155  mutt_file_expand_fmt(buf, simple, mutt_b2s(tmp));
157  }
158  }
159 }
160 
167 static struct MuttThread *top_of_thread(struct Email *e)
168 {
169  if (!e)
170  return NULL;
171 
172  struct MuttThread *t = e->thread;
173 
174  while (t && t->parent)
175  t = t->parent;
176 
177  return t;
178 }
179 
187 {
188  if (!e || !Context || !Context->mailbox)
189  return false;
190 
191  struct MuttThread *me = top_of_thread(e);
192  if (!me)
193  return false;
194 
195  struct Mailbox *m = Context->mailbox;
196 
197  m->vcount = 0;
198  Context->vsize = 0;
199  Context->collapsed = false;
200 
201  for (int i = 0; i < m->msg_count; i++)
202  {
203  e = m->emails[i];
204  if (!e)
205  break;
206 
207  e->vnum = -1;
208  e->visible = false;
209  e->collapsed = false;
210  e->num_hidden = 0;
211 
212  if (top_of_thread(e) == me)
213  {
214  struct Body *body = e->body;
215 
216  e->vnum = m->vcount;
217  e->visible = true;
218  m->v2r[m->vcount] = i;
219  m->vcount++;
220  Context->vsize += (body->length + body->offset - body->hdr_offset);
221  }
222  }
223  return true;
224 }
225 
236 int mutt_pattern_alias_func(int op, char *prompt, char *menu_name,
237  struct AliasMenuData *mdata, struct Menu *menu)
238 {
239  int rc = -1;
240  struct Progress progress;
241  struct Buffer *buf = mutt_buffer_pool_get();
242 
243  mutt_buffer_strcpy(buf, mdata->str);
244  if (prompt)
245  {
246  if ((mutt_buffer_get_field(prompt, buf, MUTT_PATTERN | MUTT_CLEAR) != 0) ||
248  {
250  return -1;
251  }
252  }
253 
254  mutt_message(_("Compiling search pattern..."));
255 
256  bool match_all = false;
257  struct PatternList *pat = NULL;
258  char *simple = mutt_buffer_strdup(buf);
259  if (simple)
260  {
262  const char *pbuf = buf->data;
263  while (*pbuf == ' ')
264  pbuf++;
265  match_all = mutt_str_equal(pbuf, "~A");
266 
267  struct Buffer err = mutt_buffer_make(0);
268  pat = mutt_pattern_comp(buf->data, MUTT_PC_FULL_MSG, &err);
269  if (!pat)
270  {
271  mutt_error("%s", mutt_b2s(&err));
272  mutt_buffer_dealloc(&err);
273  goto bail;
274  }
275  }
276  else
277  {
278  match_all = true;
279  }
280 
281  mutt_progress_init(&progress, _("Executing command on matching messages..."),
282  MUTT_PROGRESS_READ, ARRAY_SIZE(&mdata->ava));
283 
284  int vcounter = 0;
285  struct AliasView *avp = NULL;
286  ARRAY_FOREACH(avp, &mdata->ava)
287  {
288  mutt_progress_update(&progress, ARRAY_FOREACH_IDX, -1);
289 
290  if (match_all ||
292  {
293  avp->is_visible = true;
294  vcounter++;
295  }
296  else
297  {
298  avp->is_visible = false;
299  }
300  }
301 
302  mutt_str_replace(&mdata->str, simple);
303 
304  if (menu)
305  {
306  menu->max = vcounter;
307  menu->current = 0;
308 
309  FREE(&menu->title);
310 
311  if (match_all)
312  menu->title = menu_create_alias_title(menu_name, NULL);
313  else
314  menu->title = menu_create_alias_title(menu_name, simple);
315  }
316 
318 
319  rc = 0;
320 
321 bail:
323  FREE(&simple);
324  mutt_pattern_free(&pat);
325 
326  return rc;
327 }
328 
336 int mutt_pattern_func(int op, char *prompt)
337 {
338  if (!Context || !Context->mailbox)
339  return -1;
340 
341  struct Buffer err;
342  int rc = -1;
343  struct Progress progress;
344  struct Buffer *buf = mutt_buffer_pool_get();
345  struct Mailbox *m = Context->mailbox;
346 
348  if (prompt || (op != MUTT_LIMIT))
349  {
350  if ((mutt_buffer_get_field(prompt, buf, MUTT_PATTERN | MUTT_CLEAR) != 0) ||
352  {
354  return -1;
355  }
356  }
357 
358  mutt_message(_("Compiling search pattern..."));
359 
360  char *simple = mutt_buffer_strdup(buf);
362  const char *pbuf = buf->data;
363  while (*pbuf == ' ')
364  pbuf++;
365  const bool match_all = mutt_str_equal(pbuf, "~A");
366 
367  mutt_buffer_init(&err);
368  err.dsize = 256;
369  err.data = mutt_mem_malloc(err.dsize);
370  struct PatternList *pat = mutt_pattern_comp(buf->data, MUTT_PC_FULL_MSG, &err);
371  if (!pat)
372  {
373  mutt_error("%s", err.data);
374  goto bail;
375  }
376 
377 #ifdef USE_IMAP
378  if ((m->type == MUTT_IMAP) && (!imap_search(m, pat)))
379  goto bail;
380 #endif
381 
382  mutt_progress_init(&progress, _("Executing command on matching messages..."),
383  MUTT_PROGRESS_READ, (op == MUTT_LIMIT) ? m->msg_count : m->vcount);
384 
385  if (op == MUTT_LIMIT)
386  {
387  m->vcount = 0;
388  Context->vsize = 0;
389  Context->collapsed = false;
390  int padding = mx_msg_padding_size(m);
391 
392  for (int i = 0; i < m->msg_count; i++)
393  {
394  struct Email *e = m->emails[i];
395  if (!e)
396  break;
397 
398  mutt_progress_update(&progress, i, -1);
399  /* new limit pattern implicitly uncollapses all threads */
400  e->vnum = -1;
401  e->visible = false;
402  e->collapsed = false;
403  e->num_hidden = 0;
404  if (match_all ||
406  {
407  e->vnum = m->vcount;
408  e->visible = true;
409  m->v2r[m->vcount] = i;
410  m->vcount++;
411  struct Body *b = e->body;
412  Context->vsize += b->length + b->offset - b->hdr_offset + padding;
413  }
414  }
415  }
416  else
417  {
418  for (int i = 0; i < m->vcount; i++)
419  {
420  struct Email *e = mutt_get_virt_email(Context->mailbox, i);
421  if (!e)
422  continue;
423  mutt_progress_update(&progress, i, -1);
425  {
426  switch (op)
427  {
428  case MUTT_UNDELETE:
429  mutt_set_flag(m, e, MUTT_PURGE, false);
430  /* fallthrough */
431  case MUTT_DELETE:
432  mutt_set_flag(m, e, MUTT_DELETE, (op == MUTT_DELETE));
433  break;
434  case MUTT_TAG:
435  case MUTT_UNTAG:
436  mutt_set_flag(m, e, MUTT_TAG, (op == MUTT_TAG));
437  break;
438  }
439  }
440  }
441  }
442 
444 
445  if (op == MUTT_LIMIT)
446  {
447  /* drop previous limit pattern */
448  FREE(&Context->pattern);
450 
451  if (m->msg_count && !m->vcount)
452  mutt_error(_("No messages matched criteria"));
453 
454  /* record new limit pattern, unless match all */
455  if (!match_all)
456  {
457  Context->pattern = simple;
458  simple = NULL; /* don't clobber it */
460  }
461  }
462 
463  rc = 0;
464 
465 bail:
467  FREE(&simple);
468  mutt_pattern_free(&pat);
469  FREE(&err.data);
470 
471  return rc;
472 }
473 
482 int mutt_search_command(struct Mailbox *m, int cur, int op)
483 {
484  struct Progress progress;
485 
486  if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
487  {
488  char buf[256];
489  mutt_str_copy(buf, (LastSearch[0] != '\0') ? LastSearch : "", sizeof(buf));
490  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
491  _("Search for: ") :
492  _("Reverse search for: "),
493  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0) ||
494  (buf[0] == '\0'))
495  {
496  return -1;
497  }
498 
499  if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
500  OptSearchReverse = false;
501  else
502  OptSearchReverse = true;
503 
504  /* compare the *expanded* version of the search pattern in case
505  * $simple_search has changed while we were searching */
506  struct Buffer *tmp = mutt_buffer_pool_get();
507  mutt_buffer_strcpy(tmp, buf);
509 
511  {
512  struct Buffer err;
513  mutt_buffer_init(&err);
514  OptSearchInvalid = true;
515  mutt_str_copy(LastSearch, buf, sizeof(LastSearch));
517  mutt_message(_("Compiling search pattern..."));
519  err.dsize = 256;
520  err.data = mutt_mem_malloc(err.dsize);
522  if (!SearchPattern)
523  {
525  mutt_error("%s", err.data);
526  FREE(&err.data);
527  LastSearch[0] = '\0';
528  LastSearchExpn[0] = '\0';
529  return -1;
530  }
531  FREE(&err.data);
533  }
534 
536  }
537 
538  if (OptSearchInvalid)
539  {
540  for (int i = 0; i < m->msg_count; i++)
541  m->emails[i]->searched = false;
542 #ifdef USE_IMAP
543  if ((m->type == MUTT_IMAP) && (!imap_search(m, SearchPattern)))
544  return -1;
545 #endif
546  OptSearchInvalid = false;
547  }
548 
549  int incr = OptSearchReverse ? -1 : 1;
550  if (op == OP_SEARCH_OPPOSITE)
551  incr = -incr;
552 
553  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_READ, m->vcount);
554 
555  for (int i = cur + incr, j = 0; j != m->vcount; j++)
556  {
557  const char *msg = NULL;
558  mutt_progress_update(&progress, j, -1);
559  if (i > m->vcount - 1)
560  {
561  i = 0;
562  if (C_WrapSearch)
563  msg = _("Search wrapped to top");
564  else
565  {
566  mutt_message(_("Search hit bottom without finding match"));
567  return -1;
568  }
569  }
570  else if (i < 0)
571  {
572  i = m->vcount - 1;
573  if (C_WrapSearch)
574  msg = _("Search wrapped to bottom");
575  else
576  {
577  mutt_message(_("Search hit top without finding match"));
578  return -1;
579  }
580  }
581 
582  struct Email *e = mutt_get_virt_email(m, i);
583  if (e->searched)
584  {
585  /* if we've already evaluated this message, use the cached value */
586  if (e->matched)
587  {
589  if (msg && *msg)
590  mutt_message(msg);
591  return i;
592  }
593  }
594  else
595  {
596  /* remember that we've already searched this message */
597  e->searched = true;
599  MUTT_MATCH_FULL_ADDRESS, m, e, NULL);
600  if (e->matched > 0)
601  {
603  if (msg && *msg)
604  mutt_message(msg);
605  return i;
606  }
607  }
608 
609  if (SigInt)
610  {
611  mutt_error(_("Search interrupted"));
612  SigInt = 0;
613  return -1;
614  }
615 
616  i += incr;
617  }
618 
619  mutt_error(_("Not found"));
620  return -1;
621 }
622 
631 int mutt_search_alias_command(struct Menu *menu, int cur, int op)
632 {
633  struct Progress progress;
634 
635  struct AliasViewArray *ava = &((struct AliasMenuData *) menu->mdata)->ava;
636 
637  if ((*LastSearch == '\0') || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
638  {
639  char buf[256];
640  mutt_str_copy(buf, (LastSearch[0] != '\0') ? LastSearch : "", sizeof(buf));
641  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
642  _("Search for: ") :
643  _("Reverse search for: "),
644  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0) ||
645  (buf[0] == '\0'))
646  {
647  return -1;
648  }
649 
650  if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
651  OptSearchReverse = false;
652  else
653  OptSearchReverse = true;
654 
655  /* compare the *expanded* version of the search pattern in case
656  * $simple_search has changed while we were searching */
657  struct Buffer *tmp = mutt_buffer_pool_get();
658  mutt_buffer_strcpy(tmp, buf);
660 
662  {
663  struct Buffer err;
664  mutt_buffer_init(&err);
665  OptSearchInvalid = true;
666  mutt_str_copy(LastSearch, buf, sizeof(LastSearch));
668  mutt_message(_("Compiling search pattern..."));
670  err.dsize = 256;
671  err.data = mutt_mem_malloc(err.dsize);
673  if (!SearchPattern)
674  {
676  mutt_error("%s", err.data);
677  FREE(&err.data);
678  LastSearch[0] = '\0';
679  LastSearchExpn[0] = '\0';
680  return -1;
681  }
682  FREE(&err.data);
684  }
685 
687  }
688 
689  if (OptSearchInvalid)
690  {
691  struct AliasView *av = NULL;
692  ARRAY_FOREACH(av, ava)
693  {
694  av->is_searched = false;
695  }
696 
697  OptSearchInvalid = false;
698  }
699 
700  int incr = OptSearchReverse ? -1 : 1;
701  if (op == OP_SEARCH_OPPOSITE)
702  incr = -incr;
703 
704  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_READ, ARRAY_SIZE(ava));
705 
706  for (int i = cur + incr, j = 0; j != ARRAY_SIZE(ava); j++)
707  {
708  const char *msg = NULL;
709  mutt_progress_update(&progress, j, -1);
710  if (i > ARRAY_SIZE(ava) - 1)
711  {
712  i = 0;
713  if (C_WrapSearch)
714  msg = _("Search wrapped to top");
715  else
716  {
717  mutt_message(_("Search hit bottom without finding match"));
718  return -1;
719  }
720  }
721  else if (i < 0)
722  {
723  i = ARRAY_SIZE(ava) - 1;
724  if (C_WrapSearch)
725  msg = _("Search wrapped to bottom");
726  else
727  {
728  mutt_message(_("Search hit top without finding match"));
729  return -1;
730  }
731  }
732 
733  struct AliasView *av = ARRAY_GET(ava, i);
734  if (av->is_searched)
735  {
736  /* if we've already evaluated this message, use the cached value */
737  if (av->is_matched)
738  {
740  if (msg && *msg)
741  mutt_message(msg);
742  return i;
743  }
744  }
745  else
746  {
747  /* remember that we've already searched this message */
748  av->is_searched = true;
750  MUTT_MATCH_FULL_ADDRESS, av, NULL);
751  if (av->is_matched > 0)
752  {
754  if (msg && *msg)
755  mutt_message(msg);
756  return i;
757  }
758  }
759 
760  if (SigInt)
761  {
762  mutt_error(_("Search interrupted"));
763  SigInt = 0;
764  return -1;
765  }
766 
767  i += incr;
768  }
769 
770  mutt_error(_("Not found"));
771  return -1;
772 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Convenience wrapper for the gui headers.
bool imap_search(struct Mailbox *m, const struct PatternList *pat)
Find messages in mailbox matching a pattern.
Definition: search.c:228
The "current" mailbox.
Definition: context.h:38
int mutt_pattern_func(int op, char *prompt)
Perform some Pattern matching.
Definition: pattern.c:336
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define NONULL(x)
Definition: string2.h:37
Relative range.
Definition: private.h:78
int msg_count
Total number of messages.
Definition: mailbox.h:91
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
IMAP network mailbox.
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
Less-than range.
Definition: private.h:80
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:396
#define RANGE_REL_RX
Definition: private.h:90
GUI selectable list of items.
Definition: mutt_menu.h:52
struct Body * body
List of MIME parts.
Definition: email.h:91
Structs that make up an email.
The "currently-open" mailbox.
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
int mutt_search_command(struct Mailbox *m, int cur, int op)
Perform a search.
Definition: pattern.c:482
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:91
#define mutt_message(...)
Definition: logging.h:83
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:74
char * menu_create_alias_title(char *menu_name, char *limit)
Create a title string for the Menu.
Definition: gui.c:84
AliasMenuData - AliasView array wrapper with Pattern information.
Definition: gui.h:53
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:109
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
Messages in limited view.
Definition: mutt.h:105
bool mutt_limit_current_thread(struct Email *e)
Limit the email view to the current thread.
Definition: pattern.c:186
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
Messages to be un-deleted.
Definition: mutt.h:99
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:83
struct PatternList * mutt_pattern_comp(const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1056
bool is_matched
Search matches this Alias.
Definition: gui.h:41
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
Messages to be purged (bypass trash)
Definition: mutt.h:100
int mutt_search_alias_command(struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:631
GUI data wrapping an Alias.
Definition: gui.h:36
#define RANGE_LT_RX
Definition: private.h:97
bool searched
Email has been searched.
Definition: email.h:67
Single symbol.
Definition: private.h:82
All user-callable functions.
A progress bar.
Definition: progress.h:50
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:64
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
#define RANGE_BARE_RX
Definition: private.h:101
int vcount
The number of virtual messages.
Definition: mailbox.h:102
The body of an email.
Definition: body.h:34
A simple (non-regex) pattern.
Definition: lib.h:71
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:212
struct Mailbox * mailbox
Definition: context.h:50
Many unsorted constants and some structs.
API for mailboxes.
const char * title
Title of this menu.
Definition: mutt_menu.h:54
Convenience wrapper for the core headers.
Progress tracks elements, according to $read_inc
Definition: progress.h:42
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
char * str
String representing the limit being used.
Definition: gui.h:55
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
Progress bar.
#define RANGE_GT_RX
Definition: private.h:98
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:40
#define mutt_b2s(buf)
Definition: buffer.h:41
Regular expression representing a range.
Definition: private.h:64
bool is_visible
Is visible?
Definition: gui.h:44
Prototypes for many functions.
bool visible
Is this message part of the view?
Definition: email.h:74
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:84
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
#define SLIST_FIRST(head)
Definition: queue.h:228
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Messages to be deleted.
Definition: mutt.h:98
A mailbox.
Definition: mailbox.h:81
int mutt_pattern_alias_exec(struct Pattern *pat, PatternExecFlags flags, struct AliasView *av, struct PatternCache *cache)
Match a pattern against an alias.
Definition: exec.c:1041
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:167
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
struct PatternList * limit_pattern
Compiled limit pattern.
Definition: context.h:42
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:1447
Tagged messages.
Definition: mutt.h:103
char * data
Pointer to data.
Definition: buffer.h:35
bool(* eat_arg_t)(struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)
Function to parse a pattern.
Definition: pattern.c:80
Greater-than range.
Definition: private.h:81
GUI present the user with a selectable list.
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
bool is_searched
Alias has been searched.
Definition: gui.h:40
int vnum
Virtual message number.
Definition: email.h:88
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pattern
Definition: options.h:52
void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
Set up a progress bar.
Definition: progress.c:153
Absolute range.
Definition: private.h:79
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
int mutt_pattern_alias_func(int op, char *prompt, char *menu_name, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:236
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: mutt_globals.h:170
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: mutt_globals.h:107
#define mutt_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:85
An Email conversation.
Definition: thread.h:34
int 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:738
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
static struct PatternList * SearchPattern
current search pattern
Definition: pattern.c:82
#define MUTT_ALIAS_SIMPLESEARCH
Definition: lib.h:57
Shared constants/structs that are private to libpattern.
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:716
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
bool collapsed
Are all threads collapsed?
Definition: context.h:48
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define RANGE_ABS_RX
Definition: private.h:94
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:57
Messages to be un-tagged.
Definition: mutt.h:104
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1554
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1004
int current
Current entry.
Definition: mutt_menu.h:56
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:64
Convenience wrapper for the library headers.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
Limit pattern string.
Definition: context.h:41
Shared code for the Alias and Query Dialogs.
static unsigned char * pbuf
Cache PGP data packet.
Definition: pgppacket.c:38
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:98
WHERE bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: options.h:53
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
bool matched
Search matches this Email.
Definition: email.h:68