NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
dlgquery.c
Go to the documentation of this file.
1 
71 #include "config.h"
72 #include <stdbool.h>
73 #include <stdint.h>
74 #include <stdio.h>
75 #include <string.h>
76 #include <sys/types.h>
77 #include "mutt/lib.h"
78 #include "address/lib.h"
79 #include "config/lib.h"
80 #include "email/lib.h"
81 #include "core/lib.h"
82 #include "gui/lib.h"
83 #include "mutt.h"
84 #include "lib.h"
85 #include "menu/lib.h"
86 #include "pattern/lib.h"
87 #include "question/lib.h"
88 #include "send/lib.h"
89 #include "alias.h"
90 #include "context.h"
91 #include "format_flags.h"
92 #include "gui.h"
93 #include "mutt_globals.h"
94 #include "mutt_logging.h"
95 #include "muttlib.h"
96 #include "opcodes.h"
97 
99 static const struct Mapping QueryHelp[] = {
100  // clang-format off
101  { N_("Exit"), OP_EXIT },
102  { N_("Mail"), OP_MAIL },
103  { N_("New Query"), OP_QUERY },
104  { N_("Make Alias"), OP_CREATE_ALIAS },
105  { N_("Sort"), OP_SORT },
106  { N_("Rev-Sort"), OP_SORT_REVERSE },
107  { N_("Search"), OP_SEARCH },
108  { N_("Help"), OP_HELP },
109  { NULL, 0 },
110  // clang-format on
111 };
112 
119 static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
120 {
121  if (!al || !TAILQ_EMPTY(al) || !alias)
122  return false;
123 
124  mutt_addrlist_copy(al, &alias->addr, false);
125  if (!TAILQ_EMPTY(al))
126  {
127  struct Address *first = TAILQ_FIRST(al);
128  struct Address *second = TAILQ_NEXT(first, entries);
129  if (!second && !first->personal)
130  first->personal = mutt_str_dup(alias->name);
131 
132  mutt_addrlist_to_intl(al, NULL);
133  }
134 
135  return true;
136 }
137 
143 static int query_search(struct Menu *menu, regex_t *rx, int line)
144 {
145  const struct AliasViewArray *ava = &((struct AliasMenuData *) menu->mdata)->ava;
146  struct AliasView *av = ARRAY_GET(ava, line);
147  struct Alias *alias = av->alias;
148 
149  if (alias->name && (regexec(rx, alias->name, 0, NULL, 0) == 0))
150  return 0;
151  if (alias->comment && (regexec(rx, alias->comment, 0, NULL, 0) == 0))
152  return 0;
153  if (!TAILQ_EMPTY(&alias->addr))
154  {
155  struct Address *addr = TAILQ_FIRST(&alias->addr);
156  if (addr->personal && (regexec(rx, addr->personal, 0, NULL, 0) == 0))
157  {
158  return 0;
159  }
160  if (addr->mailbox && (regexec(rx, addr->mailbox, 0, NULL, 0) == 0))
161  {
162  return 0;
163  }
164  }
165 
166  return REG_NOMATCH;
167 }
168 
180 static const char *query_format_str(char *buf, size_t buflen, size_t col, int cols,
181  char op, const char *src, const char *prec,
182  const char *if_str, const char *else_str,
183  intptr_t data, MuttFormatFlags flags)
184 {
185  struct AliasView *av = (struct AliasView *) data;
186  struct Alias *alias = av->alias;
187  char fmt[128];
188  char tmp[256] = { 0 };
189  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
190 
191  switch (op)
192  {
193  case 'a':
194  tmp[0] = '<';
195  mutt_addrlist_write(&alias->addr, tmp + 1, sizeof(tmp) - 1, true);
196  const size_t len = strlen(tmp);
197  if (len < (sizeof(tmp) - 1))
198  {
199  tmp[len] = '>';
200  tmp[len + 1] = '\0';
201  }
202  mutt_format_s(buf, buflen, prec, tmp);
203  break;
204  case 'c':
205  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
206  snprintf(buf, buflen, fmt, av->num + 1);
207  break;
208  case 'e':
209  if (!optional)
210  mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
211  else if (!alias->comment || (*alias->comment == '\0'))
212  optional = false;
213  break;
214  case 'n':
215  mutt_format_s(buf, buflen, prec, NONULL(alias->name));
216  break;
217  case 't':
218  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
219  snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
220  break;
221  default:
222  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
223  snprintf(buf, buflen, fmt, op);
224  break;
225  }
226 
227  if (optional)
228  {
229  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
231  }
232  else if (flags & MUTT_FORMAT_OPTIONAL)
233  {
234  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
235  data, MUTT_FORMAT_NO_FLAGS);
236  }
237 
238  /* We return the format string, unchanged */
239  return src;
240 }
241 
245 static void query_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
246 {
247  const struct AliasMenuData *mdata = menu->mdata;
248  const struct AliasViewArray *ava = &mdata->ava;
249  struct AliasView *av = ARRAY_GET(ava, line);
250 
251  const char *const query_format = cs_subset_string(mdata->sub, "query_format");
252 
253  mutt_expando_format(buf, buflen, 0, menu->win->state.cols, NONULL(query_format),
254  query_format_str, (intptr_t) av, MUTT_FORMAT_ARROWCURSOR);
255 }
256 
260 static int query_tag(struct Menu *menu, int sel, int act)
261 {
262  const struct AliasMenuData *mdata = menu->mdata;
263  const struct AliasViewArray *ava = &mdata->ava;
264  struct AliasView *av = ARRAY_GET(ava, sel);
265 
266  bool ot = av->is_tagged;
267 
268  av->is_tagged = ((act >= 0) ? act : !av->is_tagged);
269  return av->is_tagged - ot;
270 }
271 
281 static int query_run(char *s, bool verbose, struct AliasList *al,
282  const struct ConfigSubset *sub)
283 {
284  FILE *fp = NULL;
285  char *buf = NULL;
286  size_t buflen;
287  char *msg = NULL;
288  size_t msglen = 0;
289  char *p = NULL;
290  struct Buffer *cmd = mutt_buffer_pool_get();
291 
292  const char *const query_command = cs_subset_string(sub, "query_command");
293  mutt_buffer_file_expand_fmt_quote(cmd, query_command, s);
294 
295  pid_t pid = filter_create(mutt_buffer_string(cmd), NULL, &fp, NULL);
296  if (pid < 0)
297  {
298  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", mutt_buffer_string(cmd));
300  return -1;
301  }
303 
304  if (verbose)
305  mutt_message(_("Waiting for response..."));
306 
307  /* The query protocol first reads one NL-terminated line. If an error
308  * occurs, this is assumed to be an error message. Otherwise it's ignored. */
309  msg = mutt_file_read_line(msg, &msglen, fp, NULL, MUTT_RL_NO_FLAGS);
310  while ((buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS)))
311  {
312  p = strtok(buf, "\t\n");
313  if (p)
314  {
315  struct Alias *alias = alias_new();
316 
317  mutt_addrlist_parse(&alias->addr, p);
318  p = strtok(NULL, "\t\n");
319  if (p)
320  {
321  alias->name = mutt_str_dup(p);
322  p = strtok(NULL, "\t\n");
323  if (p)
324  alias->comment = mutt_str_dup(p);
325  }
326  TAILQ_INSERT_TAIL(al, alias, entries);
327  }
328  }
329  FREE(&buf);
330  mutt_file_fclose(&fp);
331  if (filter_wait(pid))
332  {
333  mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
334  if (verbose)
335  mutt_error("%s", msg);
336  }
337  else
338  {
339  if (verbose)
340  mutt_message("%s", msg);
341  }
342  FREE(&msg);
343 
344  return 0;
345 }
346 
351 {
352  if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
353  return -1;
354 
355  if (nc->event_subtype != NT_WINDOW_DELETE)
356  return 0;
357 
358  struct MuttWindow *win_menu = nc->global_data;
359  struct EventWindow *ev_w = nc->event_data;
360  if (ev_w->win != win_menu)
361  return 0;
362 
363  struct Menu *menu = win_menu->wdata;
364 
367 
368  mutt_debug(LL_DEBUG5, "window delete done\n");
369  return 0;
370 }
371 
378 struct MuttWindow *query_dialog_new(struct AliasMenuData *mdata, char *query)
379 {
381  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
382 
383  struct Menu *menu = dlg->wdata;
384 
386  menu->search = query_search;
387  menu->custom_search = true;
388  menu->tag = query_tag;
389  menu->max = ARRAY_SIZE(&mdata->ava);
390  menu->mdata = mdata;
391 
392  struct MuttWindow *win_menu = menu->win;
393 
394  // Override the Simple Dialog's recalc()
395  win_menu->recalc = alias_recalc;
396 
397  char title[256];
398  snprintf(title, sizeof(title), "%s%s", _("Query: "), query);
399  sbar_set_title(sbar, title);
400 
401  // NT_COLOR is handled by the SimpleDialog
404 
405  return dlg;
406 }
407 
416 static void dlg_select_query(char *buf, size_t buflen, struct AliasList *all,
417  bool retbuf, struct ConfigSubset *sub)
418 {
419  struct AliasMenuData mdata = { NULL, ARRAY_HEAD_INITIALIZER, sub };
420  struct Alias *np = NULL;
421  TAILQ_FOREACH(np, all, entries)
422  {
423  alias_array_alias_add(&mdata.ava, np);
424  }
425  alias_array_sort(&mdata.ava, mdata.sub);
426 
427  struct MuttWindow *dlg = query_dialog_new(&mdata, buf);
428  struct Menu *menu = dlg->wdata;
429  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
430 
431  int done = 0;
432  while (done == 0)
433  {
434  const int op = menu_loop(menu);
435  switch (op)
436  {
437  case OP_QUERY_APPEND:
438  case OP_QUERY:
439  {
440  if ((mutt_get_field(_("Query: "), buf, buflen, MUTT_COMP_NO_FLAGS,
441  false, NULL, NULL) != 0) ||
442  (buf[0] == '\0'))
443  {
444  break;
445  }
446 
447  if (op == OP_QUERY)
448  {
449  ARRAY_FREE(&mdata.ava);
450  aliaslist_free(all);
451  }
452 
453  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
454  query_run(buf, true, &al, sub);
456  char title[256];
457  snprintf(title, sizeof(title), "%s%s", _("Query: "), buf);
458  sbar_set_title(sbar, title);
459 
460  if (TAILQ_EMPTY(&al))
461  {
462  menu->max = 0;
463  break;
464  }
465 
466  struct Alias *tmp = NULL;
467  TAILQ_FOREACH_SAFE(np, &al, entries, tmp)
468  {
469  alias_array_alias_add(&mdata.ava, np);
470  TAILQ_REMOVE(&al, np, entries);
471  TAILQ_INSERT_TAIL(all, np, entries); // Transfer
472  }
473  alias_array_sort(&mdata.ava, mdata.sub);
474  menu->max = ARRAY_SIZE(&mdata.ava);
475  break;
476  }
477 
478  case OP_CREATE_ALIAS:
479  if (menu->tagprefix)
480  {
481  struct AddressList naddr = TAILQ_HEAD_INITIALIZER(naddr);
482 
483  struct AliasView *avp = NULL;
484  ARRAY_FOREACH(avp, &mdata.ava)
485  {
486  if (avp->is_tagged)
487  {
488  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
489  if (alias_to_addrlist(&al, avp->alias))
490  {
491  mutt_addrlist_copy(&naddr, &al, false);
492  mutt_addrlist_clear(&al);
493  }
494  }
495  }
496 
497  alias_create(&naddr, sub);
498  mutt_addrlist_clear(&naddr);
499  }
500  else
501  {
502  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
503  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu_get_index(menu))->alias))
504  {
505  alias_create(&al, sub);
506  mutt_addrlist_clear(&al);
507  }
508  }
509  break;
510 
511  case OP_GENERIC_SELECT_ENTRY:
512  if (retbuf)
513  {
514  done = 2;
515  break;
516  }
517  /* fallthrough */
518  case OP_MAIL:
519  {
520  struct Email *e = email_new();
521  e->env = mutt_env_new();
522  if (menu->tagprefix)
523  {
524  struct AliasView *avp = NULL;
525  ARRAY_FOREACH(avp, &mdata.ava)
526  {
527  if (avp->is_tagged)
528  {
529  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
530  if (alias_to_addrlist(&al, avp->alias))
531  {
532  mutt_addrlist_copy(&e->env->to, &al, false);
533  mutt_addrlist_clear(&al);
534  }
535  }
536  }
537  }
538  else
539  {
540  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
541  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu_get_index(menu))->alias))
542  {
543  mutt_addrlist_copy(&e->env->to, &al, false);
544  mutt_addrlist_clear(&al);
545  }
546  }
548  NeoMutt->sub);
550  break;
551  }
552 
553  case OP_SORT:
554  case OP_SORT_REVERSE:
555  {
556  int sort = cs_subset_sort(sub, "sort_alias");
557 
558  bool resort = true;
559  bool reverse = (op == OP_SORT_REVERSE);
560 
561  switch (mutt_multi_choice(
562  reverse ?
563  /* L10N: The highlighted letters must match the "Sort" options */
564  _("Rev-Sort (a)lias, a(d)dress or (u)nsorted?") :
565  /* L10N: The highlighted letters must match the "Rev-Sort" options */
566  _("Sort (a)lias, a(d)dress or (u)nsorted?"),
567  /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
568  _("adu")))
569  {
570  case -1: /* abort */
571  resort = false;
572  break;
573 
574  case 1: /* (a)lias */
575  sort = SORT_ALIAS;
576  break;
577 
578  case 2: /* a(d)dress */
579  sort = SORT_ADDRESS;
580  break;
581 
582  case 3: /* (u)nsorted */
583  sort = SORT_ORDER;
584  break;
585  }
586 
587  if (resort)
588  {
589  sort |= reverse ? SORT_REVERSE : 0;
590 
591  cs_subset_str_native_set(sub, "sort_alias", sort, NULL);
593  }
594 
595  break;
596  }
597 
598  case OP_SEARCH_REVERSE:
599  case OP_SEARCH_NEXT:
600  case OP_SEARCH_OPPOSITE:
601  case OP_SEARCH:
602  {
603  int index = mutt_search_alias_command(menu, menu_get_index(menu), op);
604  if (index == -1)
605  break;
606 
607  menu_set_index(menu, index);
608  break;
609  }
610 
611  case OP_MAIN_LIMIT:
612  {
613  int rc = mutt_pattern_alias_func(_("Limit to addresses matching: "), &mdata, menu);
614  if (rc == 0)
615  {
616  alias_array_sort(&mdata.ava, mdata.sub);
617  alias_set_title(sbar, _("Query"), mdata.str);
619  }
620 
621  break;
622  }
623 
624  case OP_EXIT:
625  done = 1;
626  break;
627  }
628  }
629 
630  /* if we need to return the selected entries */
631  if (retbuf && (done == 2))
632  {
633  bool tagged = false;
634  size_t curpos = 0;
635 
636  memset(buf, 0, buflen);
637 
638  /* check for tagged entries */
639  struct AliasView *avp = NULL;
640  ARRAY_FOREACH(avp, &mdata.ava)
641  {
642  if (!avp->is_tagged)
643  continue;
644 
645  if (curpos == 0)
646  {
647  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
648  if (alias_to_addrlist(&al, avp->alias))
649  {
651  tagged = true;
652  mutt_addrlist_write(&al, buf, buflen, false);
653  curpos = mutt_str_len(buf);
654  mutt_addrlist_clear(&al);
655  }
656  }
657  else if (curpos + 2 < buflen)
658  {
659  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
660  if (alias_to_addrlist(&al, avp->alias))
661  {
663  strcat(buf, ", ");
664  mutt_addrlist_write(&al, buf + curpos + 2, buflen - curpos - 2, false);
665  curpos = mutt_str_len(buf);
666  mutt_addrlist_clear(&al);
667  }
668  }
669  }
670  /* then enter current message */
671  if (!tagged)
672  {
673  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
674  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu_get_index(menu))->alias))
675  {
677  mutt_addrlist_write(&al, buf, buflen, false);
678  mutt_addrlist_clear(&al);
679  }
680  }
681  }
682 
683  simple_dialog_free(&dlg);
684  ARRAY_FREE(&mdata.ava);
685 }
686 
694 int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
695 {
696  const char *const query_command = cs_subset_string(sub, "query_command");
697  if (!query_command)
698  {
699  mutt_warning(_("Query command not defined"));
700  return 0;
701  }
702 
703  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
704  query_run(buf, true, &al, sub);
705  if (TAILQ_EMPTY(&al))
706  return 0;
707 
708  struct Alias *a_first = TAILQ_FIRST(&al);
709  if (!TAILQ_NEXT(a_first, entries)) // only one response?
710  {
711  struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
712  if (alias_to_addrlist(&addr, a_first))
713  {
714  mutt_addrlist_to_local(&addr);
715  buf[0] = '\0';
716  mutt_addrlist_write(&addr, buf, buflen, false);
717  mutt_addrlist_clear(&addr);
718  aliaslist_free(&al);
720  }
721  return 0;
722  }
723 
724  /* multiple results, choose from query menu */
725  dlg_select_query(buf, buflen, &al, true, sub);
726  aliaslist_free(&al);
727  return 0;
728 }
729 
734 void query_index(struct ConfigSubset *sub)
735 {
736  const char *const query_command = cs_subset_string(sub, "query_command");
737  if (!query_command)
738  {
739  mutt_warning(_("Query command not defined"));
740  return;
741  }
742 
743  char buf[256] = { 0 };
744  if ((mutt_get_field(_("Query: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS, false,
745  NULL, NULL) != 0) ||
746  (buf[0] == '\0'))
747  {
748  return;
749  }
750 
751  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
752  query_run(buf, false, &al, sub);
753  if (TAILQ_EMPTY(&al))
754  return;
755 
756  dlg_select_query(buf, sizeof(buf), &al, false, sub);
757  aliaslist_free(&al);
758 }
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1388
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
Email Address Handling.
void alias_array_sort(struct AliasViewArray *ava, const struct ConfigSubset *sub)
Sort and reindex an AliasViewArray.
Definition: sort.c:157
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:618
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:372
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:650
Representation of a single alias to an email address.
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:45
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:208
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:200
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:54
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Convenience wrapper for the config headers.
struct Mailbox * ctx_mailbox(struct Context *ctx)
Wrapper to get the mailbox in a Context, or NULL.
Definition: context.c:444
The "currently-open" mailbox.
Convenience wrapper for the core headers.
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:872
void query_index(struct ConfigSubset *sub)
Perform an Alias Query and display the results.
Definition: dlgquery.c:734
static const struct Mapping QueryHelp[]
Help Bar for the Address Query dialog.
Definition: dlgquery.c:99
static void dlg_select_query(char *buf, size_t buflen, struct AliasList *all, bool retbuf, struct ConfigSubset *sub)
Get the user to enter an Address Query.
Definition: dlgquery.c:416
static int query_run(char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlgquery.c:281
struct MuttWindow * query_dialog_new(struct AliasMenuData *mdata, char *query)
Create an Query Selection Dialog.
Definition: dlgquery.c:378
static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlgquery.c:119
int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
Perform auto-complete using an Address Query.
Definition: dlgquery.c:694
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Structs that make up an email.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:671
void mutt_buffer_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1439
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
Flags to control mutt_expando_format()
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
static const char * query_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the query menu - Implements format_t -.
Definition: dlgquery.c:180
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:780
#define mutt_warning(...)
Definition: logging.h:85
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static void query_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the query list - Implements Menu::make_entry() -.
Definition: dlgquery.c:245
static int query_search(struct Menu *menu, regex_t *rx, int line)
Search a Address menu item - Implements Menu::search() -.
Definition: dlgquery.c:143
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag() -.
Definition: dlgquery.c:260
int alias_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: gui.c:43
int query_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlgquery.c:350
int alias_recalc(struct MuttWindow *win)
Recalculate the display of the Alias Window - Implements MuttWindow::recalc() -.
Definition: gui.c:87
Convenience wrapper for the gui headers.
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:126
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:163
void alias_set_title(struct MuttWindow *sbar, char *menu_name, char *limit)
Create a title string for the Menu.
Definition: gui.c:67
Shared code for the Alias and Query Dialogs.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
#define FREE(x)
Definition: memory.h:40
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:55
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:632
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:608
int menu_loop(struct Menu *menu)
Menu event loop.
Definition: menu.c:283
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:622
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
Hundreds of global variables to back the user variables.
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
NeoMutt Logging.
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:520
@ WT_DLG_QUERY
Query Dialog, dlg_select_query()
Definition: mutt_window.h:90
@ WT_STATUS_BAR
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
@ NT_WINDOW_DELETE
Window is about to be deleted.
Definition: mutt_window.h:206
Some miscellaneous functions.
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
All user-callable functions.
Match patterns to emails.
int mutt_search_alias_command(struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:653
int mutt_pattern_alias_func(char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:243
void mutt_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
Ask the user a question.
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:50
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:219
Convenience wrapper for the send headers.
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2110
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:39
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
@ SORT_ALIAS
Sort by email alias.
Definition: sort2.h:53
@ SORT_ADDRESS
Sort by email address.
Definition: sort2.h:54
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
Key value store.
#define NONULL(x)
Definition: string2.h:37
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * personal
Real name of address.
Definition: address.h:37
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:54
char * str
String representing the limit being used.
Definition: gui.h:53
struct ConfigSubset * sub
Config items.
Definition: gui.h:55
GUI data wrapping an Alias.
Definition: gui.h:36
struct Alias * alias
Alias.
Definition: gui.h:44
bool is_tagged
Is it tagged?
Definition: gui.h:41
int num
Index number in list.
Definition: gui.h:37
A shortcut for an email address or addresses.
Definition: alias.h:34
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
String manipulation buffer.
Definition: buffer.h:34
A set of inherited config items.
Definition: subset.h:47
The "current" mailbox.
Definition: context.h:38
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
struct AddressList to
Email's 'To' list.
Definition: envelope.h:58
An Event that happened to a Window.
Definition: mutt_window.h:216
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
Mapping between user-readable string and a constant.
Definition: mapping.h:32
Definition: lib.h:67
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:74
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:103
int(* search)(struct Menu *menu, regex_t *rx, int line)
Definition: lib.h:116
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:128
bool tagprefix
User has pressed <tag-prefix>
Definition: lib.h:73
void * mdata
Private data.
Definition: lib.h:153
int max
Number of entries in the menu.
Definition: lib.h:69
bool custom_search
The menu implements its own non-Menusearch()-compatible search, trickle OP_SEARCH*.
Definition: lib.h:91
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:171
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Data passed to a notification function.
Definition: observer.h:34
void * event_data
Data from notify_send()
Definition: observer.h:38
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:36
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:37
void * global_data
Data from notify_observer_add()
Definition: observer.h:39
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
@ MENU_QUERY
Select from results of external query.
Definition: type.h:57