diff -r 77256e350c2e OPS --- a/OPS Tue Feb 21 21:52:49 2006 +++ b/OPS Wed Mar 1 20:03:27 2006 @@ -158,6 +158,7 @@ OP_SHELL_ESCAPE "invoke a command in a subshell" OP_SORT "sort messages" OP_SORT_REVERSE "sort messages in reverse order" +OP_STATUS_COMMANDS "show status of most of the commands" OP_TAG "tag the current entry" OP_TAG_PREFIX "apply next function to tagged messages" OP_TAG_PREFIX_COND "apply next function ONLY to tagged messages" diff -r 77256e350c2e PATCHES --- a/PATCHES Tue Feb 21 21:52:49 2006 +++ b/PATCHES Wed Mar 1 20:03:27 2006 @@ -1,0 +1,1 @@ +assumed, comval, namequot, pattern diff -r 77256e350c2e charset.c --- a/charset.c Tue Feb 21 21:52:49 2006 +++ b/charset.c Wed Mar 1 20:03:27 2006 @@ -282,6 +282,21 @@ return !ascii_strcasecmp (buffer, chs); } +char *mutt_get_default_charset () +{ + static char fcharset[SHORT_STRING]; + const char *c = AssumedCharset; + const char *c1; + + if (c && *c) + { + c1 = strchr (c, ':'); + strfcpy (fcharset, c, c1 ? (c1 - c + 1) : sizeof (fcharset)); + } + else + strcpy (fcharset, "us-ascii"); /* __STRCPY_CHECKED__ */ + return fcharset; +} #ifndef HAVE_ICONV diff -r 77256e350c2e charset.h --- a/charset.h Tue Feb 21 21:52:49 2006 +++ b/charset.h Wed Mar 1 20:03:27 2006 @@ -47,6 +47,7 @@ void fgetconv_close (FGETCONV **); void mutt_set_langinfo_charset (void); +char *mutt_get_default_charset (); #define M_ICONV_HOOK_FROM 1 #define M_ICONV_HOOK_TO 2 diff -r 77256e350c2e copy.c --- a/copy.c Tue Feb 21 21:52:49 2006 +++ b/copy.c Wed Mar 1 20:03:27 2006 @@ -982,6 +982,7 @@ if ((a = rfc822_parse_adrlist (a, s + l)) == NULL) return 0; + rfc822_dequotepersonal_adrlist (a); mutt_addrlist_to_local (a); rfc2047_decode_adrlist (a); diff -r 77256e350c2e curs_lib.c --- a/curs_lib.c Tue Feb 21 21:52:49 2006 +++ b/curs_lib.c Wed Mar 1 20:03:27 2006 @@ -130,6 +130,7 @@ mutt_refresh (); getyx (stdscr, y, x); ret = _mutt_enter_string (buf, buflen, y, x, complete, multiple, files, numfiles, es); + complete &= ~(M_CLEAR); } while (ret == 1); CLEARLINE (LINES-1); diff -r 77256e350c2e curs_main.c --- a/curs_main.c Tue Feb 21 21:52:49 2006 +++ b/curs_main.c Wed Mar 1 20:03:27 2006 @@ -811,7 +811,7 @@ CHECK_ATTACH; mutt_pattern_func (M_DELETE, _("Delete messages matching: ")); - menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + menu->redraw = REDRAW_FULL; break; #ifdef USE_POP @@ -826,6 +826,14 @@ case OP_HELP: mutt_help (MENU_MAIN); + menu->redraw = REDRAW_FULL; + break; + + case OP_STATUS_COMMANDS: + + InComval = 1; + mutt_comval (); + InComval = 0; menu->redraw = REDRAW_FULL; break; @@ -866,8 +874,8 @@ menu->redraw = REDRAW_INDEX | REDRAW_STATUS; if (Context->msgcount && (Sort & SORT_MASK) == SORT_THREADS) mutt_draw_tree (Context); - menu->redraw = REDRAW_FULL; - } + } + menu->redraw = REDRAW_FULL; if (Context->pattern) mutt_message _("To view all messages, limit to \"all\"."); break; @@ -917,6 +925,8 @@ menu->current = menu->oldcurrent; else menu->redraw = REDRAW_MOTION; + if (op == OP_SEARCH || op == OP_SEARCH_REVERSE) + menu->redraw = REDRAW_FULL; break; case OP_SORT: @@ -966,7 +976,7 @@ CHECK_MSGCOUNT; CHECK_VISIBLE; mutt_pattern_func (M_TAG, _("Tag messages matching: ")); - menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + menu->redraw = REDRAW_FULL; break; case OP_MAIN_UNDELETE_PATTERN: @@ -979,16 +989,16 @@ CHECK_IMAP_ACL(IMAP_ACL_DELETE); #endif - if (mutt_pattern_func (M_UNDELETE, _("Undelete messages matching: ")) == 0) - menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + mutt_pattern_func (M_UNDELETE, _("Undelete messages matching: ")); + menu->redraw = REDRAW_FULL; break; case OP_MAIN_UNTAG_PATTERN: CHECK_MSGCOUNT; CHECK_VISIBLE; - if (mutt_pattern_func (M_UNTAG, _("Untag messages matching: ")) == 0) - menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + mutt_pattern_func (M_UNTAG, _("Untag messages matching: ")); + menu->redraw = REDRAW_FULL; break; /* -------------------------------------------------------------------- diff -r 77256e350c2e enter.c --- a/enter.c Tue Feb 21 21:52:49 2006 +++ b/enter.c Wed Mar 1 20:03:27 2006 @@ -567,6 +567,17 @@ else BEEP (); /* let the user know that nothing matched */ replace_part (state, 0, buf); + } + else if (flags & M_PATTERN) + { + if ((i = state->curpos) && state->wbuf[i - 1] == '~') + { + if (mutt_ask_pattern (buf, buflen)) + replace_part (state, i, buf); + rv = 1; + goto bye; + } + goto self_insert; } else goto self_insert; diff -r 77256e350c2e functions.h --- a/functions.h Tue Feb 21 21:52:49 2006 +++ b/functions.h Wed Mar 1 20:03:27 2006 @@ -50,6 +50,7 @@ { "half-up", OP_HALF_UP, "[" }, { "half-down", OP_HALF_DOWN, "]" }, { "help", OP_HELP, "?" }, + { "status-commands", OP_STATUS_COMMANDS, NULL }, { "tag-prefix", OP_TAG_PREFIX, ";" }, { "tag-prefix-cond", OP_TAG_PREFIX_COND, NULL }, { "end-cond", OP_END_COND, NULL }, @@ -213,6 +214,7 @@ OP_MAIN_NEXT_NEW_THEN_UNREAD, "\t" }, { "pipe-message", OP_PIPE, "|" }, { "help", OP_HELP, "?" }, + { "status-commands", OP_STATUS_COMMANDS, NULL }, { "next-page", OP_NEXT_PAGE, " " }, { "previous-page", OP_PREV_PAGE, "-" }, { "top", OP_PAGER_TOP, "^" }, diff -r 77256e350c2e globals.h --- a/globals.h Tue Feb 21 21:52:49 2006 +++ b/globals.h Wed Mar 1 20:03:27 2006 @@ -33,6 +33,7 @@ WHERE char *AliasFile; WHERE char *AliasFmt; +WHERE char *AssumedCharset; WHERE char *AttachSep; WHERE char *Attribution; WHERE char *AttachFormat; @@ -179,6 +180,7 @@ WHERE short ConnectTimeout; WHERE short HistSize; +WHERE short InComval INITVAL (0); WHERE short MenuContext; WHERE short PagerContext; WHERE short PagerIndexLines; diff -r 77256e350c2e handler.c --- a/handler.c Tue Feb 21 21:52:49 2006 +++ b/handler.c Wed Mar 1 20:03:27 2006 @@ -1746,6 +1746,8 @@ if (istext && s->flags & M_CHARCONV) { char *charset = mutt_get_parameter ("charset", b->parameter); + if (!charset && AssumedCharset && *AssumedCharset) + charset = mutt_get_default_charset (); if (charset && Charset) cd = mutt_iconv_open (Charset, charset, M_ICONV_HOOK_FROM); } diff -r 77256e350c2e hdrline.c --- a/hdrline.c Tue Feb 21 21:52:49 2006 +++ b/hdrline.c Wed Mar 1 20:03:27 2006 @@ -59,7 +59,11 @@ if (mutt_is_subscribed_list (adr)) { if (pfx && buf && buflen) - snprintf (buf, buflen, "%s%s", pfx, mutt_get_name (adr)); + { + const char *name = mutt_get_name (adr); + snprintf (buf, buflen, "%s%s", pfx, name); + FREE (&name); + } return 1; } } @@ -102,6 +106,7 @@ static void make_from (ENVELOPE *hdr, char *buf, size_t len, int do_lists) { int me; + const char *name = NULL; me = mutt_addr_is_user (hdr->from); @@ -114,13 +119,16 @@ } if (me && hdr->to) - snprintf (buf, len, "To %s", mutt_get_name (hdr->to)); + snprintf (buf, len, "To %s", name = mutt_get_name (hdr->to)); else if (me && hdr->cc) - snprintf (buf, len, "Cc %s", mutt_get_name (hdr->cc)); + snprintf (buf, len, "Cc %s", name = mutt_get_name (hdr->cc)); else if (hdr->from) - strfcpy (buf, mutt_get_name (hdr->from), len); + strfcpy (buf, name = mutt_get_name (hdr->from), len); else *buf = 0; + + if (name) + FREE (&name); } static void make_from_addr (ENVELOPE *hdr, char *buf, size_t len, int do_lists) @@ -493,7 +501,11 @@ break; case 'n': - mutt_format_s (dest, destlen, prefix, mutt_get_name (hdr->env->from)); + { + const char *name = mutt_get_name (hdr->env->from); + mutt_format_s (dest, destlen, prefix, name); + FREE (&name); + } break; case 'N': @@ -588,10 +600,13 @@ if (!check_for_mailing_list (hdr->env->to, "To ", buf2, sizeof (buf2)) && !check_for_mailing_list (hdr->env->cc, "Cc ", buf2, sizeof (buf2))) { + const char *name = NULL; if (hdr->env->to) - snprintf (buf2, sizeof (buf2), "To %s", mutt_get_name (hdr->env->to)); + snprintf (buf2, sizeof (buf2), "To %s", name = mutt_get_name (hdr->env->to)); else if (hdr->env->cc) - snprintf (buf2, sizeof (buf2), "Cc %s", mutt_get_name (hdr->env->cc)); + snprintf (buf2, sizeof (buf2), "Cc %s", name = mutt_get_name (hdr->env->cc)); + if (name) + FREE (&name); } mutt_format_s (dest, destlen, prefix, buf2); break; @@ -617,15 +632,22 @@ case 'v': if (mutt_addr_is_user (hdr->env->from)) { + const char *name = NULL; if (hdr->env->to) - mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->to)); + mutt_format_s (buf2, sizeof (buf2), prefix, name = mutt_get_name (hdr->env->to)); else if (hdr->env->cc) - mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->cc)); + mutt_format_s (buf2, sizeof (buf2), prefix, name = mutt_get_name (hdr->env->cc)); else *buf2 = 0; - } - else - mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name (hdr->env->from)); + if (name) + FREE (&name); + } + else + { + const char *name = mutt_get_name (hdr->env->from); + mutt_format_s (buf2, sizeof (buf2), prefix, name); + FREE (&name); + } if ((p = strpbrk (buf2, " %@"))) *p = 0; mutt_format_s (dest, destlen, prefix, buf2); diff -r 77256e350c2e help.c --- a/help.c Tue Feb 21 21:52:49 2006 +++ b/help.c Wed Mar 1 20:03:27 2006 @@ -353,3 +353,46 @@ NULL) == OP_REFORMAT_WINCH); } + +void mutt_comval () +{ + char t[_POSIX_PATH_MAX]; + FILE *f; + BUFFER *comval; + + mutt_mktemp (t); + + do { + if ((f = safe_fopen (t, "w")) == NULL) + { + mutt_perror (t); + return; + } + + comval = NULL; + + comval = mutt_buffer_init (comval); + fputs (_("Status of commands:\n\n"), f); + if (!mutt_dump_command_values (comval, 0)) + fputs (comval->data, f); + else + fputs (_("unknown error"), f); + mutt_buffer_free (&comval); + + comval = mutt_buffer_init (comval); + fputs (_("\nUnused commands:\n\n"), f); + if (!mutt_dump_command_values (comval, 1)) + fputs (comval->data, f); + else + fputs (_("unknown error"), f); + mutt_buffer_free (&comval); + + fclose (f); + } + while + (mutt_do_pager (_("Status of commands"), t, + M_PAGER_RETWINCH | M_PAGER_MARKER | M_PAGER_NSKIP, + NULL) + == OP_REFORMAT_WINCH); +} + diff -r 77256e350c2e hook.c --- a/hook.c Tue Feb 21 21:52:49 2006 +++ b/hook.c Wed Mar 1 20:03:27 2006 @@ -485,3 +485,29 @@ FREE (&token.data); } #endif + +int mutt_dump_hook (BUFFER *buf, unsigned long type) +{ + HOOK *h; + char s[STRING]; + int match = 0; + if (!buf) + return 1; + for (h = Hooks; h; h = h->next) + { + if (h->type & type) + { + match = 1; + mutt_buffer_addstr (buf, h->rx.not ? "\n !( " : "\n "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, h->rx.pattern, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + mutt_buffer_addstr (buf, h->rx.not ? " )\n " : "\n "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, h->command, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + } + } + return (match) ? 0 : -1; +} + diff -r 77256e350c2e init.c --- a/init.c Tue Feb 21 21:52:49 2006 +++ b/init.c Wed Mar 1 20:03:27 2006 @@ -557,6 +557,40 @@ return nremoved; } +static int dump_spam_list (BUFFER *buf) +{ + SPAM_LIST *old, *spam; + char s[STRING]; + if (!buf) + return 1; + for (old = spam = SpamList; spam; spam = spam->next) + { + if (!spam->rx || !spam->template) + return 1; + mutt_buffer_addstr (buf, "\n "); + if (spam->rx->not) + mutt_buffer_addstr (buf, "!( "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, spam->rx->pattern, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + if (spam->rx->not) + mutt_buffer_addstr (buf, " )"); + + mutt_buffer_addstr (buf, "\n "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, spam->template, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + } + return ((old == spam) ? -1 : 0); +} + +static int dump_spam (BUFFER *buf, unsigned long data) +{ + if (data == M_SPAM) + return dump_spam_list (buf); + else + return dump_rx_list (buf, UL &NoSpamList); +} static void remove_from_list (LIST **l, const char *str) { @@ -664,6 +698,44 @@ while (MoreArgs (s)); return 0; +} + +static int dump_list (BUFFER *buf, unsigned long data) +{ + LIST *old, *lst; + char s[STRING]; + if (!buf) + return 1; + for (old = lst = *((LIST **) data); lst; lst = lst->next) + { + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, lst->data, sizeof (s), 0); + mutt_buffer_addstr (buf, "\n "); + mutt_buffer_addstr (buf, s); + } + return (old == lst) ? -1 : 0; +} + +static int dump_rx_list (BUFFER *buf, unsigned long data) +{ + RX_LIST *old, *rxl; + char s[STRING]; + if (!buf) + return 1; + for (old = rxl = *((RX_LIST **) data); rxl; rxl = rxl->next) + { + if (!rxl->rx) + return 1; + mutt_buffer_addstr (buf, "\n "); + if (rxl->rx->not) + mutt_buffer_addstr (buf, "!( "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, rxl->rx->pattern, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + if (rxl->rx->not) + mutt_buffer_addstr (buf, " )"); + } + return ((old == rxl) ? -1 : 0); } static void _alternates_clean (void) @@ -906,6 +978,48 @@ return -1; } +static int dump_group (BUFFER *buf, unsigned long data) +{ + int i, processed = 0; + struct hash_elem *t; + RX_LIST *rs; + ADDRESS *as; + + if (!buf) + return 1; + /* I know searching through a HASH is slow, but... */ + for (i = 0; i < Groups->nelem; i++) + { + t = Groups->table[i]; + if (t == NULL) + continue; + mutt_buffer_addstr (buf, "\n "); + mutt_buffer_addstr (buf, t->key); + if ((rs = ((group_t *)t->data)->rs)) + { + mutt_buffer_addstr (buf, "\n RX:"); + if (dump_rx_list (buf, UL &rs)) /* 1: unknown / -1: no RX */ + return 1; /* unknown error */ + processed = 1; + } + if ((as = ((group_t *)t->data)->as)) + { + mutt_buffer_addstr (buf, "\n ADDR:"); + while (as) + { + mutt_buffer_addstr (buf, "\n "); + if (as->mailbox) + mutt_buffer_addstr (buf, as->mailbox); + else + return 1; + as = as->next; + processed = 1; + } + } + } + return processed ? 0 : -1; +} + static int parse_ungroup (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { strfcpy (err->data, "not implemented", err->dsize); @@ -1175,6 +1289,58 @@ } return parse_unattach_list(buf, s, listp, err); +} + +static int _dump_attach_list (BUFFER *buf, LIST *data) +{ + LIST *lst; + char s[SHORT_STRING]; + + if (!buf) + return 1; + for (lst = data; lst; lst = lst->next) + { + mutt_buffer_addstr (buf, "\n "); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, ((ATTACH_MATCH *) lst->data)->major, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + mutt_buffer_addch (buf, '/'); + mutt_format_string (s, sizeof (s), 0, sizeof (s), 0, + 0, ((ATTACH_MATCH *) lst->data)->minor, sizeof (s), 0); + mutt_buffer_addstr (buf, s); + } + return (data == lst) ? -1 : 0; +} + +static int dump_attachments (BUFFER *buf, unsigned long data) +{ + int rv, used = 0; + BUFFER *tmpbuf = NULL; + + if (!buf) + return 1; + +#define DUMP_ATTACH_IF_USED(a,b) \ + tmpbuf = mutt_buffer_from (tmpbuf, "\n " a);\ + if (!(rv = _dump_attach_list (tmpbuf, b)))\ + {\ + used = 1;\ + mutt_buffer_addstr (buf, tmpbuf->data);\ + }\ + mutt_buffer_free (&tmpbuf);\ + if (rv == 1)\ + return 1 + + DUMP_ATTACH_IF_USED("+A", AttachAllow); + DUMP_ATTACH_IF_USED("-A", AttachExclude); + DUMP_ATTACH_IF_USED("+I", InlineAllow); + DUMP_ATTACH_IF_USED("-I", InlineExclude); +#undef DUMP_ATTACH_IF_USED + + if (used) + return 0; + else + return -1; } static int parse_unlists (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) @@ -3018,6 +3184,31 @@ return 0; } +int mutt_dump_command_values (BUFFER *buf, int unused) +{ + int i, rv = 0; + BUFFER *tmpbuf = NULL; + + mutt_buffer_addstr (buf, ""); /* make sure it is initialized */ + + for (i = 0; Commands[i].name; i++) + { + if (Commands[i].dump) + { + tmpbuf = mutt_buffer_init (tmpbuf); + mutt_buffer_addstr (tmpbuf, Commands[i].name); + rv = Commands[i].dump (tmpbuf, Commands[i].data); + mutt_buffer_addstr (tmpbuf, unused ? "\n" : "\n\n"); + if ((unused && rv == -1) || (!unused && !rv)) + mutt_buffer_addstr (buf, tmpbuf->data); + mutt_buffer_free (&tmpbuf); + if (rv == 1) + return 1; + } + } + return i ? 0 : 1; +} + static int parse_group_context (group_context_t **ctx, BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { while (!mutt_strcasecmp (buf->data, "-group")) diff -r 77256e350c2e init.h --- a/init.h Tue Feb 21 21:52:49 2006 +++ b/init.h Wed Mar 1 20:03:27 2006 @@ -203,6 +203,22 @@ ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before ** editing the body of an outgoing message. */ + { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL 0}, + /* + ** .pp + ** This variable is a colon-separated list of character encoding + ** schemes for messages without character encoding indication. + ** Header field values and message body content without character encoding + ** indication would be assumed that they are written in one of this list. + ** By default, all the header fields and message body without any charset + ** indication are assumed to be in "us-ascii". + ** .pp + ** For example, Japanese users might prefer this: + ** .pp + ** set assumed_charset="iso-2022-jp:euc-jp:shift_jis" + ** .pp + ** However, only the first content is valid for the message body. + */ { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " }, /* ** .pp @@ -3011,6 +3027,12 @@ static int parse_alternates (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_unalternates (BUFFER *, BUFFER *, unsigned long, BUFFER *); +static int dump_list (BUFFER *, unsigned long); +static int dump_rx_list (BUFFER *, unsigned long); +static int dump_spam (BUFFER *, unsigned long); +static int dump_group (BUFFER *, unsigned long); +static int dump_attachments (BUFFER *, unsigned long); + /* Parse -group arguments */ static int parse_group_context (group_context_t **ctx, BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err); @@ -3020,73 +3042,73 @@ char *name; int (*func) (BUFFER *, BUFFER *, unsigned long, BUFFER *); unsigned long data; - unsigned long data1; + int (*dump) (BUFFER *, unsigned long); }; struct command_t Commands[] = { - { "alternates", parse_alternates, 0 }, - { "unalternates", parse_unalternates, 0 }, + { "alternates", parse_alternates, UL &Alternates, dump_rx_list }, + { "unalternates", parse_unalternates, UL &UnAlternates,dump_rx_list}, #ifdef USE_SOCKET - { "account-hook", mutt_parse_hook, M_ACCOUNTHOOK }, + { "account-hook", mutt_parse_hook, M_ACCOUNTHOOK, mutt_dump_hook}, #endif - { "alias", parse_alias, 0 }, - { "attachments", parse_attachments, 0 }, - { "unattachments",parse_unattachments,0 }, - { "auto_view", parse_list, UL &AutoViewList }, - { "alternative_order", parse_list, UL &AlternativeOrderList}, - { "bind", mutt_parse_bind, 0 }, - { "charset-hook", mutt_parse_hook, M_CHARSETHOOK }, + { "alias", parse_alias, 0, NULL /* dump_alias */}, + { "attachments", parse_attachments, 0, dump_attachments }, + { "unattachments", parse_unattachments, 0, NULL }, + { "auto_view", parse_list, UL &AutoViewList, dump_list }, + { "alternative_order",parse_list, UL &AlternativeOrderList, dump_list }, + { "bind", mutt_parse_bind, 0, NULL }, + { "charset-hook", mutt_parse_hook, M_CHARSETHOOK, mutt_dump_hook}, #ifdef HAVE_COLOR - { "color", mutt_parse_color, 0 }, - { "uncolor", mutt_parse_uncolor, 0 }, + { "color", mutt_parse_color, 0, NULL /* dump_color */}, + { "uncolor", mutt_parse_uncolor, 0, NULL }, #endif - { "exec", mutt_parse_exec, 0 }, - { "fcc-hook", mutt_parse_hook, M_FCCHOOK }, - { "fcc-save-hook", mutt_parse_hook, M_FCCHOOK | M_SAVEHOOK }, - { "folder-hook", mutt_parse_hook, M_FOLDERHOOK }, - { "group", parse_group, 0 }, - { "ungroup", parse_ungroup, 0 }, - { "hdr_order", parse_list, UL &HeaderOrderList }, + { "exec", mutt_parse_exec, 0, NULL }, + { "fcc-hook", mutt_parse_hook, M_FCCHOOK, mutt_dump_hook}, + { "fcc-save-hook", mutt_parse_hook, M_FCCHOOK | M_SAVEHOOK, NULL }, + { "folder-hook", mutt_parse_hook, M_FOLDERHOOK, mutt_dump_hook}, + { "group", parse_group, 0, dump_group }, + { "ungroup", parse_ungroup, 0, NULL }, + { "hdr_order", parse_list, UL &HeaderOrderList, dump_list }, #ifdef HAVE_ICONV - { "iconv-hook", mutt_parse_hook, M_ICONVHOOK }, + { "iconv-hook", mutt_parse_hook, M_ICONVHOOK, mutt_dump_hook}, #endif - { "ignore", parse_ignore, 0 }, - { "lists", parse_lists, 0 }, - { "macro", mutt_parse_macro, 0 }, - { "mailboxes", mutt_parse_mailboxes, M_MAILBOXES }, - { "unmailboxes", mutt_parse_mailboxes, M_UNMAILBOXES }, - { "message-hook", mutt_parse_hook, M_MESSAGEHOOK }, - { "mbox-hook", mutt_parse_hook, M_MBOXHOOK }, - { "mime_lookup", parse_list, UL &MimeLookupList }, - { "unmime_lookup", parse_unlist, UL &MimeLookupList }, - { "mono", mutt_parse_mono, 0 }, - { "my_hdr", parse_my_hdr, 0 }, - { "pgp-hook", mutt_parse_hook, M_CRYPTHOOK }, - { "crypt-hook", mutt_parse_hook, M_CRYPTHOOK }, - { "push", mutt_parse_push, 0 }, - { "reply-hook", mutt_parse_hook, M_REPLYHOOK }, - { "reset", parse_set, M_SET_RESET }, - { "save-hook", mutt_parse_hook, M_SAVEHOOK }, - { "score", mutt_parse_score, 0 }, - { "send-hook", mutt_parse_hook, M_SENDHOOK }, - { "send2-hook", mutt_parse_hook, M_SEND2HOOK }, - { "set", parse_set, 0 }, - { "source", parse_source, 0 }, - { "spam", parse_spam_list, M_SPAM }, - { "nospam", parse_spam_list, M_NOSPAM }, - { "subscribe", parse_subscribe, 0 }, - { "toggle", parse_set, M_SET_INV }, - { "unalias", parse_unalias, 0 }, - { "unalternative_order",parse_unlist, UL &AlternativeOrderList }, - { "unauto_view", parse_unlist, UL &AutoViewList }, - { "unhdr_order", parse_unlist, UL &HeaderOrderList }, - { "unhook", mutt_parse_unhook, 0 }, - { "unignore", parse_unignore, 0 }, - { "unlists", parse_unlists, 0 }, - { "unmono", mutt_parse_unmono, 0 }, - { "unmy_hdr", parse_unmy_hdr, 0 }, - { "unscore", mutt_parse_unscore, 0 }, - { "unset", parse_set, M_SET_UNSET }, - { "unsubscribe", parse_unsubscribe, 0 }, + { "ignore", parse_ignore, UL &Ignore, dump_list }, + { "unignore", parse_unignore, UL &UnIgnore, dump_list }, + { "lists", parse_lists, UL &MailLists, dump_rx_list }, + { "unlists", parse_unlists, UL &UnMailLists,dump_rx_list }, + { "subscribe", parse_subscribe, UL &SubscribedLists, dump_rx_list }, + { "unsubscribe", parse_unsubscribe,UL &UnSubscribedLists,dump_rx_list }, + { "macro", mutt_parse_macro, 0, NULL }, + { "mailboxes", mutt_parse_mailboxes, M_MAILBOXES, NULL }, + { "unmailboxes", mutt_parse_mailboxes, M_UNMAILBOXES, NULL }, + { "message-hook", mutt_parse_hook, M_MESSAGEHOOK, mutt_dump_hook}, + { "mbox-hook", mutt_parse_hook, M_MBOXHOOK, mutt_dump_hook}, + { "mime_lookup", parse_list, UL &MimeLookupList, dump_list }, + { "unmime_lookup", parse_unlist, UL &MimeLookupList, NULL }, + { "mono", mutt_parse_mono, 0, NULL }, + { "my_hdr", parse_my_hdr, UL &UserHeader, dump_list }, + { "pgp-hook", mutt_parse_hook, M_CRYPTHOOK, mutt_dump_hook}, + { "crypt-hook", mutt_parse_hook, M_CRYPTHOOK, mutt_dump_hook}, + { "push", mutt_parse_push, 0, NULL }, + { "reply-hook", mutt_parse_hook, M_REPLYHOOK, mutt_dump_hook}, + { "reset", parse_set, M_SET_RESET, NULL }, + { "save-hook", mutt_parse_hook, M_SAVEHOOK, mutt_dump_hook}, + { "score", mutt_parse_score, 0 /*UL &Score*/, NULL /*dump_score*/}, + { "send-hook", mutt_parse_hook, M_SENDHOOK, mutt_dump_hook}, + { "send2-hook", mutt_parse_hook, M_SEND2HOOK, mutt_dump_hook}, + { "set", parse_set, 0, NULL }, + { "source", parse_source, 0, NULL }, + { "spam", parse_spam_list, M_SPAM, dump_spam }, + { "nospam", parse_spam_list, M_NOSPAM, dump_spam }, + { "toggle", parse_set, M_SET_INV, NULL }, + { "unalias", parse_unalias, 0, NULL }, + { "unalternative_order",parse_unlist, UL &AlternativeOrderList,NULL }, + { "unauto_view", parse_unlist, UL &AutoViewList, NULL }, + { "unhdr_order", parse_unlist, UL &HeaderOrderList, NULL }, + { "unhook", mutt_parse_unhook, 0, NULL }, + { "unmono", mutt_parse_unmono, 0, NULL }, + { "unmy_hdr", parse_unmy_hdr, 0, NULL }, + { "unscore", mutt_parse_unscore, 0, NULL }, + { "unset", parse_set, M_SET_UNSET, NULL }, { NULL } }; diff -r 77256e350c2e pager.c --- a/pager.c Tue Feb 21 21:52:49 2006 +++ b/pager.c Wed Mar 1 20:03:27 2006 @@ -2139,6 +2139,19 @@ mutt_error _("Help is currently being shown."); break; + case OP_STATUS_COMMANDS: + if (! InComval) + { + InComval = 1; + mutt_comval (); + redraw = REDRAW_FULL; + InComval = 0; + } + else + /* from either help or status-commands */ + mutt_error _("You have already invoked status-commands."); + break; + case OP_PAGER_HIDE_QUOTED: if (has_types) { diff -r 77256e350c2e parse.c --- a/parse.c Tue Feb 21 21:52:49 2006 +++ b/parse.c Wed Mar 1 20:03:27 2006 @@ -213,9 +213,23 @@ if (*s == '"') { + int state_ascii = 1; s++; - for (i=0; *s && *s != '"' && i < sizeof (buffer) - 1; i++, s++) + for (i=0; *s && i < sizeof (buffer) - 1; i++, s++) { + if (AssumedCharset && *AssumedCharset) { + /* As iso-2022-* has a characer of '"' with non-ascii state, + * ignore it. */ + if (*s == 0x1b && i < sizeof (buffer) - 2) + { + if (s[1] == '(' && (s[2] == 'B' || s[2] == 'J')) + state_ascii = 1; + else + state_ascii = 0; + } + } + if (state_ascii && *s == '"') + break; if (*s == '\\') { /* Quote the next character */ @@ -388,7 +402,9 @@ if (ct->type == TYPETEXT) { if (!(pc = mutt_get_parameter ("charset", ct->parameter))) - mutt_set_parameter ("charset", "us-ascii", &ct->parameter); + mutt_set_parameter ("charset", (AssumedCharset && *AssumedCharset) ? + (const char *) mutt_get_default_charset () + : "us-ascii", &ct->parameter); } } diff -r 77256e350c2e pattern.c --- a/pattern.c Tue Feb 21 21:52:49 2006 +++ b/pattern.c Wed Mar 1 20:03:27 2006 @@ -25,6 +25,8 @@ #include "keymap.h" #include "mailbox.h" #include "copy.h" +#include "mutt_menu.h" +#include "mutt_curses.h" #include #include @@ -45,57 +47,103 @@ static int eat_range (pattern_t *pat, BUFFER *, BUFFER *); static int patmatch (const pattern_t *pat, const char *buf); +#define EAT_REGEXP 1 +#define EAT_DATE 2 +#define EAT_RANGE 3 struct pattern_flags { int tag; /* character used to represent this op */ int op; /* operation to perform */ int class; - int (*eat_arg) (pattern_t *, BUFFER *, BUFFER *); + int eat_arg; + char *desc; } Flags[] = { - { 'A', M_ALL, 0, NULL }, - { 'b', M_BODY, M_FULL_MSG, eat_regexp }, - { 'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp }, - { 'c', M_CC, 0, eat_regexp }, - { 'C', M_RECIPIENT, 0, eat_regexp }, - { 'd', M_DATE, 0, eat_date }, - { 'D', M_DELETED, 0, NULL }, - { 'e', M_SENDER, 0, eat_regexp }, - { 'E', M_EXPIRED, 0, NULL }, - { 'f', M_FROM, 0, eat_regexp }, - { 'F', M_FLAG, 0, NULL }, - { 'g', M_CRYPT_SIGN, 0, NULL }, - { 'G', M_CRYPT_ENCRYPT, 0, NULL }, - { 'h', M_HEADER, M_FULL_MSG, eat_regexp }, - { 'H', M_HORMEL, 0, eat_regexp }, - { 'i', M_ID, 0, eat_regexp }, - { 'k', M_PGP_KEY, 0, NULL }, - { 'l', M_LIST, 0, NULL }, - { 'L', M_ADDRESS, 0, eat_regexp }, - { 'm', M_MESSAGE, 0, eat_range }, - { 'n', M_SCORE, 0, eat_range }, - { 'N', M_NEW, 0, NULL }, - { 'O', M_OLD, 0, NULL }, - { 'p', M_PERSONAL_RECIP, 0, NULL }, - { 'P', M_PERSONAL_FROM, 0, NULL }, - { 'Q', M_REPLIED, 0, NULL }, - { 'r', M_DATE_RECEIVED, 0, eat_date }, - { 'R', M_READ, 0, NULL }, - { 's', M_SUBJECT, 0, eat_regexp }, - { 'S', M_SUPERSEDED, 0, NULL }, - { 't', M_TO, 0, eat_regexp }, - { 'T', M_TAG, 0, NULL }, - { 'u', M_SUBSCRIBED_LIST, 0, NULL }, - { 'U', M_UNREAD, 0, NULL }, - { 'v', M_COLLAPSED, 0, NULL }, - { 'V', M_CRYPT_VERIFIED, 0, NULL }, - { 'x', M_REFERENCE, 0, eat_regexp }, - { 'X', M_MIMEATTACH, 0, eat_range }, - { 'y', M_XLABEL, 0, eat_regexp }, - { 'z', M_SIZE, 0, eat_range }, - { '=', M_DUPLICATED, 0, NULL }, - { '$', M_UNREFERENCED, 0, NULL }, + { 'A', M_ALL, 0, 0, + N_("all messages") }, + { 'b', M_BODY, M_FULL_MSG, EAT_REGEXP, + N_("messages whose body matches EXPR") }, + { 'B', M_WHOLE_MSG, M_FULL_MSG, EAT_REGEXP, + N_("messages whose body or headers match EXPR") }, + { 'c', M_CC, 0, EAT_REGEXP, + N_("messages whose CC header matches EXPR") }, + { 'C', M_RECIPIENT, 0, EAT_REGEXP, + N_("messages whose recipient matches EXPR") }, + { 'd', M_DATE, 0, EAT_DATE, + N_("messages sent in DATERANGE") }, + { 'D', M_DELETED, 0, 0, + N_("deleted messages") }, + { 'e', M_SENDER, 0, EAT_REGEXP, + N_("messages whose Sender header matches EXPR") }, + { 'E', M_EXPIRED, 0, 0, + N_("expired messages") }, + { 'f', M_FROM, 0, EAT_REGEXP, + N_("messages whose From header matches EXPR") }, + { 'F', M_FLAG, 0, 0, + N_("flagged messages") }, + { 'g', M_CRYPT_SIGN, 0, 0, + N_("cryptographically signed messages") }, + { 'G', M_CRYPT_ENCRYPT, 0, 0, + N_("cryptographically encrypted messages") }, + { 'h', M_HEADER, M_FULL_MSG, EAT_REGEXP, + N_("messages whose header matches EXPR") }, + { 'H', M_HORMEL, 0, EAT_REGEXP, + N_("messages whose spam tag matches EXPR") }, + { 'i', M_ID, 0, EAT_REGEXP, + N_("messages whose Message-ID matches EXPR") }, + { 'k', M_PGP_KEY, 0, 0, + N_("messages which contain PGP key") }, + { 'l', M_LIST, 0, 0, + N_("messages addressed to known mailing lists") }, + { 'L', M_ADDRESS, 0, EAT_REGEXP, + N_("messages whose From/Sender/To/CC matches EXPR") }, + { 'm', M_MESSAGE, 0, EAT_RANGE, + N_("messages whose number is in RANGE") }, + { 'n', M_SCORE, 0, EAT_RANGE, + N_("messages whose score is in RANGE") }, + { 'N', M_NEW, 0, 0, + N_("new messages") }, + { 'O', M_OLD, 0, 0, + N_("old messages") }, + { 'p', M_PERSONAL_RECIP, 0, 0, + N_("messages addressed to you") }, + { 'P', M_PERSONAL_FROM, 0, 0, + N_("messages from you") }, + { 'Q', M_REPLIED, 0, 0, + N_("messages which have been replied to") }, + { 'r', M_DATE_RECEIVED, 0, EAT_DATE, + N_("messages received in DATERANGE") }, + { 'R', M_READ, 0, 0, + N_("already read messages") }, + { 's', M_SUBJECT, 0, EAT_REGEXP, + N_("messages whose Subject header matches EXPR") }, + { 'S', M_SUPERSEDED, 0, 0, + N_("superseded messages") }, + { 't', M_TO, 0, EAT_REGEXP, + N_("messages whose To header matches EXPR") }, + { 'T', M_TAG, 0, 0, + N_("tagged messages") }, + { 'u', M_SUBSCRIBED_LIST, 0, 0, + N_("messages addressed to subscribed mailing lists") }, + { 'U', M_UNREAD, 0, 0, + N_("unread messages") }, + { 'v', M_COLLAPSED, 0, 0, + N_("messages in collapsed threads") }, + { 'V', M_CRYPT_VERIFIED, 0, 0, + N_("cryptographically verified messages") }, + { 'x', M_REFERENCE, 0, EAT_REGEXP, + N_("messages whose References header matches EXPR") }, + { 'X', M_MIMEATTACH, 0, EAT_RANGE, + N_("messages with RANGE attachments") }, + { 'y', M_XLABEL, 0, EAT_REGEXP, + N_("messages whose X-Label header matches EXPR") }, + { 'z', M_SIZE, 0, EAT_RANGE, + N_("messages whose size is in RANGE") }, + { '=', M_DUPLICATED, 0, 0, + N_("duplicated messages") }, + { '$', M_UNREFERENCED, 0, 0, + N_("unreferenced messages") }, { 0 } }; @@ -252,7 +300,7 @@ return match; } -int eat_regexp (pattern_t *pat, BUFFER *s, BUFFER *err) +static int eat_regexp (pattern_t *pat, BUFFER *s, BUFFER *err) { BUFFER buf; int r; @@ -303,7 +351,7 @@ return 0; } -int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) +static int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) { char *tmp; int do_exclusive = 0; @@ -867,13 +915,20 @@ if (entry->eat_arg) { + int eatrv = 0; if (!*ps.dptr) { snprintf (err->data, err->dsize, _("missing parameter")); mutt_pattern_free (&curlist); return NULL; } - if (entry->eat_arg (tmp, &ps, err) == -1) + switch (entry->eat_arg) + { + case EAT_REGEXP: eatrv = eat_regexp (tmp, &ps, err); break; + case EAT_DATE: eatrv = eat_date (tmp, &ps, err); break; + case EAT_RANGE: eatrv = eat_range (tmp, &ps, err); break; + } + if (eatrv == -1) { mutt_pattern_free (&curlist); return NULL; @@ -1433,3 +1488,134 @@ mutt_error _("Not found."); return (-1); } + +static void pattern_entry (char *s, size_t l, MUTTMENU * menu, int num) +{ + LIST **PatTable = (LIST **) menu->data; + + mutt_format_string (s, l, 0, COLS, 0, ' ', PatTable[num]->data, + mutt_strlen (PatTable[num]->data), 0); +} + +static char pattern_menu (LIST *pats) +{ + int patmax = 0; + LIST **PatTable = NULL; + MUTTMENU *menu; + int i, done = 0; + char helpstr[SHORT_STRING], buf[LONG_STRING]; + LIST *pat; + char rv = 0; + + for (i = 0, pat = pats; pat; pat = pat->next) + { + if (i == patmax) + { + patmax += 5; + safe_realloc (&PatTable, sizeof (LIST *) * patmax); + } + PatTable[i++] = pat; + } + + helpstr[0] = 0; + mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_GENERIC, OP_EXIT); + safe_strcat (helpstr, sizeof (helpstr), buf); + mutt_make_help (buf, sizeof (buf), _("Select "), MENU_GENERIC, + OP_GENERIC_SELECT_ENTRY); + safe_strcat (helpstr, sizeof (helpstr), buf); + mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP); + safe_strcat (helpstr, sizeof (helpstr), buf); + + menu = mutt_new_menu (); + menu->max = i; + menu->make_entry = pattern_entry; + menu->menu = MENU_GENERIC; + menu->help = helpstr; + menu->data = PatTable; + menu->title = _("Patterns"); + + mutt_clear_error (); + + while (!done) + { + switch (mutt_menuLoop (menu)) + { + case OP_GENERIC_SELECT_ENTRY: + rv = PatTable[menu->current]->data[1]; + done = 1; + break; + + case OP_EXIT: + rv = 0; + done = 1; + break; + } + } + + mutt_menuDestroy (&menu); + FREE (&PatTable); + + set_option (OPTNEEDREDRAW); + + return (rv); +} + +static LIST *list_patterns () +{ + LIST *first = NULL, *last = NULL, *cur = NULL; + int i; + + for (i = 0; Flags[i].tag; i++) + { + char buf[LONG_STRING]; + switch (Flags[i].eat_arg) + { + case EAT_REGEXP: + snprintf (buf, sizeof (buf), _("~%c EXPR %s"), + (char) Flags[i].tag, _(Flags[i].desc)); + break; + case EAT_RANGE: + snprintf (buf, sizeof (buf), _("~%c RANGE %s"), + (char) Flags[i].tag, _(Flags[i].desc)); + break; + case EAT_DATE: + snprintf (buf, sizeof (buf), _("~%c DATERANGE %s"), + (char) Flags[i].tag, _(Flags[i].desc)); + break; + default: + snprintf (buf, sizeof (buf), _("~%c %s"), + (char) Flags[i].tag, _(Flags[i].desc)); + } + cur = (LIST *) safe_calloc (1, sizeof (LIST)); + cur->data = safe_strdup (buf); + if (!first) + first = cur; + if (last) + last->next = cur; + last = cur; + } + if (cur) + cur->next = NULL; + return (first); +} + +int mutt_ask_pattern (char *buf, size_t buflen) +{ + char c; + LIST *l; + int rv = 0; + + if (!buf || buflen < 3) + return 0; + if ((l = list_patterns())) + { + if ((c = pattern_menu (l))) + { + sprintf (buf, "%c ", c); /* __SPRINTF_CHECKED__ */ + rv = 1; + } + mutt_free_list (&l); + } + return rv; +} + diff -r 77256e350c2e protos.h --- a/protos.h Tue Feb 21 21:52:49 2006 +++ b/protos.h Wed Mar 1 20:03:27 2006 @@ -171,6 +171,7 @@ int mutt_count_body_parts (HEADER *hdr, int flags); void mutt_check_rescore (CONTEXT *); void mutt_clear_error (void); +void mutt_comval (void); void mutt_create_alias (ENVELOPE *, ADDRESS *); void mutt_decode_attachment (BODY *, STATE *); void mutt_decode_base64 (STATE *s, long len, int istext, iconv_t cd); @@ -258,6 +259,7 @@ int mutt_addwch (wchar_t); int mutt_alias_complete (char *, size_t); int mutt_alloc_color (int fg, int bg); +int mutt_ask_pattern (char *, size_t); int mutt_any_key_to_continue (const char *); int mutt_buffy_check (int); int mutt_buffy_notify (void); @@ -279,6 +281,8 @@ int mutt_copy_body (FILE *, BODY **, BODY *); int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int); int mutt_display_message (HEADER *h); +int mutt_dump_command_values (BUFFER *, int); +int mutt_dump_hook (BUFFER *, unsigned long); int mutt_dump_variables (void); int mutt_edit_attachment(BODY *); int mutt_edit_message (CONTEXT *, HEADER *); diff -r 77256e350c2e rfc2047.c --- a/rfc2047.c Tue Feb 21 21:52:49 2006 +++ b/rfc2047.c Wed Mar 1 20:03:27 2006 @@ -85,6 +85,41 @@ iconv_close (cd); return n; +} + +int convert_nonmime_string (char **ps) +{ + const char *p, *q; + + for (p = AssumedCharset; p; p = q ? q + 1 : 0) + { + char *u = *ps; + char *s; + char *fromcode; + size_t m; + size_t ulen = mutt_strlen (*ps); + size_t slen; + + if (!u || !*u) + return 0; + + q = strchr (p, ':'); + if (! (q ? q - p : mutt_strlen (p))) + return 0; /* pass-through with no conv */ + fromcode = mutt_substrdup (p, q); + m = convert_string (u, ulen, fromcode, Charset, &s, &slen); + FREE (&fromcode); + if (m != (size_t)(-1)) + { + FREE (ps); + *ps = s; + return 0; + } + } + mutt_convert_string (ps, + (const char *)mutt_get_default_charset (AssumedCharset), + Charset, M_ICONV_HOOK_FROM); + return -1; } char *mutt_choose_charset (const char *fromcode, const char *charsets, @@ -733,6 +768,19 @@ if (!(p = find_encoded_word (s, &q))) { /* no encoded words */ + if (AssumedCharset && *AssumedCharset) + { + char *t; + size_t tlen; + + t = safe_strdup (s); + convert_nonmime_string (&t); + tlen = mutt_strlen (t); + strncpy (d, t, tlen); + d += tlen; + FREE (&t); + break; + } strncpy (d, s, dlen); d += dlen; break; @@ -770,7 +818,8 @@ { while (a) { - if (a->personal && strstr (a->personal, "=?") != NULL) + if (a->personal && ((strstr (a->personal, "=?") != NULL) || + (AssumedCharset && *AssumedCharset))) rfc2047_decode (&a->personal); #ifdef EXACT_ADDRESS if (a->val && strstr (a->val, "=?") != NULL) diff -r 77256e350c2e rfc2047.h --- a/rfc2047.h Tue Feb 21 21:52:49 2006 +++ b/rfc2047.h Wed Mar 1 20:03:27 2006 @@ -18,6 +18,7 @@ char *mutt_choose_charset (const char *fromcode, const char *charsets, char *u, size_t ulen, char **d, size_t *dlen); +int convert_nonmime_string (char **); void _rfc2047_encode_string (char **, int, int); void rfc2047_encode_adrlist (ADDRESS *, const char *); diff -r 77256e350c2e rfc2231.c --- a/rfc2231.c Tue Feb 21 21:52:49 2006 +++ b/rfc2231.c Wed Mar 1 20:03:27 2006 @@ -117,6 +117,8 @@ if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?")) rfc2047_decode (&p->value); + else if (AssumedCharset && *AssumedCharset) + convert_nonmime_string (&p->value); *last = p; last = &p->next; diff -r 77256e350c2e rfc822.c --- a/rfc822.c Tue Feb 21 21:52:49 2006 +++ b/rfc822.c Wed Mar 1 20:03:27 2006 @@ -60,28 +60,6 @@ "bad address spec" }; -void rfc822_dequote_comment (char *s) -{ - char *w = s; - - for (; *s; s++) - { - if (*s == '\\') - { - if (!*++s) - break; /* error? */ - *w++ = *s; - } - else if (*s != '\"') - { - if (w != s) - *w = *s; - w++; - } - } - *w = 0; -} - void rfc822_free_address (ADDRESS **p) { ADDRESS *t; @@ -119,6 +97,8 @@ } else if (*s == '\\') { + if (*commentlen < commentmax) + comment[(*commentlen)++] = *s; if (!*++s) break; } @@ -153,8 +133,8 @@ if (!*++s) break; - if (*tokenlen < tokenmax) - token[*tokenlen] = *s; + if (*tokenlen + 1 < tokenmax) + token[++(*tokenlen)] = *s; } (*tokenlen)++; s++; @@ -451,9 +431,7 @@ { if (cur->personal) FREE (&cur->personal); - /* if we get something like "Michael R. Elkins" remove the quotes */ - rfc822_dequote_comment (phrase); - cur->personal = safe_strdup (phrase); + cur->personal = safe_strdup (phrase); } if ((ps = parse_route_addr (s + 1, comment, &commentlen, sizeof (comment) - 1, cur)) == NULL) { @@ -531,11 +509,6 @@ *pc++ = '"'; for (; *value && tmplen > 1; value++) { - if (*value == '\\' || *value == '"') - { - *pc++ = '\\'; - tmplen--; - } *pc++ = *value; tmplen--; } @@ -552,7 +525,6 @@ { size_t len; char *pbuf = buf; - char *pc; if (!addr) return; @@ -582,40 +554,12 @@ if (addr->personal) { - if (strpbrk (addr->personal, RFC822Specials)) - { - if (!buflen) - goto done; - *pbuf++ = '"'; - buflen--; - for (pc = addr->personal; *pc && buflen > 0; pc++) - { - if (*pc == '"' || *pc == '\\') - { - if (!buflen) - goto done; - *pbuf++ = '\\'; - buflen--; - } - if (!buflen) - goto done; - *pbuf++ = *pc; - buflen--; - } - if (!buflen) - goto done; - *pbuf++ = '"'; - buflen--; - } - else - { - if (!buflen) - goto done; - strfcpy (pbuf, addr->personal, buflen); - len = mutt_strlen (pbuf); - pbuf += len; - buflen -= len; - } + if (!buflen) + goto done; + strfcpy (pbuf, addr->personal, buflen); + len = mutt_strlen (pbuf); + pbuf += len; + buflen -= len; if (!buflen) goto done; @@ -791,6 +735,41 @@ return tmp; } +/* dequote personal name */ +char *rfc822_dequote_personal (char **s) +{ + if (*s && **s) + { + size_t slen = mutt_strlen (*s); + char *r = safe_malloc (slen + 1); + char *p = *s, *q = r; + if (slen > 2 && **s == '"' && *(*s + slen - 1) == '"') + { + p++; + slen--; + } + for (; p < *s + slen; p++) + { + if (*p == '\\') + *q++ = *++p; + else + *q++ = *p; + } + *q = 0; + FREE (s); + *s = r; + } + return (*s); +} + +/* dequote personal names in adrlist */ +void rfc822_dequotepersonal_adrlist (ADDRESS *a) +{ + ADDRESS *cur = a; + for (; cur; cur = cur->next) + rfc822_dequote_personal (&cur->personal); +} + #ifdef TESTING int safe_free (void **p) { diff -r 77256e350c2e rfc822.h --- a/rfc822.h Tue Feb 21 21:52:49 2006 +++ b/rfc822.h Wed Mar 1 20:03:27 2006 @@ -52,6 +52,8 @@ void rfc822_write_address_single (char *, size_t, ADDRESS *, int); void rfc822_free_address (ADDRESS **addr); void rfc822_cat (char *, size_t, const char *, const char *); +char *rfc822_dequote_personal (char **); +void rfc822_dequotepersonal_adrlist (ADDRESS *); extern int RFC822Error; extern const char *RFC822Errors[]; diff -r 77256e350c2e sort.c --- a/sort.c Tue Feb 21 21:52:49 2006 +++ b/sort.c Wed Mar 1 20:03:27 2006 @@ -90,21 +90,27 @@ return (SORTCODE (rc)); } +/* needs freeing */ const char *mutt_get_name (ADDRESS *a) { ADDRESS *ali; + char *tmp = NULL; if (a) { if (option (OPTREVALIAS) && (ali = alias_reverse_lookup (a)) && ali->personal) - return ali->personal; + tmp = safe_strdup (ali->personal); else if (a->personal) - return a->personal; + tmp = safe_strdup (a->personal); else if (a->mailbox) - return (mutt_addr_for_display (a)); + tmp = safe_strdup (mutt_addr_for_display (a)); + if (tmp) + return (rfc822_dequote_personal (&tmp)); } /* don't return NULL to avoid segfault when printing/comparing */ - return (""); + tmp = safe_malloc (1); + *tmp = '\0'; + return (tmp); } int compare_to (const void *a, const void *b) @@ -117,6 +123,8 @@ fa = mutt_get_name ((*ppa)->env->to); fb = mutt_get_name ((*ppb)->env->to); result = mutt_strcasecmp (fa, fb); + FREE (&fa); + FREE (&fb); AUXSORT(result,a,b); return (SORTCODE (result)); } @@ -131,6 +139,8 @@ fa = mutt_get_name ((*ppa)->env->from); fb = mutt_get_name ((*ppb)->env->from); result = mutt_strcasecmp (fa, fb); + FREE (&fa); + FREE (&fb); AUXSORT(result,a,b); return (SORTCODE (result)); }