X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=alias.c;h=835d55a4af6747829b9a98702712022ff6eaaa7c;hp=5d833571191bf89d6ed7d2444484ac51a9bc1f18;hb=91d0c04349c9345f0ee29a61cc18dfc144b60edc;hpb=f404a0ca916be07049af51a3022baaaaab94def6 diff --git a/alias.c b/alias.c index 5d83357..835d55a 100644 --- a/alias.c +++ b/alias.c @@ -1,110 +1,112 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2002 Michael R. Elkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ #if HAVE_CONFIG_H # include "config.h" #endif +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "lib/rx.h" +#include "lib/debug.h" + #include "mutt.h" -#include "mutt_regex.h" +#include "enter.h" #include "mutt_curses.h" #include "mutt_idna.h" +#include "mutt_menu.h" +#include "sort.h" -#include -#include +#define RSORT(x) (SortAlias & SORT_REVERSE) ? -x : x + +static struct mapping_t AliasHelp[] = { + {N_("Exit"), OP_EXIT}, + {N_("Del"), OP_DELETE}, + {N_("Undel"), OP_UNDELETE}, + {N_("Select"), OP_GENERIC_SELECT_ENTRY}, + {N_("Help"), OP_HELP}, + {NULL, OP_NULL} +}; ADDRESS *mutt_lookup_alias (const char *s) { ALIAS *t = Aliases; for (; t; t = t->next) - if (!mutt_strcasecmp (s, t->name)) + if (!m_strcasecmp(s, t->name)) return (t->addr); - return (NULL); /* no such alias */ + return (NULL); /* no such alias */ } -static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) +static ADDRESS *mutt_expand_aliases_r (ADDRESS * a, LIST ** expn) { ADDRESS *head = NULL, *last = NULL, *t, *w; LIST *u; char i; const char *fqdn; - - while (a) - { - if (!a->group && !a->personal && a->mailbox && strchr (a->mailbox, '@') == NULL) - { + + while (a) { + if (!a->group && !a->personal && a->mailbox + && strchr (a->mailbox, '@') == NULL) { t = mutt_lookup_alias (a->mailbox); - if (t) - { + if (t) { i = 0; - for (u = *expn; u; u = u->next) - { - if (mutt_strcmp (a->mailbox, u->data) == 0) /* alias already found */ - { - dprint (1, (debugfile, "mutt_expand_aliases_r(): loop in alias found for '%s'\n", a->mailbox)); - i = 1; - break; - } - } - - if (!i) - { - u = safe_malloc (sizeof (LIST)); - u->data = safe_strdup (a->mailbox); + for (u = *expn; u; u = u->next) { + if (m_strcmp(a->mailbox, u->data) == 0) { /* alias already found */ + debug_print(1, ("loop in alias found for '%s'\n", a->mailbox)); + i = 1; + break; + } + } + + if (!i) { + u = p_new(LIST, 1); + u->data = m_strdup(a->mailbox); u->next = *expn; *expn = u; - w = rfc822_cpy_adr (t); - w = mutt_expand_aliases_r (w, expn); - if (head) - last->next = w; - else - head = last = w; - while (last && last->next) - last = last->next; + w = rfc822_cpy_adr (t); + w = mutt_expand_aliases_r (w, expn); + if (head) + last->next = w; + else + head = last = w; + while (last && last->next) + last = last->next; } - t = a; - a = a->next; - t->next = NULL; - rfc822_free_address (&t); - continue; + t = a; + a = a->next; + t->next = NULL; + rfc822_free_address (&t); + continue; } - else - { - struct passwd *pw = getpwnam (a->mailbox); - - if (pw) - { - char namebuf[STRING]; - - mutt_gecos_name (namebuf, sizeof (namebuf), pw); - mutt_str_replace (&a->personal, namebuf); - -#ifdef EXACT_ADDRESS - FREE (&a->val); -#endif - } + else { + struct passwd *pw = getpwnam (a->mailbox); + + if (pw) { + char namebuf[STRING]; + + mutt_gecos_name (namebuf, sizeof (namebuf), pw); + str_replace (&a->personal, namebuf); + } } } - if (head) - { + if (head) { last->next = a; last = last->next; } @@ -114,8 +116,7 @@ static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) last->next = NULL; } - if (option (OPTUSEDOMAIN) && (fqdn = mutt_fqdn(1))) - { + if (option (OPTUSEDOMAIN) && (fqdn = mutt_fqdn (1))) { /* now qualify all local addresses */ rfc822_qualify (head, fqdn); } @@ -123,17 +124,17 @@ static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) return (head); } -ADDRESS *mutt_expand_aliases (ADDRESS *a) +ADDRESS *mutt_expand_aliases (ADDRESS * a) { ADDRESS *t; - LIST *expn = NULL; /* previously expanded aliases to avoid loops */ + LIST *expn = NULL; /* previously expanded aliases to avoid loops */ t = mutt_expand_aliases_r (a, &expn); mutt_free_list (&expn); return (mutt_remove_duplicates (t)); } -void mutt_expand_aliases_env (ENVELOPE *env) +void mutt_expand_aliases_env (ENVELOPE * env) { env->from = mutt_expand_aliases (env->from); env->to = mutt_expand_aliases (env->to); @@ -165,53 +166,47 @@ void mutt_expand_aliases_env (ENVELOPE *env) * variable. */ -static void write_safe_address (FILE *fp, char *s) +static void write_safe_address (FILE * fp, char *s) { - while (*s) - { - if (*s == '\\' || *s == '`' || *s == '\'' || *s == '"' - || *s == '$') + while (*s) { + if (*s == '\\' || *s == '`' || *s == '\'' || *s == '"' || *s == '$') fputc ('\\', fp); fputc (*s, fp); s++; } } -ADDRESS *mutt_get_address (ENVELOPE *env, char **pfxp) +ADDRESS *mutt_get_address (ENVELOPE * env, const char **pfxp) { ADDRESS *adr; - char *pfx = NULL; + const char *pfx = NULL; - if (mutt_addr_is_user (env->from)) - { - if (env->to && !mutt_is_mail_list (env->to)) - { + if (mutt_addr_is_user (env->from)) { + if (env->to && !mutt_is_mail_list (env->to)) { pfx = "To"; adr = env->to; } - else - { + else { pfx = "Cc"; adr = env->cc; } } - else if (env->reply_to && !mutt_is_mail_list (env->reply_to)) - { + else if (env->reply_to && !mutt_is_mail_list (env->reply_to)) { pfx = "Reply-To"; adr = env->reply_to; } - else - { + else { adr = env->from; pfx = "From"; } - if (pfxp) *pfxp = pfx; + if (pfxp) + *pfxp = pfx; return adr; } -void mutt_create_alias (ENVELOPE *cur, ADDRESS *iadr) +void mutt_create_alias (ENVELOPE * cur, ADDRESS * iadr) { ALIAS *new, *t; char buf[LONG_STRING], prompt[SHORT_STRING], *pc; @@ -220,18 +215,15 @@ void mutt_create_alias (ENVELOPE *cur, ADDRESS *iadr) FILE *rc; ADDRESS *adr = NULL; - if (cur) - { + if (cur) { adr = mutt_get_address (cur, NULL); } - else if (iadr) - { + else if (iadr) { adr = iadr; } - if (adr && adr->mailbox) - { - strfcpy (buf, adr->mailbox, sizeof (buf)); + if (adr && adr->mailbox) { + m_strcpy(buf, sizeof(buf), adr->mailbox); if ((pc = strchr (buf, '@'))) *pc = 0; } @@ -240,86 +232,79 @@ void mutt_create_alias (ENVELOPE *cur, ADDRESS *iadr) /* Don't suggest a bad alias name in the event of a strange local part. */ mutt_check_alias_name (buf, buf); - + retry_name: /* add a new alias */ if (mutt_get_field (_("Alias as: "), buf, sizeof (buf), 0) != 0 || !buf[0]) return; /* check to see if the user already has an alias defined */ - if (mutt_lookup_alias (buf)) - { + if (mutt_lookup_alias (buf)) { mutt_error _("You already have an alias defined with that name!"); + return; } - - if (mutt_check_alias_name (buf, fixed)) - { - switch (mutt_yesorno (_("Warning: This alias name may not work. Fix it?"), M_YES)) - { - case M_YES: - strfcpy (buf, fixed, sizeof (buf)); - goto retry_name; - case -1: - return; + + if (mutt_check_alias_name (buf, fixed)) { + switch (mutt_yesorno + (_("Warning: This alias name may not work. Fix it?"), M_YES)) { + case M_YES: + m_strcpy(buf, sizeof(buf), fixed); + goto retry_name; + case -1: + return; } } - - new = safe_calloc (1, sizeof (ALIAS)); + + new = p_new(ALIAS, 1); new->self = new; - new->name = safe_strdup (buf); + new->name = m_strdup(buf); mutt_addrlist_to_local (adr); - + if (adr) - strfcpy (buf, adr->mailbox, sizeof (buf)); + m_strcpy(buf, sizeof(buf), adr->mailbox); else buf[0] = 0; mutt_addrlist_to_idna (adr, NULL); - - do - { - if (mutt_get_field (_("Address: "), buf, sizeof (buf), 0) != 0 || !buf[0]) - { + + do { + if (mutt_get_field (_("Address: "), buf, sizeof (buf), 0) != 0 || !buf[0]) { mutt_free_alias (&new); return; } - - if((new->addr = rfc822_parse_adrlist (new->addr, buf)) == NULL) + + if ((new->addr = rfc822_parse_adrlist (new->addr, buf)) == NULL) BEEP (); - if (mutt_addrlist_to_idna (new->addr, &err)) - { + if (mutt_addrlist_to_idna (new->addr, &err)) { mutt_error (_("Error: '%s' is a bad IDN."), err); mutt_sleep (2); continue; } } - while(new->addr == NULL); - - if (adr && adr->personal && !mutt_is_mail_list (adr)) - strfcpy (buf, adr->personal, sizeof (buf)); + while (new->addr == NULL); + + if (adr && adr->personal && !mutt_is_mail_list(adr)) + m_strcpy(buf, sizeof(buf), adr->personal); else buf[0] = 0; - if (mutt_get_field (_("Personal name: "), buf, sizeof (buf), 0) != 0) - { + if (mutt_get_field (_("Personal name: "), buf, sizeof (buf), 0) != 0) { mutt_free_alias (&new); return; } - new->addr->personal = safe_strdup (buf); + new->addr->personal = m_strdup(buf); buf[0] = 0; rfc822_write_address (buf, sizeof (buf), new->addr, 1); snprintf (prompt, sizeof (prompt), _("[%s = %s] Accept?"), new->name, buf); - if (mutt_yesorno (prompt, M_YES) != M_YES) - { + if (mutt_yesorno (prompt, M_YES) != M_YES) { mutt_free_alias (&new); return; } - if ((t = Aliases)) - { + if ((t = Aliases)) { while (t->next) t = t->next; t->next = new; @@ -327,16 +312,15 @@ retry_name: else Aliases = new; - strfcpy (buf, NONULL (AliasFile), sizeof (buf)); + m_strcpy(buf, sizeof(buf), NONULL(AliasFile)); if (mutt_get_field (_("Save to file: "), buf, sizeof (buf), M_FILE) != 0) return; mutt_expand_path (buf, sizeof (buf)); - if ((rc = safe_fopen (buf, "a"))) - { + if ((rc = safe_fopen (buf, "a"))) { if (mutt_check_alias_name (new->name, NULL)) - mutt_quote_filename (buf, sizeof (buf), new->name); + mutt_quote_filename(buf, sizeof(buf), new->name); else - strfcpy (buf, new->name, sizeof (buf)); + m_strcpy(buf, sizeof(buf), new->name); fprintf (rc, "alias %s ", buf); buf[0] = 0; rfc822_write_address (buf, sizeof (buf), new->addr, 0); @@ -357,22 +341,20 @@ retry_name: static int check_alias_name_char (char c) { return (c == '-' || c == '_' || c == '+' || c == '=' || c == '.' || - isalnum ((unsigned char) c)); + isalnum ((unsigned char) c)); } int mutt_check_alias_name (const char *s, char *d) { int rv = 0; - for (; *s; s++) - { - if (!check_alias_name_char (*s)) - { + + for (; *s; s++) { + if (!check_alias_name_char (*s)) { if (!d) - return -1; - else - { - *d++ = '_'; - rv = -1; + return -1; + else { + *d++ = '_'; + rv = -1; } } else if (d) @@ -387,7 +369,7 @@ int mutt_check_alias_name (const char *s, char *d) * This routine looks to see if the user has an alias defined for the given * address. */ -ADDRESS *alias_reverse_lookup (ADDRESS *a) +ADDRESS *alias_reverse_lookup (ADDRESS * a) { ALIAS *t = Aliases; ADDRESS *ap; @@ -395,14 +377,12 @@ ADDRESS *alias_reverse_lookup (ADDRESS *a) if (!a || !a->mailbox) return NULL; - for (; t; t = t->next) - { + for (; t; t = t->next) { /* cycle through all addresses if this is a group alias */ - for (ap = t->addr; ap; ap = ap->next) - { + for (ap = t->addr; ap; ap = ap->next) { if (!ap->group && ap->mailbox && - ascii_strcasecmp (ap->mailbox, a->mailbox) == 0) - return ap; + ascii_strcasecmp (ap->mailbox, a->mailbox) == 0) + return ap; } } return 0; @@ -423,162 +403,335 @@ int mutt_alias_complete (char *s, size_t buflen) #define min(a,b) ((aname && strstr (a->name, s) == a->name) - { - if (!bestname[0]) /* init */ - strfcpy (bestname, a->name, - min (mutt_strlen (a->name) + 1, sizeof (bestname))); - else - { - for (i = 0 ; a->name[i] && a->name[i] == bestname[i] ; i++) - ; - bestname[i] = 0; - } + if (s[0] != 0) { /* avoid empty string as strstr argument */ + p_clear(bestname, sizeof(bestname)); + + while (a) { + if (a->name && strstr (a->name, s) == a->name) { + if (!bestname[0]) /* init */ + m_strcpy(bestname, MIN(m_strlen(a->name) + 1, sizeof(bestname)), + a->name); + else { + for (i = 0; a->name[i] && a->name[i] == bestname[i]; i++); + bestname[i] = 0; + } } a = a->next; } - if (bestname[0] != 0) - { - if (mutt_strcmp (bestname, s) != 0) - { - /* we are adding something to the completion */ - strfcpy (s, bestname, mutt_strlen (bestname) + 1); - return 1; + if (bestname[0] != 0) { + if (m_strcmp(bestname, s) != 0) { + /* we are adding something to the completion */ + m_strcpy(s, m_strlen(bestname) + 1, bestname); + return 1; } /* build alias list and show it */ a = Aliases; - while (a) - { - if (a->name && (strstr (a->name, s) == a->name)) - { - if (!a_list) /* init */ - a_cur = a_list = (ALIAS *) safe_malloc (sizeof (ALIAS)); - else - { - a_cur->next = (ALIAS *) safe_malloc (sizeof (ALIAS)); - a_cur = a_cur->next; - } - memcpy (a_cur, a, sizeof (ALIAS)); - a_cur->next = NULL; - } - a = a->next; + while (a) { + if (a->name && (strstr (a->name, s) == a->name)) { + if (!a_list) /* init */ + a_cur = a_list = p_new(ALIAS, 1); + else { + a_cur->next = p_new(ALIAS, 1); + a_cur = a_cur->next; + } + memcpy (a_cur, a, sizeof (ALIAS)); + a_cur->next = NULL; + } + a = a->next; } } } bestname[0] = 0; - mutt_alias_menu (bestname, sizeof(bestname), a_list ? a_list : Aliases); + mutt_alias_menu (bestname, sizeof (bestname), a_list ? a_list : Aliases); if (bestname[0] != 0) - strfcpy (s, bestname, buflen); + m_strcpy(s, buflen, bestname); /* free the alias list */ - while (a_list) - { + while (a_list) { a_cur = a_list; a_list = a_list->next; - FREE (&a_cur); + p_delete(&a_cur); } /* remove any aliases marked for deletion */ a_list = NULL; - for (a_cur = Aliases; a_cur;) - { - if (a_cur->del) - { + for (a_cur = Aliases; a_cur;) { + if (a_cur->del) { if (a_list) - a_list->next = a_cur->next; + a_list->next = a_cur->next; else - Aliases = a_cur->next; - + Aliases = a_cur->next; + a_cur->next = NULL; mutt_free_alias (&a_cur); - + if (a_list) - a_cur = a_list; + a_cur = a_list; else - a_cur = Aliases; + a_cur = Aliases; } - else - { + else { a_list = a_cur; - a_cur = a_cur->next; + a_cur = a_cur->next; } } - + return 0; } -static int string_is_address(const char *str, const char *u, const char *d) +static int string_is_address (const char *str, const char *u, const char *d) { char buf[LONG_STRING]; - - snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d)); - if (ascii_strcasecmp(str, buf) == 0) + + snprintf (buf, sizeof (buf), "%s@%s", NONULL (u), NONULL (d)); + if (ascii_strcasecmp (str, buf) == 0) return 1; - + return 0; } /* returns TRUE if the given address belongs to the user. */ -int mutt_addr_is_user (ADDRESS *addr) +int mutt_addr_is_user (ADDRESS * addr) { /* NULL address is assumed to be the user. */ - if (!addr) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, NULL address\n")); + if (!addr) { + debug_print(5, ("yes, NULL address\n")); return 1; } - if (!addr->mailbox) - { - dprint (5, (debugfile, "mail_addr_is_user: no, no mailbox\n")); + if (!addr->mailbox) { + debug_print(5, ("no, no mailbox\n")); return 0; } - if (ascii_strcasecmp (addr->mailbox, Username) == 0) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s = %s\n", addr->mailbox, Username)); + if (ascii_strcasecmp (addr->mailbox, Username) == 0) { + debug_print(5, ("yes, %s = %s\n", addr->mailbox, Username)); return 1; } - if (string_is_address(addr->mailbox, Username, Hostname)) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s = %s @ %s \n", addr->mailbox, Username, Hostname)); + if (string_is_address (addr->mailbox, Username, Hostname)) { + debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, Hostname)); return 1; } - if (string_is_address(addr->mailbox, Username, mutt_fqdn(0))) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (0))); + if (string_is_address (addr->mailbox, Username, mutt_fqdn (0))) { + debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (0))); return 1; } - if (string_is_address(addr->mailbox, Username, mutt_fqdn(1))) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (1))); + if (string_is_address (addr->mailbox, Username, mutt_fqdn (1))) { + debug_print(5, ("yes, %s = %s @ %s \n", addr->mailbox, Username, mutt_fqdn (1))); return 1; } - if (From && !ascii_strcasecmp (From->mailbox, addr->mailbox)) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s = %s\n", addr->mailbox, From->mailbox)); + if (From && !ascii_strcasecmp (From->mailbox, addr->mailbox)) { + debug_print(5, ("yes, %s = %s\n", addr->mailbox, From->mailbox)); return 1; } - if (mutt_match_rx_list (addr->mailbox, Alternates)) - { - dprint (5, (debugfile, "mail_addr_is_user: yes, %s matched by alternates.\n", addr->mailbox)); - if (mutt_match_rx_list (addr->mailbox, UnAlternates)) - dprint (5, (debugfile, "mail_addr_is_user: but, %s matched by unalternates.\n", addr->mailbox)); + if (rx_list_match (Alternates, addr->mailbox)) { + debug_print(5, ("yes, %s matched by alternates.\n", addr->mailbox)); + if (rx_list_match (UnAlternates, addr->mailbox)) + debug_print(5, ("but, %s matched by unalternates.\n", addr->mailbox)); else return 1; } - - dprint (5, (debugfile, "mail_addr_is_user: no, all failed.\n")); + + debug_print(5, ("no, all failed.\n")); return 0; } + +static const char *alias_format_str (char *dest, size_t destlen, char op, + const char *src, const char *fmt, + const char *ifstring, + const char *elsestring, + unsigned long data, format_flag flags) +{ + char tmp[SHORT_STRING], adr[SHORT_STRING]; + ALIAS *alias = (ALIAS *) data; + + switch (op) { + case 'f': + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, alias->del ? "D" : " "); + break; + case 'a': + mutt_format_s (dest, destlen, fmt, alias->name); + break; + case 'r': + adr[0] = 0; + rfc822_write_address (adr, sizeof (adr), alias->addr, 1); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, adr); + break; + case 'n': + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, alias->num + 1); + break; + case 't': + dest[0] = alias->tagged ? '*' : ' '; + dest[1] = 0; + break; + } + + return (src); +} + +static void alias_entry (char *s, size_t slen, MUTTMENU * m, int num) +{ + mutt_FormatString (s, slen, NONULL (AliasFmt), alias_format_str, + (unsigned long) ((ALIAS **) m->data)[num], + M_FORMAT_ARROWCURSOR); +} + +static int alias_tag (MUTTMENU * menu, int n, int m) +{ + ALIAS *cur = ((ALIAS **) menu->data)[n]; + int ot = cur->tagged; + + cur->tagged = (m >= 0 ? m : !cur->tagged); + + return cur->tagged - ot; +} + +static int alias_SortAlias (const void *a, const void *b) +{ + ALIAS *pa = *(ALIAS **) a; + ALIAS *pb = *(ALIAS **) b; + int r = m_strcasecmp(pa->name, pb->name); + + return (RSORT (r)); +} + +static int alias_SortAddress (const void *a, const void *b) +{ + ADDRESS *pa = (*(ALIAS **) a)->addr; + ADDRESS *pb = (*(ALIAS **) b)->addr; + int r; + + if (pa == pb) + r = 0; + else if (pa == NULL) + r = -1; + else if (pb == NULL) + r = 1; + else if (pa->personal) { + if (pb->personal) + r = m_strcasecmp(pa->personal, pb->personal); + else + r = 1; + } + else if (pb->personal) + r = -1; + else + r = ascii_strcasecmp (pa->mailbox, pb->mailbox); + return (RSORT (r)); +} + +void mutt_alias_menu (char *buf, size_t buflen, ALIAS * aliases) +{ + ALIAS *aliasp; + MUTTMENU *menu; + ALIAS **AliasTable = NULL; + int t = -1; + int i, done = 0; + int op; + char helpstr[SHORT_STRING]; + + int omax; + + if (!aliases) { + mutt_error _("You have no aliases!"); + + return; + } + + /* tell whoever called me to redraw the screen when I return */ + set_option (OPTNEEDREDRAW); + + menu = mutt_new_menu (); + menu->make_entry = alias_entry; + menu->tag = alias_tag; + menu->menu = MENU_ALIAS; + menu->title = _("Aliases"); + menu->help = + mutt_compile_help (helpstr, sizeof (helpstr), MENU_ALIAS, AliasHelp); + +new_aliases: + + omax = menu->max; + + /* count the number of aliases */ + for (aliasp = aliases; aliasp; aliasp = aliasp->next) { + aliasp->self->del = 0; + aliasp->self->tagged = 0; + menu->max++; + } + + p_realloc(&AliasTable, menu->max); + menu->data = AliasTable; + + for (i = omax, aliasp = aliases; aliasp; aliasp = aliasp->next, i++) { + AliasTable[i] = aliasp->self; + aliases = aliasp; + } + + if ((SortAlias & SORT_MASK) != SORT_ORDER) { + qsort (AliasTable, i, sizeof (ALIAS *), + (SortAlias & SORT_MASK) == + SORT_ADDRESS ? alias_SortAddress : alias_SortAlias); + } + + for (i = 0; i < menu->max; i++) + AliasTable[i]->num = i; + + while (!done) { + if (aliases->next) { + menu->redraw |= REDRAW_FULL; + aliases = aliases->next; + goto new_aliases; + } + + switch ((op = mutt_menuLoop (menu))) { + case OP_DELETE: + case OP_UNDELETE: + if (menu->tagprefix) { + for (i = 0; i < menu->max; i++) + if (AliasTable[i]->tagged) + AliasTable[i]->del = (op == OP_DELETE) ? 1 : 0; + menu->redraw |= REDRAW_INDEX; + } + else { + AliasTable[menu->current]->self->del = (op == OP_DELETE) ? 1 : 0; + menu->redraw |= REDRAW_CURRENT; + if (option (OPTRESOLVE) && menu->current < menu->max - 1) { + menu->current++; + menu->redraw |= REDRAW_INDEX; + } + } + break; + case OP_GENERIC_SELECT_ENTRY: + t = menu->current; + case OP_EXIT: + done = 1; + break; + } + } + + for (i = 0; i < menu->max; i++) { + if (AliasTable[i]->tagged) { + mutt_addrlist_to_local (AliasTable[i]->addr); + rfc822_write_address (buf, buflen, AliasTable[i]->addr, 0); + t = -1; + } + } + + if (t != -1) { + mutt_addrlist_to_local (AliasTable[t]->addr); + rfc822_write_address (buf, buflen, AliasTable[t]->addr, 0); + } + + mutt_menuDestroy (&menu); + p_delete(&AliasTable); + +}