NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
dlgquery.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include "mutt/lib.h"
37 #include "address/lib.h"
38 #include "email/lib.h"
39 #include "core/lib.h"
40 #include "gui/lib.h"
41 #include "mutt.h"
42 #include "lib.h"
43 #include "pattern/lib.h"
44 #include "send/lib.h"
45 #include "alias.h"
46 #include "format_flags.h"
47 #include "gui.h"
48 #include "keymap.h"
49 #include "mutt_globals.h"
50 #include "mutt_logging.h"
51 #include "mutt_menu.h"
52 #include "muttlib.h"
53 #include "opcodes.h"
54 
56 static const struct Mapping QueryHelp[] = {
57  // clang-format off
58  { N_("Exit"), OP_EXIT },
59  { N_("Mail"), OP_MAIL },
60  { N_("New Query"), OP_QUERY },
61  { N_("Make Alias"), OP_CREATE_ALIAS },
62  { N_("Sort"), OP_SORT },
63  { N_("Rev-Sort"), OP_SORT_REVERSE },
64  { N_("Search"), OP_SEARCH },
65  { N_("Help"), OP_HELP },
66  { NULL, 0 },
67  // clang-format on
68 };
69 
76 static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
77 {
78  if (!al || !TAILQ_EMPTY(al) || !alias)
79  return false;
80 
81  mutt_addrlist_copy(al, &alias->addr, false);
82  if (!TAILQ_EMPTY(al))
83  {
84  struct Address *first = TAILQ_FIRST(al);
85  struct Address *second = TAILQ_NEXT(first, entries);
86  if (!second && !first->personal)
87  first->personal = mutt_str_dup(alias->name);
88 
89  mutt_addrlist_to_intl(al, NULL);
90  }
91 
92  return true;
93 }
94 
100 static int query_search(struct Menu *menu, regex_t *rx, int line)
101 {
102  const struct AliasViewArray *ava = &((struct AliasMenuData *) menu->mdata)->ava;
103  struct AliasView *av = ARRAY_GET(ava, line);
104  struct Alias *alias = av->alias;
105 
106  if (alias->name && (regexec(rx, alias->name, 0, NULL, 0) == 0))
107  return 0;
108  if (alias->comment && (regexec(rx, alias->comment, 0, NULL, 0) == 0))
109  return 0;
110  if (!TAILQ_EMPTY(&alias->addr))
111  {
112  struct Address *addr = TAILQ_FIRST(&alias->addr);
113  if (addr->personal && (regexec(rx, addr->personal, 0, NULL, 0) == 0))
114  {
115  return 0;
116  }
117  if (addr->mailbox && (regexec(rx, addr->mailbox, 0, NULL, 0) == 0))
118  {
119  return 0;
120  }
121  }
122 
123  return REG_NOMATCH;
124 }
125 
137 static const char *query_format_str(char *buf, size_t buflen, size_t col, int cols,
138  char op, const char *src, const char *prec,
139  const char *if_str, const char *else_str,
140  intptr_t data, MuttFormatFlags flags)
141 {
142  struct AliasView *av = (struct AliasView *) data;
143  struct Alias *alias = av->alias;
144  char fmt[128];
145  char tmp[256] = { 0 };
146  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
147 
148  switch (op)
149  {
150  case 'a':
151  tmp[0] = '<';
152  mutt_addrlist_write(&alias->addr, tmp + 1, sizeof(tmp) - 1, true);
153  const size_t len = strlen(tmp);
154  if (len < (sizeof(tmp) - 1))
155  {
156  tmp[len] = '>';
157  tmp[len + 1] = '\0';
158  }
159  mutt_format_s(buf, buflen, prec, tmp);
160  break;
161  case 'c':
162  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
163  snprintf(buf, buflen, fmt, av->num + 1);
164  break;
165  case 'e':
166  if (!optional)
167  mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
168  else if (!alias->comment || (*alias->comment == '\0'))
169  optional = false;
170  break;
171  case 'n':
172  mutt_format_s(buf, buflen, prec, NONULL(alias->name));
173  break;
174  case 't':
175  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
176  snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
177  break;
178  default:
179  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
180  snprintf(buf, buflen, fmt, op);
181  break;
182  }
183 
184  if (optional)
185  {
186  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
188  }
189  else if (flags & MUTT_FORMAT_OPTIONAL)
190  {
191  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
192  data, MUTT_FORMAT_NO_FLAGS);
193  }
194 
195  return src;
196 }
197 
201 static void query_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
202 {
203  const struct AliasMenuData *mdata = (struct AliasMenuData *) menu->mdata;
204  const struct AliasViewArray *ava = &((struct AliasMenuData *) menu->mdata)->ava;
205  struct AliasView *av = ARRAY_GET(ava, line);
206 
207  const char *query_format = cs_subset_string(mdata->sub, "query_format");
208 
209  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols, NONULL(query_format),
211 }
212 
216 static int query_tag(struct Menu *menu, int sel, int act)
217 {
218  const struct AliasViewArray *ava = &((struct AliasMenuData *) menu->mdata)->ava;
219  struct AliasView *av = ARRAY_GET(ava, sel);
220 
221  bool ot = av->is_tagged;
222 
223  av->is_tagged = ((act >= 0) ? act : !av->is_tagged);
224  return av->is_tagged - ot;
225 }
226 
236 static int query_run(char *s, bool verbose, struct AliasList *al,
237  const struct ConfigSubset *sub)
238 {
239  FILE *fp = NULL;
240  char *buf = NULL;
241  size_t buflen;
242  char *msg = NULL;
243  size_t msglen = 0;
244  char *p = NULL;
245  struct Buffer *cmd = mutt_buffer_pool_get();
246 
247  const char *query_command = cs_subset_string(sub, "query_command");
248  mutt_buffer_file_expand_fmt_quote(cmd, query_command, s);
249 
250  pid_t pid = filter_create(mutt_b2s(cmd), NULL, &fp, NULL);
251  if (pid < 0)
252  {
253  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", mutt_b2s(cmd));
255  return -1;
256  }
258 
259  if (verbose)
260  mutt_message(_("Waiting for response..."));
261 
262  /* The query protocol first reads one NL-terminated line. If an error
263  * occurs, this is assumed to be an error message. Otherwise it's ignored. */
264  msg = mutt_file_read_line(msg, &msglen, fp, NULL, 0);
265  while ((buf = mutt_file_read_line(buf, &buflen, fp, NULL, 0)))
266  {
267  p = strtok(buf, "\t\n");
268  if (p)
269  {
270  struct Alias *alias = alias_new();
271 
272  mutt_addrlist_parse(&alias->addr, p);
273  p = strtok(NULL, "\t\n");
274  if (p)
275  {
276  alias->name = mutt_str_dup(p);
277  p = strtok(NULL, "\t\n");
278  if (p)
279  alias->comment = mutt_str_dup(p);
280  }
281  TAILQ_INSERT_TAIL(al, alias, entries);
282  }
283  }
284  FREE(&buf);
285  mutt_file_fclose(&fp);
286  if (filter_wait(pid))
287  {
288  mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
289  if (verbose)
290  mutt_error("%s", msg);
291  }
292  else
293  {
294  if (verbose)
295  mutt_message("%s", msg);
296  }
297  FREE(&msg);
298 
299  return 0;
300 }
301 
310 static void dlg_select_query(char *buf, size_t buflen, struct AliasList *all,
311  bool retbuf, struct ConfigSubset *sub)
312 {
313  struct AliasMenuData mdata = { NULL, NULL, ARRAY_HEAD_INITIALIZER, sub };
314 
315  struct Alias *np = NULL;
316  TAILQ_FOREACH(np, all, entries)
317  {
318  alias_array_alias_add(&mdata.ava, np);
319  }
320  alias_array_sort(&mdata.ava, mdata.sub);
321 
322  struct Menu *menu = NULL;
323  char title[256];
324 
325  snprintf(title, sizeof(title), "%s%s", _("Query: "), buf);
326 
327  menu = mutt_menu_new(MENU_QUERY);
329  dlg->help_data = QueryHelp;
330  dlg->help_menu = MENU_QUERY;
331 
333  menu->search = query_search;
334  menu->custom_search = true;
335  menu->tag = query_tag;
336  menu->title = strdup(title);
337  menu->max = ARRAY_SIZE(&mdata.ava);
338  menu->mdata = &mdata;
340 
343 
344  short sort_alias = cs_subset_sort(sub, "sort_alias");
345 
346  int done = 0;
347  while (done == 0)
348  {
349  const int op = mutt_menu_loop(menu);
350  switch (op)
351  {
352  case OP_QUERY_APPEND:
353  case OP_QUERY:
354  {
355  if ((mutt_get_field(_("Query: "), buf, buflen, MUTT_COMP_NO_FLAGS) != 0) ||
356  (buf[0] == '\0'))
357  {
358  break;
359  }
360 
361  if (op == OP_QUERY)
362  {
363  ARRAY_FREE(&mdata.ava);
364  aliaslist_free(all);
365  }
366 
367  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
368  query_run(buf, true, &al, sub);
369  menu->redraw = REDRAW_FULL;
370  if (TAILQ_EMPTY(&al))
371  break;
372 
373  snprintf(title, sizeof(title), "%s%s", _("Query: "), buf);
374 
375  struct Alias *tmp = NULL;
376  TAILQ_FOREACH_SAFE(np, &al, entries, tmp)
377  {
378  alias_array_alias_add(&mdata.ava, np);
379  TAILQ_REMOVE(&al, np, entries);
380  TAILQ_INSERT_TAIL(all, np, entries); // Transfer
381  }
382  alias_array_sort(&mdata.ava, mdata.sub);
383  menu->max = ARRAY_SIZE(&mdata.ava);
384  break;
385  }
386 
387  case OP_CREATE_ALIAS:
388  if (menu->tagprefix)
389  {
390  struct AddressList naddr = TAILQ_HEAD_INITIALIZER(naddr);
391 
392  struct AliasView *avp = NULL;
393  ARRAY_FOREACH(avp, &mdata.ava)
394  {
395  if (avp->is_tagged)
396  {
397  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
398  if (alias_to_addrlist(&al, avp->alias))
399  {
400  mutt_addrlist_copy(&naddr, &al, false);
401  mutt_addrlist_clear(&al);
402  }
403  }
404  }
405 
406  alias_create(&naddr, sub);
407  mutt_addrlist_clear(&naddr);
408  }
409  else
410  {
411  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
412  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu->current)->alias))
413  {
414  alias_create(&al, sub);
415  mutt_addrlist_clear(&al);
416  }
417  }
418  break;
419 
420  case OP_GENERIC_SELECT_ENTRY:
421  if (retbuf)
422  {
423  done = 2;
424  break;
425  }
426  /* fallthrough */
427  case OP_MAIL:
428  {
429  struct Email *e = email_new();
430  e->env = mutt_env_new();
431  if (menu->tagprefix)
432  {
433  struct AliasView *avp = NULL;
434  ARRAY_FOREACH(avp, &mdata.ava)
435  {
436  if (avp->is_tagged)
437  {
438  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
439  if (alias_to_addrlist(&al, avp->alias))
440  {
441  mutt_addrlist_copy(&e->env->to, &al, false);
442  mutt_addrlist_clear(&al);
443  }
444  }
445  }
446  }
447  else
448  {
449  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
450  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu->current)->alias))
451  {
452  mutt_addrlist_copy(&e->env->to, &al, false);
453  mutt_addrlist_clear(&al);
454  }
455  }
457  menu->redraw = REDRAW_FULL;
458  break;
459  }
460 
461  case OP_SORT:
462  case OP_SORT_REVERSE:
463  {
464  int sort = sort_alias;
465  bool resort = true;
466  bool reverse = (op == OP_SORT_REVERSE);
467 
468  switch (mutt_multi_choice(
469  reverse ?
470  /* L10N: The highlighted letters must match the "Sort" options */
471  _("Rev-Sort (a)lias, a(d)dress or (u)nsorted?") :
472  /* L10N: The highlighted letters must match the "Rev-Sort" options */
473  _("Sort (a)lias, a(d)dress or (u)nsorted?"),
474  /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
475  _("adu")))
476  {
477  case -1: /* abort */
478  resort = false;
479  break;
480 
481  case 1: /* (a)lias */
482  sort = SORT_ALIAS;
483  break;
484 
485  case 2: /* a(d)dress */
486  sort = SORT_ADDRESS;
487  break;
488 
489  case 3: /* (u)nsorted */
490  sort = SORT_ORDER;
491  break;
492  }
493 
494  if (resort)
495  {
496  sort |= reverse ? SORT_REVERSE : 0;
497 
498  cs_subset_str_native_set(sub, "sort_alias", sort, NULL);
499  menu->redraw = REDRAW_FULL;
500  }
501 
502  break;
503  }
504 
505  case OP_SEARCH_REVERSE:
506  case OP_SEARCH_NEXT:
507  case OP_SEARCH_OPPOSITE:
508  case OP_SEARCH:
509  menu->current = mutt_search_alias_command(menu, menu->current, op);
510  if (menu->current == -1)
511  menu->current = menu->oldcurrent;
512  else
513  menu->redraw |= REDRAW_MOTION;
514  break;
515 
516  case OP_MAIN_LIMIT:
517  {
518  int result = mutt_pattern_alias_func(
519  MUTT_LIMIT, _("Limit to messages matching: "), _("Query"), &mdata, menu);
520 
521  if (result == 0)
522  {
523  alias_array_sort(&mdata.ava, mdata.sub);
524  menu->redraw = REDRAW_FULL;
525  }
526 
527  break;
528  }
529 
530  case OP_EXIT:
531  done = 1;
532  break;
533  }
534  }
535 
536  /* if we need to return the selected entries */
537  if (retbuf && (done == 2))
538  {
539  bool tagged = false;
540  size_t curpos = 0;
541 
542  memset(buf, 0, buflen);
543 
544  /* check for tagged entries */
545  struct AliasView *avp = NULL;
546  ARRAY_FOREACH(avp, &mdata.ava)
547  {
548  if (!avp->is_tagged)
549  continue;
550 
551  if (curpos == 0)
552  {
553  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
554  if (alias_to_addrlist(&al, avp->alias))
555  {
557  tagged = true;
558  mutt_addrlist_write(&al, buf, buflen, false);
559  curpos = mutt_str_len(buf);
560  mutt_addrlist_clear(&al);
561  }
562  }
563  else if (curpos + 2 < buflen)
564  {
565  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
566  if (alias_to_addrlist(&al, avp->alias))
567  {
569  strcat(buf, ", ");
570  mutt_addrlist_write(&al, buf + curpos + 2, buflen - curpos - 2, false);
571  curpos = mutt_str_len(buf);
572  mutt_addrlist_clear(&al);
573  }
574  }
575  }
576  /* then enter current message */
577  if (!tagged)
578  {
579  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
580  if (alias_to_addrlist(&al, ARRAY_GET(&mdata.ava, menu->current)->alias))
581  {
583  mutt_addrlist_write(&al, buf, buflen, false);
584  mutt_addrlist_clear(&al);
585  }
586  }
587  }
588 
591 
592  mutt_menu_pop_current(menu);
593  mutt_menu_free(&menu);
595  ARRAY_FREE(&mdata.ava);
596 }
597 
605 int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
606 {
607  const char *query_command = cs_subset_string(sub, "query_command");
608  if (!query_command)
609  {
610  mutt_warning(_("Query command not defined"));
611  return 0;
612  }
613 
614  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
615  query_run(buf, true, &al, sub);
616  if (TAILQ_EMPTY(&al))
617  return 0;
618 
619  struct Alias *a_first = TAILQ_FIRST(&al);
620  if (!TAILQ_NEXT(a_first, entries)) // only one response?
621  {
622  struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
623  if (alias_to_addrlist(&addr, a_first))
624  {
625  mutt_addrlist_to_local(&addr);
626  buf[0] = '\0';
627  mutt_addrlist_write(&addr, buf, buflen, false);
628  mutt_addrlist_clear(&addr);
629  aliaslist_free(&al);
631  }
632  return 0;
633  }
634 
635  /* multiple results, choose from query menu */
636  dlg_select_query(buf, buflen, &al, true, sub);
637  aliaslist_free(&al);
638  return 0;
639 }
640 
645 void query_index(struct ConfigSubset *sub)
646 {
647  const char *query_command = cs_subset_string(sub, "query_command");
648  if (!query_command)
649  {
650  mutt_warning(_("Query command not defined"));
651  return;
652  }
653 
654  char buf[256] = { 0 };
655  if ((mutt_get_field(_("Query: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
656  (buf[0] == '\0'))
657  {
658  return;
659  }
660 
661  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
662  query_run(buf, false, &al, sub);
663  if (TAILQ_EMPTY(&al))
664  return;
665 
666  dlg_select_query(buf, sizeof(buf), &al, false, sub);
667  aliaslist_free(&al);
668 }
Convenience wrapper for the gui headers.
static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlgquery.c:76
A shortcut for an email address or addresses.
Definition: alias.h:33
#define mutt_warning(...)
Definition: logging.h:82
The "current" mailbox.
Definition: context.h:38
char * name
Short name.
Definition: alias.h:35
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:45
#define IP
Definition: set.h:54
Manage keymappings.
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:37
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:716
GUI selectable list of items.
Definition: mutt_menu.h:52
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Structs that make up an email.
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
Convenience wrapper for the send headers.
#define mutt_message(...)
Definition: logging.h:83
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:134
AliasMenuData - AliasView array wrapper with Pattern information.
Definition: gui.h:53
int oldcurrent
For driver use only.
Definition: mutt_menu.h:76
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1386
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:198
static int query_search(struct Menu *menu, regex_t *rx, int line)
Search a Address menu item - Implements Menu::search()
Definition: dlgquery.c:100
Messages in limited view.
Definition: mutt.h:105
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
Perform auto-complete using an Address Query.
Definition: dlgquery.c:605
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
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
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
Query Dialog, dlg_select_query()
Definition: mutt_window.h:87
String manipulation buffer.
Definition: buffer.h:33
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Sort by email address.
Definition: sort2.h:56
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
A division of the screen.
Definition: mutt_window.h:115
GUI data wrapping an Alias.
Definition: gui.h:36
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:310
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:45
int alias_color_observer(struct NotifyCallback *nc)
Listen for color configuration changes and refreshes the menu.
Definition: gui.c:66
Flags to control mutt_expando_format()
All user-callable functions.
Container for Accounts, Notifications.
Definition: neomutt.h:36
Representation of a single alias to an email address.
struct MuttWindow * dialog_create_simple_index(struct Menu *menu, enum WindowType type)
Create a simple index Dialog.
Definition: dialog.c:165
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
void alias_array_sort(struct AliasViewArray *ava, const struct ConfigSubset *sub)
Sort and reindex an AliasViewArray.
Definition: sort.c:158
Email Address Handling.
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:40
Some miscellaneous functions.
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:292
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:137
static const struct Mapping QueryHelp[]
Help Bar for the Address Query dialog.
Definition: dlgquery.c:56
Select from results of external query.
Definition: keymap.h:83
Many unsorted constants and some structs.
static short sort_alias
Definition: sort.c:42
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:50
const char * title
Title of this menu.
Definition: mutt_menu.h:54
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:366
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:608
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:54
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
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:169
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define REDRAW_MOTION
Redraw after moving the menu list.
Definition: mutt_menu.h:41
int alias_config_observer(struct NotifyCallback *nc)
Listen for sort_alias configuration changes and reorders menu items accordingly.
Definition: gui.c:44
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:236
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:219
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:933
Colour has changed, ColorId, EventColor.
Definition: notify_type.h:35
static void query_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the query list - Implements Menu::make_entry()
Definition: dlgquery.c:201
A set of inherited config items.
Definition: subset.h:46
struct Alias * alias
Alias.
Definition: gui.h:45
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
bool tagprefix
Definition: mutt_menu.h:61
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:135
Match patterns to emails.
void dialog_destroy_simple_index(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: dialog.c:209
GUI present the user with a selectable list.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
Sort by email alias.
Definition: sort2.h:55
char * comment
Free-form comment string.
Definition: alias.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
int(* tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:107
bool custom_search
The menu implements its own non-Menusearch()-compatible search, trickle OP_SEARCH*.
Definition: mutt_menu.h:79
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:58
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:37
char * personal
Real name of address.
Definition: address.h:36
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:639
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
bool is_tagged
Is it tagged?
Definition: gui.h:42
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:1244
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
Log at debug level 1.
Definition: logging.h:40
void query_index(struct ConfigSubset *sub)
Perform an Alias Query and display the results.
Definition: dlgquery.c:645
struct ConfigSubset * sub
Config items.
Definition: gui.h:58
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:772
#define mutt_error(...)
Definition: logging.h:84
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:1432
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag()
Definition: dlgquery.c:216
#define FREE(x)
Definition: memory.h:40
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1995
Mapping between user-readable string and a constant.
Definition: mapping.h:31
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:207
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:57
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
Hundreds of global variables to back the user variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:714
int current
Current entry.
Definition: mutt_menu.h:56
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
struct MuttWindow * win_index
Definition: mutt_menu.h:63
Convenience wrapper for the library headers.
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
int mutt_pattern_alias_func(int op, char *prompt, char *title, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:236
int num
Index number in list.
Definition: gui.h:38
#define N_(a)
Definition: message.h:32
int mutt_search_alias_command(struct Menu *menu, int cur, int op)
Perform a search.
Definition: pattern.c:631
Shared code for the Alias and Query Dialogs.
int(* search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:98
void(* make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:88
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
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83