NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
dlgalias.c
Go to the documentation of this file.
1 
76 #include "config.h"
77 #include <stdbool.h>
78 #include <stdint.h>
79 #include <stdio.h>
80 #include <string.h>
81 #include "mutt/lib.h"
82 #include "address/lib.h"
83 #include "config/lib.h"
84 #include "core/lib.h"
85 #include "gui/lib.h"
86 #include "mutt.h"
87 #include "lib.h"
88 #include "menu/lib.h"
89 #include "pattern/lib.h"
90 #include "question/lib.h"
91 #include "alias.h"
92 #include "format_flags.h"
93 #include "gui.h"
94 #include "muttlib.h"
95 #include "opcodes.h"
96 
98 static const struct Mapping AliasHelp[] = {
99  // clang-format off
100  { N_("Exit"), OP_EXIT },
101  { N_("Del"), OP_DELETE },
102  { N_("Undel"), OP_UNDELETE },
103  { N_("Sort"), OP_SORT },
104  { N_("Rev-Sort"), OP_SORT_REVERSE },
105  { N_("Select"), OP_GENERIC_SELECT_ENTRY },
106  { N_("Help"), OP_HELP },
107  { NULL, 0 },
108  // clang-format on
109 };
110 
123 static const char *alias_format_str(char *buf, size_t buflen, size_t col, int cols,
124  char op, const char *src, const char *prec,
125  const char *if_str, const char *else_str,
126  intptr_t data, MuttFormatFlags flags)
127 {
128  char fmt[128], addr[1024];
129  struct AliasView *av = (struct AliasView *) data;
130  struct Alias *alias = av->alias;
131 
132  switch (op)
133  {
134  case 'a':
135  mutt_format_s(buf, buflen, prec, alias->name);
136  break;
137  case 'c':
138  mutt_format_s(buf, buflen, prec, alias->comment);
139  break;
140  case 'f':
141  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
142  snprintf(buf, buflen, fmt, av->is_deleted ? "D" : " ");
143  break;
144  case 'n':
145  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
146  snprintf(buf, buflen, fmt, av->num + 1);
147  break;
148  case 'r':
149  addr[0] = '\0';
150  mutt_addrlist_write(&alias->addr, addr, sizeof(addr), true);
151  mutt_format_s(buf, buflen, prec, addr);
152  break;
153  case 't':
154  buf[0] = av->is_tagged ? '*' : ' ';
155  buf[1] = '\0';
156  break;
157  }
158 
159  return src;
160 }
161 
165 static void alias_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
166 {
167  const struct AliasMenuData *mdata = menu->mdata;
168  const struct AliasViewArray *ava = &mdata->ava;
169  const struct AliasView *av = ARRAY_GET(ava, line);
170 
171  const char *const alias_format = cs_subset_string(mdata->sub, "alias_format");
172 
173  mutt_expando_format(buf, buflen, 0, menu->win->state.cols, NONULL(alias_format),
174  alias_format_str, (intptr_t) av, MUTT_FORMAT_ARROWCURSOR);
175 }
176 
180 static int alias_tag(struct Menu *menu, int sel, int act)
181 {
182  const struct AliasMenuData *mdata = menu->mdata;
183  const struct AliasViewArray *ava = &mdata->ava;
184  struct AliasView *av = ARRAY_GET(ava, sel);
185 
186  bool ot = av->is_tagged;
187 
188  av->is_tagged = ((act >= 0) ? act : !av->is_tagged);
189 
190  return av->is_tagged - ot;
191 }
192 
196 static int alias_alias_observer(struct NotifyCallback *nc)
197 {
198  if ((nc->event_type != NT_ALIAS) || !nc->global_data || !nc->event_data)
199  return -1;
200 
201  struct EventAlias *ev_a = nc->event_data;
202  struct Menu *menu = nc->global_data;
203  struct AliasMenuData *mdata = menu->mdata;
204  struct Alias *alias = ev_a->alias;
205 
206  if (nc->event_subtype == NT_ALIAS_ADD)
207  {
208  alias_array_alias_add(&mdata->ava, alias);
209 
210  if (alias_array_count_visible(&mdata->ava) != ARRAY_SIZE(&mdata->ava))
211  {
212  mutt_pattern_alias_func(MUTT_LIMIT, NULL, mdata, menu);
213  }
214  }
215  else if (nc->event_subtype == NT_ALIAS_DELETE)
216  {
217  alias_array_alias_delete(&mdata->ava, alias);
218 
219  int vcount = alias_array_count_visible(&mdata->ava);
220  int index = menu_get_index(menu);
221  if ((index > (vcount - 1)) && (index > 0))
222  menu_set_index(menu, index - 1);
223  }
224 
225  alias_array_sort(&mdata->ava, mdata->sub);
226 
227  menu->max = alias_array_count_visible(&mdata->ava);
229  mutt_debug(LL_DEBUG5, "alias done, request WA_RECALC, MENU_REDRAW_FULL\n");
230 
231  return 0;
232 }
233 
242 {
243  if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
244  return -1;
245 
246  if (nc->event_subtype != NT_WINDOW_DELETE)
247  return 0;
248 
249  struct MuttWindow *win_menu = nc->global_data;
250  struct EventWindow *ev_w = nc->event_data;
251  if (ev_w->win != win_menu)
252  return 0;
253 
254  struct Menu *menu = win_menu->wdata;
255 
259 
260  mutt_debug(LL_DEBUG5, "window delete done\n");
261  return 0;
262 }
263 
270 {
271  struct MuttWindow *dlg = simple_dialog_new(MENU_ALIAS, WT_DLG_ALIAS, AliasHelp);
272 
273  struct Menu *menu = dlg->wdata;
275  menu->custom_search = true;
276  menu->tag = alias_tag;
277  menu->max = alias_array_count_visible(&mdata->ava);
278  menu->mdata = mdata;
279 
280  struct MuttWindow *win_menu = menu->win;
281 
282  // Override the Simple Dialog's recalc()
283  win_menu->recalc = alias_recalc;
284 
285  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
286 
287  alias_set_title(sbar, _("Aliases"), mdata->str);
288 
289  // NT_COLOR is handled by the SimpleDialog
293 
294  return dlg;
295 }
296 
303 static void dlg_select_alias(char *buf, size_t buflen, struct AliasMenuData *mdata)
304 {
305  if (ARRAY_EMPTY(&mdata->ava))
306  {
307  mutt_warning(_("You have no aliases"));
308  return;
309  }
310 
311  struct MuttWindow *dlg = alias_dialog_new(mdata);
312  struct Menu *menu = dlg->wdata;
313  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
314 
315  int t = -1;
316  bool done = false;
317 
318  alias_array_sort(&mdata->ava, mdata->sub);
319 
320  struct AliasView *avp = NULL;
321  ARRAY_FOREACH(avp, &mdata->ava)
322  {
323  avp->num = ARRAY_FOREACH_IDX;
324  }
325 
326  while (!done)
327  {
328  int op = menu_loop(menu);
329  switch (op)
330  {
331  case OP_DELETE:
332  case OP_UNDELETE:
333  if (menu->tagprefix)
334  {
335  ARRAY_FOREACH(avp, &mdata->ava)
336  {
337  if (avp->is_tagged)
338  avp->is_deleted = (op == OP_DELETE);
339  }
341  }
342  else
343  {
344  int index = menu_get_index(menu);
345  ARRAY_GET(&mdata->ava, index)->is_deleted = (op == OP_DELETE);
347  const bool c_resolve = cs_subset_bool(NeoMutt->sub, "resolve");
348  if (c_resolve && (index < (menu->max - 1)))
349  {
350  menu_set_index(menu, index + 1);
352  }
353  }
354  break;
355  case OP_SORT:
356  case OP_SORT_REVERSE:
357  {
358  int sort = cs_subset_sort(mdata->sub, "sort_alias");
359  bool resort = true;
360  bool reverse = (op == OP_SORT_REVERSE);
361 
362  switch (mutt_multi_choice(
363  reverse ?
364  /* L10N: The highlighted letters must match the "Sort" options */
365  _("Rev-Sort (a)lias, a(d)dress or (u)nsorted?") :
366  /* L10N: The highlighted letters must match the "Rev-Sort" options */
367  _("Sort (a)lias, a(d)dress or (u)nsorted?"),
368  /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
369  _("adu")))
370  {
371  case -1: /* abort */
372  resort = false;
373  break;
374 
375  case 1: /* (a)lias */
376  sort = SORT_ALIAS;
377  break;
378 
379  case 2: /* a(d)dress */
380  sort = SORT_ADDRESS;
381  break;
382 
383  case 3: /* (u)nsorted */
384  sort = SORT_ORDER;
385  break;
386  }
387 
388  if (resort)
389  {
390  sort |= reverse ? SORT_REVERSE : 0;
391 
392  // This will trigger a WA_RECALC
393  cs_subset_str_native_set(mdata->sub, "sort_alias", sort, NULL);
394  }
395 
396  break;
397  }
398  case OP_SEARCH_REVERSE:
399  case OP_SEARCH_NEXT:
400  case OP_SEARCH_OPPOSITE:
401  case OP_SEARCH:
402  {
403  int index = mutt_search_alias_command(menu, menu_get_index(menu), op);
404  if (index == -1)
405  break;
406 
407  menu_set_index(menu, index);
408  break;
409  }
410 
411  case OP_MAIN_LIMIT:
412  {
413  int rc = mutt_pattern_alias_func(MUTT_LIMIT, _("Limit to messages matching: "),
414  mdata, menu);
415  if (rc == 0)
416  {
417  alias_set_title(sbar, _("Aliases"), mdata->str);
419  }
420 
421  break;
422  }
423 
424  case OP_GENERIC_SELECT_ENTRY:
425  t = menu_get_index(menu);
426  if (t >= ARRAY_SIZE(&mdata->ava))
427  t = -1;
428  done = true;
429  break;
430  case OP_EXIT:
431  done = true;
432  break;
433  }
434  }
435 
436  ARRAY_FOREACH(avp, &mdata->ava)
437  {
438  if (avp->is_tagged)
439  {
440  mutt_addrlist_write(&avp->alias->addr, buf, buflen, true);
441  t = -1;
442  }
443  }
444 
445  if (t != -1)
446  {
447  mutt_addrlist_write(&ARRAY_GET(&mdata->ava, t)->alias->addr, buf, buflen, true);
448  }
449 
450  simple_dialog_free(&dlg);
451 }
452 
465 int alias_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
466 {
467  struct Alias *np = NULL;
468  char bestname[8192] = { 0 };
469 
470  struct AliasMenuData mdata = { NULL, ARRAY_HEAD_INITIALIZER, sub };
471  mdata.str = mutt_str_dup(buf);
472 
473  if (buf[0] != '\0')
474  {
475  TAILQ_FOREACH(np, &Aliases, entries)
476  {
477  if (np->name && mutt_strn_equal(np->name, buf, strlen(buf)))
478  {
479  if (bestname[0] == '\0') /* init */
480  {
481  mutt_str_copy(bestname, np->name,
482  MIN(mutt_str_len(np->name) + 1, sizeof(bestname)));
483  }
484  else
485  {
486  int i;
487  for (i = 0; np->name[i] && (np->name[i] == bestname[i]); i++)
488  ; // do nothing
489 
490  bestname[i] = '\0';
491  }
492  }
493  }
494 
495  if (bestname[0] != '\0')
496  {
497  /* fake the pattern for menu title */
498  char *mtitle = NULL;
499  mutt_str_asprintf(&mtitle, "~f ^%s", buf);
500  FREE(&mdata.str);
501  mdata.str = mtitle;
502 
503  if (!mutt_str_equal(bestname, buf))
504  {
505  /* we are adding something to the completion */
506  mutt_str_copy(buf, bestname, mutt_str_len(bestname) + 1);
507  FREE(&mdata.str);
508  return 1;
509  }
510 
511  /* build alias list and show it */
512  TAILQ_FOREACH(np, &Aliases, entries)
513  {
514  int aasize = alias_array_alias_add(&mdata.ava, np);
515 
516  struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
517 
518  if (np->name && !mutt_strn_equal(np->name, buf, strlen(buf)))
519  {
520  av->is_visible = false;
521  }
522  }
523  }
524  }
525 
526  if (ARRAY_EMPTY(&mdata.ava))
527  {
528  TAILQ_FOREACH(np, &Aliases, entries)
529  {
530  alias_array_alias_add(&mdata.ava, np);
531  }
532 
533  mutt_pattern_alias_func(MUTT_LIMIT, NULL, &mdata, NULL);
534  }
535 
536  alias_array_sort(&mdata.ava, mdata.sub);
537 
538  bestname[0] = '\0';
539  dlg_select_alias(bestname, sizeof(bestname), &mdata);
540  if (bestname[0] != '\0')
541  mutt_str_copy(buf, bestname, buflen);
542 
543  struct AliasView *avp = NULL;
544  ARRAY_FOREACH(avp, &mdata.ava)
545  {
546  if (!avp->is_deleted)
547  continue;
548 
549  TAILQ_REMOVE(&Aliases, avp->alias, entries);
550  alias_free(&avp->alias);
551  }
552 
553  ARRAY_FREE(&mdata.ava);
554  FREE(&mdata.str);
555 
556  return 0;
557 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
A shortcut for an email address or addresses.
Definition: alias.h:33
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:550
char * name
Short name.
Definition: alias.h:35
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
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
static void dlg_select_alias(char *buf, size_t buflen, struct AliasMenuData *mdata)
Display a menu of Aliases.
Definition: dlgalias.c:303
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:165
#define MIN(a, b)
Definition: memory.h:31
Definition: lib.h:67
Data passed to a notification function.
Definition: observer.h:39
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
An Event that happened to a Window.
Definition: mutt_window.h:215
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:198
Messages in limited view.
Definition: mutt.h:101
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
#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
int alias_array_count_visible(struct AliasViewArray *ava)
Count number of visible Aliases.
Definition: array.c:91
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:35
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:54
An alias-change event.
Definition: alias.h:63
Window is about to be deleted.
Definition: mutt_window.h:206
GUI data wrapping an Alias.
Definition: gui.h:35
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:45
int mutt_pattern_alias_func(int op, char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:241
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.
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
void alias_set_title(struct MuttWindow *sbar, char *menu_name, char *limit)
Create a title string for the Menu.
Definition: gui.c:67
Convenience wrapper for the config headers.
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:105
void alias_array_sort(struct AliasViewArray *ava, const struct ConfigSubset *sub)
Sort and reindex an AliasViewArray.
Definition: sort.c:157
Email Address Handling.
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
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:305
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
Alias is about to be deleted.
Definition: alias.h:55
Many unsorted constants and some structs.
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
Convenience wrapper for the core headers.
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:54
char * str
String representing the limit being used.
Definition: gui.h:54
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
#define mutt_warning(...)
Definition: logging.h:86
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
int alias_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: gui.c:43
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
bool is_visible
Is visible?
Definition: gui.h:43
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:57
A set of inherited config items.
Definition: subset.h:46
struct Alias * alias
Alias.
Definition: gui.h:44
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void * mdata
Private data.
Definition: lib.h:155
int alias_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t.
Definition: dlgalias.c:241
Alias has been added.
Definition: alias.h:54
bool tagprefix
User has pressed <tag-prefix>
Definition: lib.h:75
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
Match patterns to emails.
struct Alias * alias
Definition: alias.h:65
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int alias_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
alias completion routine
Definition: dlgalias.c:465
Sort by email alias.
Definition: sort2.h:53
char * comment
Free-form comment string.
Definition: alias.h:37
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:49
Ask the user a question.
static int alias_alias_observer(struct NotifyCallback *nc)
Notification that an Alias has changed - Implements observer_t.
Definition: dlgalias.c:196
struct MuttWindow * alias_dialog_new(struct AliasMenuData *mdata)
Create an Alias Selection Dialog.
Definition: dlgalias.c:269
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:130
bool custom_search
The menu implements its own non-Menusearch()-compatible search, trickle OP_SEARCH*.
Definition: lib.h:93
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:629
static void alias_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the alias list - Implements Menu::make_entry() -.
Definition: dlgalias.c:165
int max
Number of entries in the menu.
Definition: lib.h:71
void * event_data
Data from notify_send()
Definition: observer.h:44
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
bool is_tagged
Is it tagged?
Definition: gui.h:41
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
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:749
struct ConfigSubset * sub
Config items.
Definition: gui.h:56
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
int alias_array_alias_delete(struct AliasViewArray *ava, struct Alias *alias)
Delete an Alias from the AliasViewArray.
Definition: array.c:69
#define FREE(x)
Definition: memory.h:40
Mapping between user-readable string and a constant.
Definition: mapping.h:31
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:128
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:55
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:171
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
Select an email address by its alias.
Definition: type.h:37
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
Log at debug level 5.
Definition: logging.h:44
Convenience wrapper for the library headers.
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
static int alias_tag(struct Menu *menu, int sel, int act)
Tag some aliases - Implements Menu::tag() -.
Definition: dlgalias.c:180
int num
Index number in list.
Definition: gui.h:37
void * wdata
Private data.
Definition: mutt_window.h:145
#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:652
bool is_deleted
Is it deleted?
Definition: gui.h:42
Shared code for the Alias and Query Dialogs.
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
static const char * alias_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 alias list - Implements format_t -Expando Description %a Alias name %c Comme...
Definition: dlgalias.c:123
int alias_recalc(struct MuttWindow *win)
Recalculate the display of the Alias Window - Implements MuttWindow::recalc() -.
Definition: gui.c:87
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
Alias Dialog, dlg_select_alias()
Definition: mutt_window.h:77