diff -ur mutt-1.5.9.orig/PATCHES mutt-1.5.9/PATCHES --- mutt-1.5.9.orig/PATCHES 2005-03-14 01:33:06.000000000 +0900 +++ mutt-1.5.9/PATCHES 2005-03-14 23:23:44.081510792 +0900 @@ -0,0 +1 @@ +patch-1.5.9.mutt-j.ja-beta1.1.mod diff -ur mutt-1.5.9.orig/charset.c mutt-1.5.9/charset.c --- mutt-1.5.9.orig/charset.c 2005-02-13 04:53:00.000000000 +0900 +++ mutt-1.5.9/charset.c 2005-03-14 23:23:44.088509728 +0900 @@ -227,14 +227,22 @@ /* finally, set $charset */ if (!(Charset = safe_strdup (buff2))) +#ifdef DEFAULT_JAPANESE + Charset = safe_strdup ("euc-jp"); +#else Charset = safe_strdup ("iso-8859-1"); +#endif } #else void mutt_set_langinfo_charset (void) { +#ifdef DEFAULT_JAPANESE + Charset = safe_strdup ("euc-jp"); +#else Charset = safe_strdup ("iso-8859-1"); +#endif } #endif @@ -282,6 +290,19 @@ 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)); + return fcharset; + } + return strcpy (fcharset, "us-ascii"); /* __STRCPY_CHECKED__ */ +} #ifndef HAVE_ICONV @@ -329,10 +351,13 @@ if ((flags & M_ICONV_HOOK_FROM) && (tmp = mutt_charset_hook (fromcode1))) mutt_canonical_charset (fromcode1, sizeof (fromcode1), tmp); - if ((cd = iconv_open (tocode1, fromcode1)) != (iconv_t) -1) + tocode2 = mutt_iconv_hook (tocode1); + tocode2 = (tocode2) ? tocode2 : tocode1; + fromcode2 = mutt_iconv_hook (fromcode1); + fromcode2 = (fromcode2) ? fromcode2 : fromcode1; + + if ((cd = iconv_open (tocode2, fromcode2)) != (iconv_t) -1) return cd; - if ((tocode2 = mutt_iconv_hook (tocode1)) && (fromcode2 = mutt_iconv_hook (fromcode1))) - return iconv_open (tocode2, fromcode2); return (iconv_t) -1; } @@ -424,6 +449,9 @@ if (!s || !*s) return 0; + if (option (OPTSANITIZEJACHARS) && !ascii_strncasecmp (from, "iso-2022-jp", 11)) + mutt_sanitize_ja_chars (s, mutt_strlen(s), 0); + if (to && from && (cd = mutt_iconv_open (to, from, flags)) != (iconv_t)-1) { int len; @@ -591,3 +619,188 @@ iconv_close (fc->cd); FREE (_fc); } + +/* + * mutt_sanitize_ja_chars() + * Adapted by TAKIZAWA Takashi + * + * - It replaces undefined KANJI characters to GETA mark. + * - It replaces character of 'JIS X 0201 kana' to '?'. + * - If $charset is EUC-JP, it replaces third character 'J' of + * escape sequence switching to 'JIS X 0201 latin' to 'B' indicating + * 'US-ASCII'. + * - If $charset is Shift_JIS, it replaces third character 'B' of + * escape sequence switching to 'US-ASCII' to 'J' indicating + * 'JIS X 0201 latin'. + */ + +#define ASCII 0 +#define JISX0201LATIN 1 +#define JISX0201KANA 2 +#define JISX0208 3 +#define OTHER_CS 4 + +void mutt_sanitize_ja_chars(char *s, size_t len, int keep_state) +{ + static int cs = ASCII; + static int kanji_cont = 0; + static int illegal_kanji = 0; + static int es = 0; + static char pes = '\0'; + static char ascii_3rd_char = 'B'; + static char jisx0201_3rd_char = 'J'; + + char *p = s; + char *p1 = NULL; + unsigned char c; + + if (!keep_state || *p == 0x1b) /* consideration about mbstate's buffer */ + { + if (!ascii_strcasecmp (Charset, "euc-jp")) + jisx0201_3rd_char = 'B'; + else if (!ascii_strcasecmp (Charset, "shift_jis")) + ascii_3rd_char = 'J'; + cs = ASCII; + kanji_cont = 0; + illegal_kanji = 0; + es = 0; + pes = '\0'; + } + + for (;p - s < len;p++) + { + if (es == 0) + { + if (*p == 0x1b) + es++; + else + { + switch (cs) + { + case ASCII: + case JISX0201LATIN: + break; + case JISX0201KANA: + *p = '?'; + break; + case JISX0208: + /* replace ku-ten code from 9 to 15 and 85 or more to "GETA MARK" */ + c = (unsigned char)*p; + if (! kanji_cont) + { + if ((size_t)(p - s + 1) == len) + return; /* the last character is a primary byte of KANJI */ + if (c <= 0x20 || (c >= 0x29 && c <= 0x2f) + || (c >= 0x75 && c <= 0xa0)) + illegal_kanji = 1; + kanji_cont = 1; + p1 = p; + } + else + { + if (c <= 0x20 || c >= 0x7f) + illegal_kanji = 1; + if (illegal_kanji && p1) + *p1 = 0x22, *p = 0x2e; + kanji_cont = 0; + illegal_kanji = 0; + } + break; + } + } + } + else if (es == 1) + { + if (*p == '$' || (*p >= '(' && *p <= '/' && *p != ',')) + { + es++; + pes = *p; + } + else + { + es = 0; + return; /* broken */ + } + } + else if (es == 2) + { + if (pes == '(') + { + switch (*p) + { + case 'B': + cs = ASCII, *p = ascii_3rd_char; + break; + case 'J': + cs = JISX0201LATIN, *p = jisx0201_3rd_char; + break; + case 'I': + /* ready to replace character to '?' */ + cs = JISX0201KANA, *p = ascii_3rd_char; + break; + default: + cs = OTHER_CS; + } + es = 0; + } + else if (pes == '$') + { + switch (*p) + { + case '@': /* JIS X 0208-1978 */ + case 'B': /* JIS X 0208-1983 */ + cs = JISX0208; + es = 0; + break; + case 'A': + cs = OTHER_CS; /* GB 2312 */ + es = 0; + break; + case '(': + case ')': + case '*': + case '+': + case '-': + case '.': + case '/': + es++; + break; + default: + es = 0; + return; /* broken */ + } + } + else + { + cs = OTHER_CS; + es = 0; + } + } + else /* es == 3 */ + { + cs = OTHER_CS; + es = 0; + } + } +} + +int mutt_copy_bytes_sanitize_ja (FILE *in, FILE *out, size_t size) +{ + char buf[2048]; + size_t chunk; + + mutt_sanitize_ja_chars (NULL, 0, 0); + while (size > 0) + { + chunk = (size > sizeof (buf)) ? sizeof (buf) : size; + if ((chunk = fread (buf, 1, chunk, in)) < 1) + break; + mutt_sanitize_ja_chars (buf, chunk, 1); + if (fwrite (buf, 1, chunk, out) != chunk) + return (-1); + size -= chunk; + } + + return 0; +} + diff -ur mutt-1.5.9.orig/charset.h mutt-1.5.9/charset.h --- mutt-1.5.9.orig/charset.h 2003-03-03 19:22:06.000000000 +0900 +++ mutt-1.5.9/charset.h 2005-03-14 23:22:11.363606056 +0900 @@ -36,6 +36,9 @@ int mutt_convert_string (char **, const char *, const char *, int); +void mutt_sanitize_ja_chars (char *, size_t, int); +int mutt_copy_bytes_sanitize_ja (FILE *, FILE *, size_t); + iconv_t mutt_iconv_open (const char *, const char *, int); size_t mutt_iconv (iconv_t, ICONV_CONST char **, size_t *, char **, size_t *, ICONV_CONST char **, const char *); @@ -47,6 +50,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 -ur mutt-1.5.9.orig/configure.in mutt-1.5.9/configure.in --- mutt-1.5.9.orig/configure.in 2005-03-14 01:36:01.000000000 +0900 +++ mutt-1.5.9/configure.in 2005-03-14 23:23:44.098508208 +0900 @@ -231,12 +231,21 @@ AC_DEFINE(HAVE_COLOR,1,[ Define if your curses library supports color. ]) MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS resize.o" + dnl --- Check name of S-Lang library + + AC_ARG_WITH(slanglib, + [ --with-slanglib=NAME Name of S-Lang library ], , + with_slanglib=yes) + if test x$with_slanglib = xyes; then + slanglib_name=slang + else + slanglib_name=$with_slanglib + fi dnl --- now that we've found it, check the link - AC_CHECK_LIB(slang, SLtt_get_terminfo, - [MUTTLIBS="$MUTTLIBS -lslang -lm"], + AC_CHECK_LIB($slanglib_name, SLtt_get_terminfo, + [MUTTLIBS="$MUTTLIBS -l$slanglib_name -lm"], [AC_MSG_ERROR(unable to compile. check config.log)], -lm) - ], [mutt_cv_curses=/usr @@ -777,6 +786,11 @@ AC_DEFINE(LOCALES_HACK,1,[ Define if the result of isprint() is unreliable. ]) fi]) +AC_ARG_ENABLE(default-japanese, AC_HELP_STRING([--enable-default-japanese], [Enable Japanese setting as default]), + [if test x$enableval = xyes; then + AC_DEFINE(DEFAULT_JAPANESE,1,[ Define to enable Japanese setting as default. ]) + fi]) + AC_ARG_WITH(exec-shell, AC_HELP_STRING([--with-exec-shell=SHELL], [Specify alternate shell (ONLY if /bin/sh is broken)]), [if test $withval != yes; then AC_DEFINE_UNQUOTED(EXECSHELL, "$withval", @@ -1049,21 +1049,55 @@ AC_ARG_WITH(wc-funcs, AC_HELP_STRING([--without-wc-funcs], [Do not use the system's wchar_t functions]), wc_funcs=$withval) -if test "$wc_funcs" != yes -a "$wc_funcs" != no; then +if test "$wc_funcs" != no; then AC_CACHE_CHECK([for wchar_t functions], mutt_cv_wc_funcs, mutt_cv_wc_funcs=no - AC_TRY_LINK([ + AC_TRY_RUN([ #define _XOPEN_SOURCE 1 +#include #include #include +#include #ifdef HAVE_WCTYPE_H #include #endif #ifdef HAVE_WCHAR_H #include -#endif], - [mbrtowc(0, 0, 0, 0); wctomb(0, 0); wcwidth(0); - iswprint(0); iswspace(0); towlower(0); towupper(0); iswalnum(0)], +#endif + +int ac_wc_test (const char *s, size_t n) +{ + wchar_t wc; int w; size_t l, k; mbstate_t mbstate; + memset(&mbstate, 0, sizeof (mbstate)); + for (l = 0, w = 0; l < n && (k = mbrtowc (&wc, s, n - l, &mbstate)); s += k, l += k) + { + if (k == (size_t)(-1) || k == (size_t)(-2) || !iswprint (wc)) + return (0); + w += wcwidth (wc); + } + return (w); +} + +int main () +{ +changequote(, )dnl + const char *kstring = "\264\301\273\372"; /* KANJI in euc-jp */ + int kwidth = 4; /* wcwidth(KAN)==2, wcwidth(JI)==2 */ + const char *locale[] = {"ja", "ja_JP", "ja_JP.EUC-JP", "ja_JP.ujis", "ja_JP.eucJP", NULL}; + int i; + /* just to confirm you have these functions */ + wctomb(0, 0); iswspace(0); towlower(0); towupper(0); iswalnum(0); + for (i = 0; locale[i]; i++) + { + setlocale (LC_ALL, locale[i]); + setlocale (LC_CTYPE, locale[i]); +changequote([, ])dnl + if (ac_wc_test (kstring, sizeof kstring) == kwidth) + exit (0); + } + exit (1); +} +], mutt_cv_wc_funcs=yes)) wc_funcs=$mutt_cv_wc_funcs fi diff -ur mutt-1.5.9.orig/curs_lib.c mutt-1.5.9/curs_lib.c --- mutt-1.5.9.orig/curs_lib.c 2005-02-04 03:47:52.000000000 +0900 +++ mutt-1.5.9/curs_lib.c 2005-03-14 23:21:40.093359856 +0900 @@ -40,6 +40,8 @@ #include #endif +extern const char *TreeUTF8Chars[]; + /* not possible to unget more than one char under some curses libs, and it * is impossible to unget function keys in SLang, so roll our own input * buffering routines. @@ -608,7 +610,14 @@ wc = replacement_char (); } if (arboreal && wc < M_TREE_MAX) - w = 1; /* hack */ + { + if (option (OPTTREECHARS)) + w = mutt_strwidth ((char *)TreeChars[wc]); + else if (Charset_is_utf8) + w = mutt_strwidth ((char *)TreeUTF8Chars[wc]); + else + w = 1; + } else { if (!IsWPrint (wc)) @@ -761,3 +770,46 @@ } return w; } + +/* + * mutt_strwidth_arboreal is mutt_strwidth considering the width of characters + * when displaying thread and attachment trees. + */ + +int mutt_strwidth_arboreal (const char *s) +{ + wchar_t wc; + int w; + size_t k, n; + mbstate_t mbstate; + + if (!s) return 0; + + n = mutt_strlen (s); + + memset (&mbstate, 0, sizeof (mbstate)); + for (w=0; n && (k = mbrtowc (&wc, s, n, &mbstate)); s += k, n -= k) + { + if (k == (size_t)(-1) || k == (size_t)(-2)) + { + k = (k == (size_t)(-1)) ? 1 : n; + wc = replacement_char (); + } + if (wc < M_TREE_MAX) + { + if (option (OPTTREECHARS)) + w += mutt_strwidth ((char *)TreeChars[wc]); + else if (Charset_is_utf8) + w += mutt_strwidth ((char *)TreeUTF8Chars[wc]); + else + w++; + } + else if (!IsWPrint (wc)) + { + w++; + } + else + w += wcwidth (wc); + } + return w; +} diff -ur mutt-1.5.9.orig/globals.h mutt-1.5.9/globals.h --- mutt-1.5.9.orig/globals.h 2005-02-13 05:01:02.000000000 +0900 +++ mutt-1.5.9/globals.h 2005-03-14 23:21:40.099358944 +0900 @@ -32,8 +32,10 @@ WHERE char *AliasFile; WHERE char *AliasFmt; +WHERE char *AssumedCharset; WHERE char *AttachSep; WHERE char *Attribution; +WHERE char *AttachCharset; WHERE char *AttachFormat; WHERE char *Charset; WHERE char *ComposeFormat; @@ -70,6 +72,7 @@ WHERE char *HeaderCachePageSize; #endif WHERE char *MhFlagged; +WHERE char *MhPath; WHERE char *MhReplied; WHERE char *MhUnseen; WHERE char *MsgFmt; @@ -107,6 +110,7 @@ WHERE char *Shell; WHERE char *Signature; WHERE char *SimpleSearch; +WHERE char *Spoiler; WHERE char *Spoolfile; WHERE char *SpamSep; #if defined(USE_SSL) || defined(USE_NSS) || defined(USE_GNUTLS) @@ -126,6 +130,20 @@ WHERE char *Status; WHERE char *Tempdir; WHERE char *Tochars; +WHERE char *TreeChars[M_TREE_MAX]; +WHERE char *TreeLLCorner; +WHERE char *TreeULCorner; +WHERE char *TreeLTee; +WHERE char *TreeHLine; +WHERE char *TreeVLine; +WHERE char *TreeSpace; +WHERE char *TreeRArrow; +WHERE char *TreeStar; +WHERE char *TreeHidden; +WHERE char *TreeEquals; +WHERE char *TreeTTee; +WHERE char *TreeBTee; +WHERE char *TreeMissing; WHERE char *Username; WHERE char *Visual; diff -ur mutt-1.5.9.orig/handler.c mutt-1.5.9/handler.c --- mutt-1.5.9.orig/handler.c 2005-02-04 03:47:52.000000000 +0900 +++ mutt-1.5.9/handler.c 2005-03-14 23:22:11.375604232 +0900 @@ -101,6 +101,9 @@ return; } + if (option (OPTSANITIZEJACHARS) && strchr (bufi, 0x1b)) + mutt_sanitize_ja_chars (bufi, *l, 1); + ib = bufi, ibl = *l; for (;;) { @@ -1512,6 +1515,7 @@ int piped = FALSE; pid_t thepid; int rc = 0; + char *charset; snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); rfc1524_mailcap_lookup (a, type, entry, M_AUTOVIEW); @@ -1542,6 +1546,11 @@ return; } + charset = mutt_get_parameter ("charset", a->parameter); + if (charset && option (OPTSANITIZEJACHARS) && !ascii_strncasecmp +(charset,"iso-2022-jp", 11)) + mutt_copy_bytes_sanitize_ja (s->fpin, fpin, a->length); + else mutt_copy_bytes (s->fpin, fpin, a->length); if(!piped) @@ -1728,9 +1737,13 @@ 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); } + else if (istext && b->charset) + cd = mutt_iconv_open (Charset, b->charset, M_ICONV_HOOK_FROM); fseek (s->fpin, b->offset, 0); switch (b->encoding) diff -ur mutt-1.5.9.orig/hdrline.c mutt-1.5.9/hdrline.c --- mutt-1.5.9.orig/hdrline.c 2005-02-13 03:53:35.000000000 +0900 +++ mutt-1.5.9/hdrline.c 2005-03-14 23:21:40.122355448 +0900 @@ -250,6 +250,7 @@ #define THREAD_NEW (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 1) #define THREAD_OLD (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 2) size_t len; + char *subj; hdr = hfi->hdr; ctx = hfi->ctx; @@ -543,11 +544,12 @@ case 's': + subj = option (OPTDELETEPREFIX) ? hdr->env->real_subj : hdr->env->subject; if (flags & M_FORMAT_TREE && !hdr->collapsed) { if (flags & M_FORMAT_FORCESUBJ) { - mutt_format_s (dest, destlen, "", NONULL (hdr->env->subject)); + mutt_format_s (dest, destlen, "", NONULL (subj)); snprintf (buf2, sizeof (buf2), "%s%s", hdr->tree, dest); mutt_format_s_tree (dest, destlen, prefix, buf2); } @@ -555,7 +557,7 @@ mutt_format_s_tree (dest, destlen, prefix, hdr->tree); } else - mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->subject)); + mutt_format_s (dest, destlen, prefix, NONULL (subj)); break; case 'S': diff -ur mutt-1.5.9.orig/hook.c mutt-1.5.9/hook.c --- mutt-1.5.9.orig/hook.c 2005-02-04 03:47:52.000000000 +0900 +++ mutt-1.5.9/hook.c 2005-03-14 23:21:40.129354384 +0900 @@ -92,7 +92,7 @@ memset (&pattern, 0, sizeof (pattern)); pattern.data = safe_strdup (path); } - else if (DefaultHook && !(data & (M_CHARSETHOOK | M_ACCOUNTHOOK)) + else if (DefaultHook && !(data & (M_CHARSETHOOK|M_ICONVHOOK|M_ACCOUNTHOOK)) && (!WithCrypto || !(data & M_CRYPTHOOK)) ) { @@ -161,7 +161,7 @@ { rx = safe_malloc (sizeof (regex_t)); #ifdef M_CRYPTHOOK - if ((rc = REGCOMP (rx, NONULL(pattern.data), ((data & (M_CRYPTHOOK|M_CHARSETHOOK)) ? REG_ICASE : 0))) != 0) + if ((rc = REGCOMP (rx, NONULL(pattern.data), ((data & (M_CRYPTHOOK|M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0))) != 0) #else if ((rc = REGCOMP (rx, NONULL(pattern.data), (data & (M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0)) != 0) #endif /* M_CRYPTHOOK */ diff -ur mutt-1.5.9.orig/init.c mutt-1.5.9/init.c --- mutt-1.5.9.orig/init.c 2005-02-13 04:06:16.000000000 +0900 +++ mutt-1.5.9/init.c 2005-03-14 23:21:40.143352256 +0900 @@ -24,6 +24,7 @@ #include "mapping.h" #include "mutt_curses.h" #include "mutt_regex.h" +#include "mutt_menu.h" #include "history.h" #include "keymap.h" #include "mbyte.h" @@ -1348,6 +1349,8 @@ *((char **) MuttVars[idx].data) = safe_strdup (tmp->data); if (mutt_strcmp (MuttVars[idx].option, "charset") == 0) mutt_set_charset (Charset); + if (mutt_strncmp (MuttVars[idx].option, "tree_", 5) == 0) + mutt_init_treechars (); } else { @@ -2370,6 +2373,11 @@ FREE (&AliasFile); AliasFile = safe_strdup (NONULL(Muttrc)); + strfcpy (buffer, NONULL(MhPath), sizeof (buffer)); + FREE (&MhPath); + mutt_expand_path (buffer, sizeof (buffer)); + MhPath = safe_strdup (buffer); + /* Process the global rc file if it exists and the user hasn't explicity requested not to via "-n". */ if (!skip_sys_rc) @@ -2421,6 +2429,8 @@ mutt_exit(1); } + mutt_init_treechars (); + #if 0 set_option (OPTWEED); /* turn weeding on by default */ #endif diff -ur mutt-1.5.9.orig/init.h mutt-1.5.9/init.h --- mutt-1.5.9.orig/init.h 2005-03-02 00:56:02.000000000 +0900 +++ mutt-1.5.9/init.h 2005-03-14 23:23:44.125504104 +0900 @@ -185,6 +185,44 @@ ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before ** editing the body of an outgoing message. */ +#ifdef DEFAULT_JAPANESE + { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL "iso-2022-jp:euc-jp:shift_jis:utf-8"}, +#else + { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL 0}, +#endif + /* + ** .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:utf-8" + ** .pp + ** However, only the first content is valid for the message body. + */ +#ifdef DEFAULT_JAPANESE + { "attach_charset", DT_STR, R_NONE, UL &AttachCharset, UL "iso-2022-jp:euc-jp:shift_jis:utf-8" }, +#else + { "attach_charset", DT_STR, R_NONE, UL &AttachCharset, UL 0 }, +#endif + /* + ** .pp + ** This variable is a colon-separated list of character encoding + ** schemes for text file attachments. + ** If unset, $$charset value will be used instead. + ** For example, the following configuration would work for Japanese + ** text handling: + ** .pp + ** set attach_charset="iso-2022-jp:euc-jp:shift_jis:utf-8" + ** .pp + ** Note: "iso-2022-*" must be put at the head of the value as shown above + ** if included. + */ { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " }, /* ** .pp @@ -387,6 +425,17 @@ ** ``$$crypt_replyencrypt'', ** ``$$crypt_autosign'', ``$$crypt_replysign'' and ``$$smime_is_default''. */ + { "create_rfc2047_parameters", DT_BOOL, R_NONE, OPTCREATERFC2047PARAMS, 0 }, + /* + ** .pp + ** When this variable is set, Mutt will add the following RFC-2047-encoded + ** MIME parameter to Content-Type header field as filename for attachment: + ** name="=?iso-2022-jp?B?GyRCO244MxsoQi50eHQ=?=" + ** .pp + ** Note: this use of RFC 2047's encoding is explicitly prohibited + ** by the standard. You may set this variable only if a mailer + ** of recipients can not parse RFC 2231 parameters. + */ { "date_format", DT_STR, R_BOTH, UL &DateFmt, UL "!%a, %b %d, %Y at %I:%M:%S%p %Z" }, /* ** .pp @@ -437,6 +486,19 @@ ** If this option is \fIset\fP, mutt's received-attachments menu will not show the subparts of ** individual messages in a multipart/digest. To see these subparts, press 'v' on that menu. */ + { "delete_prefix", DT_BOOL, R_NONE, OPTDELETEPREFIX, 0 }, + /* + ** .pp + ** If set, prefix in Subject: field generated by some mailing lists + ** (something like "Subject: [foo-ML:0012] real-subject") can be deleted + ** when displaying in index-mode and editing in message reply. + ** Deletion pattern can be configured by $$delete_regexp variable. + */ + { "delete_regexp", DT_RX, R_NONE, UL &DeleteRegexp, UL "^(\\[[A-Za-z0-9_.: \\-]*\\][ ]*)" }, + /* + ** .pp + ** A regular expression used in $$delete_prefix function. + */ { "display_filter", DT_PATH, R_PAGER, UL &DisplayFilter, UL "" }, /* ** .pp @@ -487,7 +549,11 @@ ** that it thinks they are duplicates of each other with an equals sign ** in the thread diagram. */ +#ifdef DEFAULT_JAPANESE + { "edit_headers", DT_BOOL, R_NONE, OPTEDITHDRS, 1 }, +#else { "edit_headers", DT_BOOL, R_NONE, OPTEDITHDRS, 0 }, +#endif /* ** .pp ** This option allows you to edit the header of your outgoing messages @@ -550,6 +616,9 @@ ** signed. ** (PGP only) */ + { "file_charset", DT_SYN, R_NONE, UL "attach_charset", 0 }, + /* + */ { "folder", DT_PATH, R_NONE, UL &Maildir, UL "~/Mail" }, /* ** .pp @@ -763,6 +832,17 @@ ** addresses. This overrides the compile time definition obtained from ** /etc/resolv.conf. */ +#ifdef DEFAULT_JAPANESE + { "ignore_linear_white_space", DT_BOOL, R_NONE, OPTIGNORELWS, 1 }, +#else + { "ignore_linear_white_space", DT_BOOL, R_NONE, OPTIGNORELWS, 0 }, +#endif + /* + ** .pp + ** This option replaces linear-white-space between encoded-word + ** and *text to a single space to prevent the display of MIME-encoded + ** ``Subject'' field from being devided into multiple lines. + */ { "ignore_list_reply_to", DT_BOOL, R_NONE, OPTIGNORELISTREPLYTO, 0 }, /* ** .pp @@ -1145,6 +1225,17 @@ ** .pp ** The name of the MH sequence used for unseen messages. */ + { "mh_path", DT_PATH, R_NONE, UL &MhPath, 0 }, + /* + ** .pp + ** If set, folder detection routine considers any subdirectory + ** under "mh_path" directory as an MH folder even if no other MH folder marker + ** (like "cur" subdirectory for MAILDIR folder, or .mh_sequences for + ** MH folder) is found in this directory AND no subdirectory exists + ** beneath this directory. Useful to decrease "xxx is not a mailbox." + ** error for those who are using some other semi-MH-compatible mailer + ** or dealing with MH folder by one's own shell script. + */ { "mime_forward", DT_QUAD, R_NONE, OPT_MIMEFWD, M_NO }, /* ** .pp @@ -1219,6 +1310,18 @@ { "msg_format", DT_SYN, R_NONE, UL "message_format", 0 }, /* */ + { "msgid", DT_BOOL, R_NONE, OPTMSGID, 1 }, + /* + ** .pp + ** Mutt will generate Message-ID: field by itself when + ** set(default). Unset to let MTA generate Message-ID: field. + */ + { "msgid_use_from", DT_BOOL, R_NONE, OPTMSGIDUSEFROM, 0 }, + /* + ** .pp + ** Use $$from value instead of $$hostname for Message-ID: generation. + ** Uniqueness of Message-ID: increases (especially for dialup-users). + */ { "narrow_tree", DT_BOOL, R_TREE|R_INDEX, OPTNARROWTREE, 0 }, /* ** .pp @@ -1276,6 +1379,31 @@ ** when you are at the end of a message and invoke the \fInext-page\fP ** function. */ + { "pager_hdrs_only", DT_BOOL, R_NONE, OPTPAGERHDRSONLY, 0 }, + /* + ** .pp + ** Determines whether to display message body immediately. + ** When set, only headers are displayed first, and message body is + ** shown after page scroll or line scroll are done. + */ + { "pager_spoil", DT_BOOL, R_NONE, OPTPAGERSPOIL, 0 }, + /* + ** .pp + ** Determines the style of $$pager_hdrs_only. + ** When set, message body characters are substituted by the characters + ** by $$pager_spoiler. Empty lines are shown when not set. + ** .pp + ** Note: When not set, line count of message body is calculated according + ** to the lines of the original message. File atattchments or displaying + ** in a mismatch between the empty-line count and the line count of the + ** message actually displayed. + */ + { "pager_spoiler", DT_STR, R_NONE, UL &Spoiler, UL "*" }, + /* + ** .pp + ** Specify substituting character for $$pager_hdrs_only and + ** $$pager_spoil. (valid only if both are set) + */ { "pgp_autosign", DT_SYN, R_NONE, UL "crypt_autosign", 0 }, { "crypt_autosign", DT_BOOL, R_NONE, OPTCRYPTAUTOSIGN, 0 }, /* @@ -1301,6 +1429,21 @@ ** settings can be overridden by use of the \fIsmime-menu\fP. ** (Crypto only) */ +#ifdef DEFAULT_JAPANESE + { "pgp_charsethack", DT_BOOL, R_NONE, OPTPGPCHARSETHACK, 1}, +#else + { "pgp_charsethack", DT_BOOL, R_NONE, OPTPGPCHARSETHACK, 0}, +#endif + /* + ** .pp + ** If \fIset\fP, Mutt will assume a non-MIME PGP armored message to be in + ** the charset specified in \fICharset:\fP armor header (by GnuPG) or in + ** \fIContent-Type\fP message header (by some MUAs). You should not set + ** this variable, because such an armor shouldn't have charset information. + ** By default, Mutt assumes such messages to be in UTF-8 (see RFC2440). + ** You will ignore the RFC if you set this variable! + ** (PGP only) + */ { "pgp_ignore_subkeys", DT_BOOL, R_NONE, OPTPGPIGNORESUB, 1}, /* ** .pp @@ -2257,7 +2400,11 @@ ** possibly including eventual real names. When it is unset, mutt will ** override any such real names with the setting of the $realname variable. */ +#ifdef DEFAULT_JAPANESE + { "rfc2047_parameters", DT_BOOL, R_NONE, OPTRFC2047PARAMS, 1 }, +#else { "rfc2047_parameters", DT_BOOL, R_NONE, OPTRFC2047PARAMS, 0 }, +#endif /* ** .pp ** When this variable is set, Mutt will decode RFC-2047-encoded MIME @@ -2275,6 +2422,32 @@ ** that mutt \fIgenerates\fP this kind of encoding. Instead, mutt will ** unconditionally use the encoding specified in RFC 2231. */ +#ifdef DEFAULT_JAPANESE + { "sanitize_ja_chars", DT_BOOL, R_NONE, OPTSANITIZEJACHARS, 1 }, +#else + { "sanitize_ja_chars", DT_BOOL, R_NONE, OPTSANITIZEJACHARS, 0 }, +#endif + /* + ** .pp + ** When set, Japanese "platform dependent characters" (illegal + ** characters for iso-2022-jp charset; mainly used by MS-Windows + ** mailers) are substituted to special character, GETA mark ('ESC $$ B " . + ** ESC ( B' in iso-2022-jp), and JIS X 0201 kana characters + ** (only for "ESC ) I" cases) are also substituted to "?" to + ** prevent garbage characters. JIS X 0201 kana characters are + ** not substituted if they appear in 8bit form. + ** .pp + ** This fixes another Japanese encoding issue. In case $$charset + ** is set to "EUC-JP", which does not contain JIS X 0201 roman + ** character set, the JIS X 0201 roman part of received messages + ** encoded in iso-2022-jp can not be converted to EUC-JP. + ** On the other hand, the ASCII part can not be converted to + ** Shift_JIS, which does not contain ASCII character set. Thus, + ** the converted characters are garbled in these cases. When this + ** option is set, the JIS X 0201 roman escape sequence and the + ** ASCII escape sequence are replaced appropriately to prevent + ** the output from being garbled. + */ { "save_address", DT_BOOL, R_NONE, OPTSAVEADDRESS, 0 }, /* ** .pp @@ -2335,7 +2508,11 @@ ** mutt scores are always greater than or equal to zero, the default setting ** of this variable will never mark a message read. */ +#ifdef DEFAULT_JAPANESE + { "send_charset", DT_STR, R_NONE, UL &SendCharset, UL "us-ascii:iso-2022-jp:utf-8" }, +#else { "send_charset", DT_STR, R_NONE, UL &SendCharset, UL "us-ascii:iso-8859-1:utf-8" }, +#endif /* ** .pp ** A list of character sets for outgoing messages. Mutt will use the @@ -2656,7 +2833,11 @@ ** When set, mutt uses the date received rather than the date sent ** to thread messages by subject. */ +#ifdef DEFAULT_JAPANESE + { "thorough_search", DT_BOOL, R_NONE, OPTTHOROUGHSRC, 1 }, +#else { "thorough_search", DT_BOOL, R_NONE, OPTTHOROUGHSRC, 0 }, +#endif /* ** .pp ** Affects the \fI~b\fP and \fI~h\fP search operations described in @@ -2700,6 +2881,86 @@ ** by \fIyou\fP. The sixth character is used to indicate when a mail ** was sent to a mailing-list you subscribe to (default: L). */ + { "tree_chars", DT_BOOL, R_BOTH, OPTTREECHARS, 0 }, + /* + ** .pp + ** Many terminals not compatible with vt-100 can't display ACS-characters. + ** This option can set any character for displaying tree structure in + ** index-thread or file-attatchments. + ** For example, Japanese users can use JIS X 0208 ruled line characters + ** for this purpose. The characters actually used are set by + ** $$tree_llcorner, $$tree_ulcorner, $$tree_ltee, $$tree_hline, + ** $$tree_vline, $$tree_ttee, $$tree_btee, $$tree_space, $$tree_rarrow, + ** $$tree_star, $$tree_hidden, $$tree_equals and $$tree_missing variables. + ** These values must be written in the same encoding as the $$charset + ** value. When $$tree_chars is not set (default), the characters + ** with $$ascii_chars are used. + */ + { "tree_llcorner", DT_STR, R_BOTH, UL &TreeLLCorner, UL "`" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_ulcorner", DT_STR, R_BOTH, UL &TreeULCorner, UL "," }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_ltee", DT_STR, R_BOTH, UL &TreeLTee, UL "|" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_hline", DT_STR, R_BOTH, UL &TreeHLine, UL "-" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_vline", DT_STR, R_BOTH, UL &TreeVLine, UL "|" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_ttee", DT_STR, R_BOTH, UL &TreeTTee, UL "-" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_btee", DT_STR, R_BOTH, UL &TreeBTee, UL "-" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_space", DT_STR, R_BOTH, UL &TreeSpace, UL " " }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_rarrow", DT_STR, R_BOTH, UL &TreeRArrow, UL ">" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_star", DT_STR, R_BOTH, UL &TreeStar, UL "*" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_hidden", DT_STR, R_BOTH, UL &TreeHidden, UL "&" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_equals", DT_STR, R_BOTH, UL &TreeEquals, UL "=" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ + { "tree_missing", DT_STR, R_BOTH, UL &TreeMissing, UL "?" }, + /* + ** .pp + ** See ``$$tree_chars''. + */ #ifdef USE_SOCKET { "tunnel", DT_STR, R_NONE, UL &Tunnel, UL 0 }, /* @@ -2757,6 +3018,19 @@ ** Normally, the default should work. */ #endif /* HAVE_GETADDRINFO */ +#ifndef HAVE_WC_FUNCS +#ifdef DEFAULT_JAPANESE + { "use_jisx0208", DT_BOOL, R_NONE, OPTUSEJISX0208, 1}, +#else + { "use_jisx0208", DT_BOOL, R_NONE, OPTUSEJISX0208, 0}, +#endif + /* + ** .pp + ** When \fIset\fP, Mutt will decide that Symbols, Greek and Cyrillic + ** in JIS X 0208 have a column width of 2 in UTF-8 locale. + */ +#endif + { "user_agent", DT_BOOL, R_NONE, OPTXMAILER, 1}, /* ** .pp diff -ur mutt-1.5.9.orig/mbyte.c mutt-1.5.9/mbyte.c --- mutt-1.5.9.orig/mbyte.c 2005-02-13 04:55:48.000000000 +0900 +++ mutt-1.5.9/mbyte.c 2005-03-14 23:22:48.201005920 +0900 @@ -71,8 +71,8 @@ || !ascii_strcasecmp(buffer, "cp932") || !ascii_strcasecmp(buffer, "eucJP-ms")) { charset_is_ja = 1; - charset_to_utf8 = iconv_open ("UTF-8", charset); - charset_from_utf8 = iconv_open (charset, "UTF-8"); + charset_to_utf8 = mutt_iconv_open ("UTF-8", charset, 0); + charset_from_utf8 = mutt_iconv_open (charset, "UTF-8", 0); } #endif @@ -373,6 +373,12 @@ return k; } } + else if (option (OPTUSEJISX0208)) + { + int k = wcwidth_ja (wc); + if (k != -1) + return k; + } return wcwidth_ucs (wc); } diff -ur mutt-1.5.9.orig/menu.c mutt-1.5.9/menu.c --- mutt-1.5.9.orig/menu.c 2005-03-01 00:13:57.000000000 +0900 +++ mutt-1.5.9/menu.c 2005-03-14 23:21:40.190345112 +0900 @@ -36,6 +36,59 @@ extern size_t UngetCount; +static const char TreeAsciiChars[] = +{ + 0, /* not used */ + '`', /* M_TREE_LLCORNER */ + ',', /* M_TREE_ULCORNER */ + '|', /* M_TREE_LTEE */ + '-', /* M_TREE_HLINE */ + '|', /* M_TREE_VLINE */ + ' ', /* M_TREE_SPACE */ + '>', /* M_TREE_RARROW */ + '*', /* M_TREE_STAR fake thread indicator */ + '&', /* M_TREE_HIDDEN */ + '=', /* M_TREE_EQUALS */ + '-', /* M_TREE_TTEE */ + '-', /* M_TREE_BTEE */ + '?' /* M_TREE_MISSING */ +}; + +const char *TreeUTF8Chars[] = +{ + "", /* not used */ + "\342\224\224", /* WACS_LLCORNER */ + "\342\224\214", /* WACS_ULCORNER */ + "\342\224\234", /* WACS_LTEE */ + "\342\224\200", /* WACS_HLINE */ + "\342\224\202", /* WACS_VLINE */ + " ", + ">", + "*", + "&", + "=", + "\342\224\254", /* WACS_TTEE */ + "\342\224\264", /* WACS_BTEE */ + "?" +}; + +void mutt_init_treechars () +{ + TreeChars[M_TREE_LLCORNER] = TreeLLCorner; + TreeChars[M_TREE_ULCORNER] = TreeULCorner; + TreeChars[M_TREE_LTEE] = TreeLTee; + TreeChars[M_TREE_HLINE] = TreeHLine; + TreeChars[M_TREE_VLINE] = TreeVLine; + TreeChars[M_TREE_SPACE] = TreeSpace; + TreeChars[M_TREE_RARROW] = TreeRArrow; + TreeChars[M_TREE_STAR] = TreeStar; + TreeChars[M_TREE_HIDDEN] = TreeHidden; + TreeChars[M_TREE_EQUALS] = TreeEquals; + TreeChars[M_TREE_TTEE] = TreeTTee; + TreeChars[M_TREE_BTEE] = TreeBTee; + TreeChars[M_TREE_MISSING] = TreeMissing; +} + static void print_enriched_string (int attr, unsigned char *s, int do_color) { wchar_t wc; @@ -50,83 +103,52 @@ { if (do_color) SETCOLOR (MT_COLOR_TREE); + if (option (OPTTREECHARS)) + while (*s && *s < M_TREE_MAX) + { + addstr (TreeChars[(int)*s]); + s++, n--; + } + else if (option (OPTASCIICHARS)) + while (*s && *s < M_TREE_MAX) + { + addch (TreeAsciiChars[(int)*s]); + s++, n--; + } + else if (Charset_is_utf8) + while (*s && *s < M_TREE_MAX) + { + addstr ((char *)TreeUTF8Chars[(int)*s]); + s++, n--; + } + else while (*s && *s < M_TREE_MAX) { switch (*s) { case M_TREE_LLCORNER: - if (option (OPTASCIICHARS)) - addch ('`'); - else if (Charset_is_utf8) - addstr ("\342\224\224"); /* WACS_LLCORNER */ - else addch (ACS_LLCORNER); break; case M_TREE_ULCORNER: - if (option (OPTASCIICHARS)) - addch (','); - else if (Charset_is_utf8) - addstr ("\342\224\214"); /* WACS_ULCORNER */ - else addch (ACS_ULCORNER); break; case M_TREE_LTEE: - if (option (OPTASCIICHARS)) - addch ('|'); - else if (Charset_is_utf8) - addstr ("\342\224\234"); /* WACS_LTEE */ - else addch (ACS_LTEE); break; case M_TREE_HLINE: - if (option (OPTASCIICHARS)) - addch ('-'); - else if (Charset_is_utf8) - addstr ("\342\224\200"); /* WACS_HLINE */ - else addch (ACS_HLINE); break; case M_TREE_VLINE: - if (option (OPTASCIICHARS)) - addch ('|'); - else if (Charset_is_utf8) - addstr ("\342\224\202"); /* WACS_VLINE */ - else addch (ACS_VLINE); break; case M_TREE_TTEE: - if (option (OPTASCIICHARS)) - addch ('-'); - else if (Charset_is_utf8) - addstr ("\342\224\254"); /* WACS_TTEE */ - else addch (ACS_TTEE); break; case M_TREE_BTEE: - if (option (OPTASCIICHARS)) - addch ('-'); - else if (Charset_is_utf8) - addstr ("\342\224\264"); /* WACS_BTEE */ - else addch (ACS_BTEE); break; - case M_TREE_SPACE: - addch (' '); - break; - case M_TREE_RARROW: - addch ('>'); - break; - case M_TREE_STAR: - addch ('*'); /* fake thread indicator */ - break; - case M_TREE_HIDDEN: - addch ('&'); - break; - case M_TREE_EQUALS: - addch ('='); - break; - case M_TREE_MISSING: - addch ('?'); + default: + addch (TreeAsciiChars[(int)*s]); break; } s++, n--; @@ -136,7 +158,7 @@ else if ((k = mbrtowc (&wc, (char *)s, n, &mbstate)) > 0) { addnstr ((char *)s, k); - s += k, n-= k; + s += k, n -= k; } else break; diff -ur mutt-1.5.9.orig/mutt.h mutt-1.5.9/mutt.h --- mutt-1.5.9.orig/mutt.h 2005-03-01 00:13:57.000000000 +0900 +++ mutt-1.5.9/mutt.h 2005-03-14 23:22:48.212004248 +0900 @@ -338,6 +338,8 @@ OPTCOLLAPSEUNREAD, OPTCONFIRMAPPEND, OPTCONFIRMCREATE, + OPTCREATERFC2047PARAMS, + OPTDELETEPREFIX, OPTDELETEUNTAG, OPTDIGESTCOLLAPSE, OPTDUPTHREADS, @@ -360,6 +362,7 @@ OPTHIDETHREADSUBJECT, OPTHIDETOPLIMITED, OPTHIDETOPMISSING, + OPTIGNORELWS, OPTIGNORELISTREPLYTO, #ifdef USE_IMAP OPTIMAPLSUB, @@ -393,8 +396,12 @@ OPTMETOO, OPTMHPURGE, OPTMIMEFORWDECODE, + OPTMSGID, + OPTMSGIDUSEFROM, OPTNARROWTREE, OPTPAGERSTOP, + OPTPAGERHDRSONLY, /* used to hide a body */ + OPTPAGERSPOIL, /* used to replace characters of a body */ OPTPIPEDECODE, OPTPIPESPLIT, #ifdef USE_POP @@ -411,6 +418,7 @@ OPTREVNAME, OPTREVREAL, OPTRFC2047PARAMS, + OPTSANITIZEJACHARS, OPTSAVEADDRESS, OPTSAVEEMPTY, OPTSAVENAME, @@ -426,6 +434,7 @@ OPTTHOROUGHSRC, OPTTHREADRECEIVED, OPTTILDE, + OPTTREECHARS, OPTUNCOLLAPSEJUMP, OPTUSE8BITMIME, OPTUSEDOMAIN, @@ -437,6 +446,9 @@ #ifdef HAVE_GETADDRINFO OPTUSEIPV6, #endif +#ifndef HAVE_WC_FUNCS + OPTUSEJISX0208, +#endif OPTWAITKEY, OPTWEED, OPTWRAP, @@ -459,6 +471,7 @@ OPTSMIMEISDEFAULT, OPTASKCERTLABEL, OPTSDEFAULTDECRYPTKEY, + OPTPGPCHARSETHACK, OPTPGPIGNORESUB, OPTPGPCHECKEXIT, OPTPGPLONGIDS, @@ -632,6 +645,7 @@ * If NULL, filename is used * instead. */ + char *charset; /* charset of attached file */ CONTENT *content; /* structure used to store detailed info about * the content of the attachment. this is used * to determine what content-transfer-encoding diff -ur mutt-1.5.9.orig/mutt_menu.h mutt-1.5.9/mutt_menu.h --- mutt-1.5.9.orig/mutt_menu.h 2003-10-05 04:29:27.000000000 +0900 +++ mutt-1.5.9/mutt_menu.h 2005-03-14 23:21:40.203343136 +0900 @@ -105,6 +105,8 @@ void mutt_menuDestroy (MUTTMENU **); int mutt_menuLoop (MUTTMENU *); +void mutt_init_treechars (void); + /* used in both the index and pager index to make an entry. */ void index_make_entry (char *, size_t, struct menu_t *, int); int index_color (int); diff -ur mutt-1.5.9.orig/mutt_regex.h mutt-1.5.9/mutt_regex.h --- mutt-1.5.9.orig/mutt_regex.h 2004-02-11 17:50:48.000000000 +0900 +++ mutt-1.5.9/mutt_regex.h 2005-03-14 23:21:40.207342528 +0900 @@ -51,5 +51,6 @@ WHERE REGEXP ReplyRegexp; WHERE REGEXP Smileys; WHERE REGEXP GecosMask; +WHERE REGEXP DeleteRegexp; #endif /* MUTT_REGEX_H */ diff -ur mutt-1.5.9.orig/muttlib.c mutt-1.5.9/muttlib.c --- mutt-1.5.9.orig/muttlib.c 2005-02-13 04:30:16.000000000 +0900 +++ mutt-1.5.9/muttlib.c 2005-03-14 23:21:40.217341008 +0900 @@ -1026,7 +1026,7 @@ count -= col; /* how many columns left on this line */ mutt_FormatString (buf, sizeof (buf), src, callback, data, flags); len = mutt_strlen (buf); - wid = mutt_strwidth (buf); + wid = mutt_strwidth_arboreal (buf); if (count > wid) { count -= wid; /* how many chars to pad */ @@ -1040,7 +1040,7 @@ memcpy (wptr, buf, len); wptr += len; wlen += len; - col += mutt_strwidth (buf); + col += mutt_strwidth_arboreal (buf); } break; /* skip rest of input */ } @@ -1092,7 +1092,7 @@ memcpy (wptr, buf, len); wptr += len; wlen += len; - col += mutt_strwidth (buf); + col += mutt_strwidth_arboreal (buf); } } else if (*src == '\\') diff -ur mutt-1.5.9.orig/mx.c mutt-1.5.9/mx.c --- mutt-1.5.9.orig/mx.c 2005-02-04 03:47:53.000000000 +0900 +++ mutt-1.5.9/mx.c 2005-03-14 23:21:40.228339336 +0900 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +144,39 @@ #endif /* USE_DOTLOCK */ +/* check if non-dot-beginning subdirectories exist */ +static int have_subdir (const char *path){ + int result = FALSE; + DIR * dirp; + struct dirent * de; + struct stat s; + char buffer[_POSIX_PATH_MAX + SHORT_STRING]; + + if ((dirp = opendir (path)) == NULL) + { + mutt_perror (path); + return (-1); + } + + while ((de = readdir (dirp)) != NULL) + { + if ( de->d_name[0] != '.' ) + { + snprintf (buffer, sizeof (buffer), "%s/%s", path, de->d_name); + if (lstat (buffer, &s) == -1) + continue; + + if (S_ISDIR (s.st_mode)) + { + result = TRUE; + break; + } + } + } + (void)closedir(dirp); + return result; +} + /* Args: * excl if excl != 0, request an exclusive lock * dot if dot != 0, try to dotlock the file @@ -415,6 +449,12 @@ if (access (tmp, F_OK) == 0) return (M_MH); + /* check if the directory-path is under $MhPath */ + if (mutt_strlen(MhPath) > 0 && + ! mutt_strncmp (MhPath, path, mutt_strlen(MhPath)) && + ! have_subdir (path)) + return (M_MH); + } else if (st.st_size == 0) { diff -ur mutt-1.5.9.orig/pager.c mutt-1.5.9/pager.c --- mutt-1.5.9.orig/pager.c 2005-02-13 04:30:16.000000000 +0900 +++ mutt-1.5.9/pager.c 2005-03-14 23:21:40.246336600 +0900 @@ -90,6 +90,21 @@ } #endif +#define REDRAW_WHOLE if(hdronly) \ + {\ + whole = 1; \ + hdronly = 0; \ + redraw = REDRAW_FULL; \ + break; \ + } + +#define DRAW_WHOLE if(hdronly) \ + {\ + whole = 1; \ + hdronly = 0; \ + redraw = REDRAW_FULL; \ + } + struct q_class_t { int length; @@ -145,6 +160,10 @@ #define NumSigLines 4 +static int hdronly = 0; +static int inbody = 0; +static int whole = 0; + static int check_sig (const char *s, struct line_t *info, int n) { int count = 0; @@ -1131,8 +1150,16 @@ if (col + t > wrap_cols) break; col += t; - if (pa) + if (pa) { + if (!inbody) mutt_addwch (wc); + else if (t == 1) + addch (Spoiler[0]); + else { + addch (Spoiler[0]); + addch (Spoiler[0]); + } + } } else if (wc == '\n') break; @@ -1429,6 +1456,9 @@ if (!(flags & M_SHOW)) flags = 0; + if (hdronly && buf[0] == '\n') + inbody = 1; + return (flags); } @@ -1503,6 +1533,10 @@ if (!(flags & M_SHOWCOLOR)) flags |= M_SHOWFLAT; + hdronly = option (OPTPAGERHDRSONLY) && IsHeader (extra) ? 1 : 0; + if (IsHeader (extra)) + whole = 0; + if ((fp = fopen (fname, "r")) == NULL) { mutt_perror (fname); @@ -1674,6 +1708,12 @@ lines = 0; force_redraw = 0; + if (!hdronly && IsHeader (extra)) + mutt_set_flag (Context, extra->hdr, M_READ, 1); + else if (IsHeader (extra) && Context->msgnotreadyet == extra->hdr->msgno) + mutt_set_flag (Context, extra->hdr, M_READ, 0); + inbody = 0; + while (lines < bodylen && lineInfo[curline].offset <= sb.st_size - 1) { if (display_line (fp, &last_pos, &lineInfo, curline, &lastLine, @@ -1682,6 +1722,10 @@ &QuoteList, &q_level, &force_redraw, &SearchRE) > 0) lines++; curline++; + + if (!option (OPTPAGERSPOIL) && hdronly && inbody) + lines = bodylen; + } last_offset = lineInfo[curline].offset; } while (force_redraw); @@ -1829,6 +1873,7 @@ break; case OP_NEXT_PAGE: + REDRAW_WHOLE; if (lineInfo[curline].offset < sb.st_size-1) { topline = upNLines (PagerContext, lineInfo, curline, hideQuoted); @@ -1856,6 +1901,7 @@ break; case OP_NEXT_LINE: + REDRAW_WHOLE; if (lineInfo[curline].offset < sb.st_size-1) { topline++; @@ -1911,6 +1957,7 @@ case OP_SEARCH_NEXT: case OP_SEARCH_OPPOSITE: + DRAW_WHOLE; if (SearchCompiled) { search_next: @@ -1956,6 +2003,7 @@ case OP_SEARCH: case OP_SEARCH_REVERSE: + DRAW_WHOLE; strfcpy (buffer, searchbuf, sizeof (buffer)); if (mutt_get_field ((SearchBack ? _("Reverse search: ") : _("Search: ")), buffer, sizeof (buffer), @@ -2076,6 +2124,9 @@ mutt_help (MENU_PAGER); redraw = REDRAW_FULL; InHelp = 0; + + if (!whole && option (OPTPAGERHDRSONLY)) + hdronly = 1; } else mutt_error _("Help is currently being shown."); diff -ur mutt-1.5.9.orig/parse.c mutt-1.5.9/parse.c --- mutt-1.5.9.orig/parse.c 2005-02-21 13:45:57.000000000 +0900 +++ mutt-1.5.9/parse.c 2005-03-14 23:21:40.257334928 +0900 @@ -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 */ @@ -384,7 +398,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); } } @@ -1419,6 +1435,25 @@ if (regexec (ReplyRegexp.rx, e->subject, 1, pmatch, 0) == 0) e->real_subj = e->subject + pmatch[0].rm_eo; + else if (option (OPTDELETEPREFIX)) + { + /* if this option is set, mutt will delete the string as [prefix], + * [prefix:number] and [prefix number] in Subject line. + */ + regmatch_t match[1]; + + if (regexec ((regex_t *) DeleteRegexp.rx, e->subject, 1, match, 0)) + e->real_subj = e->subject; + else + { + char *p = e->subject + match[0].rm_eo; + + if (regexec (ReplyRegexp.rx, p, 1, match, 0) == 0) + e->real_subj = p + match[0].rm_eo; + else + e->real_subj = p; + } + } else e->real_subj = e->subject; } diff -ur mutt-1.5.9.orig/pgp.c mutt-1.5.9/pgp.c --- mutt-1.5.9.orig/pgp.c 2005-02-20 07:03:16.000000000 +0900 +++ mutt-1.5.9/pgp.c 2005-03-14 23:21:40.269333104 +0900 @@ -249,6 +249,7 @@ short maybe_goodsig = 1; short have_any_sigs = 0; + char *gpgcharset = NULL; char body_charset[STRING]; mutt_get_body_charset (body_charset, sizeof (body_charset), m); @@ -317,6 +318,8 @@ && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0 || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",buf) == 0))) break; + if (mutt_strncmp ("Charset: ", buf, 9) == 0) + gpgcharset = mutt_substrdup (buf + 9, NULL); } /* leave tmpfp open in case we still need it - but flush it! */ @@ -383,9 +386,7 @@ /* - * Now, copy cleartext to the screen. NOTE - we expect that PGP - * outputs utf-8 cleartext. This may not always be true, but it - * seems to be a reasonable guess. + * Now, copy cleartext to the screen. */ if(s->flags & M_DISPLAY) @@ -408,12 +409,15 @@ { FGETCONV *fc; int c; + char *expected_charset = ((!option (OPTPGPCHARSETHACK)) ? "utf-8" : + (gpgcharset ? gpgcharset : body_charset)); rewind (pgpout); state_set_prefix (s); - fc = fgetconv_open (pgpout, "utf-8", Charset, 0); + fc = fgetconv_open (pgpout, expected_charset, Charset, M_ICONV_HOOK_FROM); while ((c = fgetconv (fc)) != EOF) state_prefix_putc (c, s); fgetconv_close (&fc); + FREE (&gpgcharset); } if (s->flags & M_DISPLAY) @@ -1354,12 +1358,11 @@ int c; FGETCONV *fc; - if (flags & ENCRYPT) - send_charset = "us-ascii"; - else - send_charset = "utf-8"; - - fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM); + send_charset = option(OPTPGPCHARSETHACK) ? body_charset : + ((flags & ENCRYPT) ? "us-ascii" : "utf-8"); + fc = fgetconv_open (fp, from_charset, + option(OPTPGPCHARSETHACK) ? send_charset : "utf-8", + M_ICONV_HOOK_FROM); while ((c = fgetconv (fc)) != EOF) fputc (c, pgpin); diff -ur mutt-1.5.9.orig/rfc2047.c mutt-1.5.9/rfc2047.c --- mutt-1.5.9.orig/rfc2047.c 2005-02-04 03:47:53.000000000 +0900 +++ mutt-1.5.9/rfc2047.c 2005-03-14 23:22:11.421597240 +0900 @@ -62,6 +62,9 @@ size_t obl, n; int e; + if (option (OPTSANITIZEJACHARS) && !ascii_strncasecmp (from, "iso-2022-jp", +11)) + mutt_sanitize_ja_chars ((char *) f, flen, 0); cd = mutt_iconv_open (to, from, 0); if (cd == (iconv_t)(-1)) return (size_t)(-1); @@ -87,6 +90,43 @@ return n; } +int convert_nonmime_string (char **ps) +{ + const char *c, *c1; + + for (c = AssumedCharset; c; c = c1 ? c1 + 1 : 0) + { + char *u = *ps; + char *s; + char *fromcode; + size_t m, n; + size_t ulen = mutt_strlen (*ps); + size_t slen; + + if (!u || !*u) + return 0; + + c1 = strchr (c, ':'); + n = c1 ? c1 - c : mutt_strlen (c); + if (!n) + return 0; + fromcode = safe_malloc (n + 1); + strfcpy (fromcode, c, n + 1); + 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, char *u, size_t ulen, char **d, size_t *dlen) { @@ -710,13 +747,54 @@ return 0; } +/* return length of linear-white-space */ +static size_t lwslen (const char *s, size_t n) +{ + const char *p = s; + size_t len = n; + + if (n <= 0) + return 0; + + for (; p < s + n; p++) + if (!strchr (" \t\r\n", *p)) + { + len = (size_t)(p - s); + break; + } + if (strchr ("\r\n", *(p-1))) /* LWS doesn't end with CRLF */ + len = (size_t)0; + return len; +} + +/* return length of linear-white-space : reverse */ +static size_t lwsrlen (const char *s, size_t n) +{ + const char *p = s + n - 1; + size_t len = n; + + if (n <= 0) + return 0; + + if (strchr ("\r\n", *p)) /* LWS doesn't end with CRLF */ + return (size_t)0; + + for (; p >= s; p--) + if (!strchr (" \t\r\n", *p)) + { + len = (size_t)(s + n - 1 - p); + break; + } + return len; +} + /* try to decode anything that looks like a valid RFC2047 encoded * header field, ignoring RFC822 parsing rules */ void rfc2047_decode (char **pd) { const char *p, *q; - size_t n; + size_t m, n; int found_encoded = 0; char *d0, *d; const char *s = *pd; @@ -733,6 +811,31 @@ if (!(p = find_encoded_word (s, &q))) { /* no encoded words */ + if (option (OPTIGNORELWS)) + { + n = mutt_strlen (s); + if (found_encoded && (m = lwslen (s, n)) != 0) + { + if (m != n) + *d = ' ', d++, dlen--; + s += m; + } + } + if (AssumedCharset && *AssumedCharset) + { + char *t; + size_t tlen; + + n = mutt_strlen (s); + t = safe_malloc (n + 1); + strfcpy (t, s, n + 1); + convert_nonmime_string (&t); + tlen = mutt_strlen (t); + strncpy (d, t, tlen); + d += tlen; + FREE (&t); + break; + } strncpy (d, s, dlen); d += dlen; break; @@ -741,8 +851,29 @@ if (p != s) { n = (size_t) (p - s); - /* ignore spaces between encoded words */ - if (!found_encoded || strspn (s, " \t\r\n") != n) + /* ignore spaces between encoded word + * and linear-white-space between encoded word and *text */ + if (option (OPTIGNORELWS)) + { + if (found_encoded && (m = lwslen (s, n)) != 0) + { + if (m != n) + *d = ' ', d++, dlen--; + n -= m, s += m; + } + + if ((m = n - lwsrlen (s, n)) != 0) + { + if (m > dlen) + m = dlen; + memcpy (d, s, m); + d += m; + dlen -= m; + if (m != n) + *d = ' ', d++, dlen--; + } + } + else if (!found_encoded || strspn (s, " \t\r\n") != n) { if (n > dlen) n = dlen; @@ -770,7 +901,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 -ur mutt-1.5.9.orig/rfc2047.h mutt-1.5.9/rfc2047.h --- mutt-1.5.9.orig/rfc2047.h 2002-12-11 20:19:40.000000000 +0900 +++ mutt-1.5.9/rfc2047.h 2005-03-14 23:21:40.283330976 +0900 @@ -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 -ur mutt-1.5.9.orig/rfc2231.c mutt-1.5.9/rfc2231.c --- mutt-1.5.9.orig/rfc2231.c 2005-02-04 03:47:53.000000000 +0900 +++ mutt-1.5.9/rfc2231.c 2005-03-14 23:21:40.288330216 +0900 @@ -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 -ur mutt-1.5.9.orig/sendlib.c mutt-1.5.9/sendlib.c --- mutt-1.5.9.orig/sendlib.c 2005-02-21 13:45:57.000000000 +0900 +++ mutt-1.5.9/sendlib.c 2005-03-14 23:21:40.305327632 +0900 @@ -407,6 +407,33 @@ } } + if (a->use_disp && option (OPTCREATERFC2047PARAMS)) + { + if(!(fn = a->d_filename)) + fn = a->filename; + + if (fn) + { + char *tmp; + + /* Strip off the leading path... */ + if ((t = strrchr (fn, '/'))) + t++; + else + t = fn; + + /* length of content-type */ + len = 21 + mutt_strlen (TYPE (a)) + mutt_strlen (a->subtype); + + buffer[0] = 0; + tmp = safe_strdup (t); + _rfc2047_encode_string (&tmp, 0, len); + rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials); + FREE (&tmp); + fprintf (f, "; name=%s", buffer); + } + } + fputc ('\n', f); if (a->description) @@ -500,7 +527,7 @@ } if (a->type == TYPETEXT && (!a->noconv)) - fc = fgetconv_open (fpin, Charset, + fc = fgetconv_open (fpin, a->charset, mutt_get_body_charset (send_charset, sizeof (send_charset), a), 0); else @@ -900,6 +927,7 @@ CONTENT *info; CONTENT_STATE state; FILE *fp = NULL; + char *fromcode; char *tocode; char buffer[100]; char chsbuf[STRING]; @@ -934,15 +962,18 @@ if (b != NULL && b->type == TYPETEXT && (!b->noconv && !b->force_charset)) { char *chs = mutt_get_parameter ("charset", b->parameter); + char *fchs = b->use_disp ? ((AttachCharset && *AttachCharset) ? + AttachCharset : Charset) : Charset; if (Charset && (chs || SendCharset) && - convert_file_from_to (fp, Charset, chs ? chs : SendCharset, - 0, &tocode, info) != (size_t)(-1)) + convert_file_from_to (fp, fchs, chs ? chs : SendCharset, + &fromcode, &tocode, info) != (size_t)(-1)) { if (!chs) { mutt_canonical_charset (chsbuf, sizeof (chsbuf), tocode); mutt_set_parameter ("charset", chsbuf, &b->parameter); } + b->charset = fromcode; FREE (&tocode); safe_fclose (&fp); return info; @@ -1325,6 +1356,7 @@ body->unlink = 1; body->use_disp = 0; body->disposition = DISPINLINE; + body->noconv = 1; mutt_parse_mime_message (ctx, hdr); @@ -1645,7 +1677,7 @@ fputs ("Subject: \n", fp); /* save message id if the user has set it */ - if (env->message_id && !privacy) + if (option (OPTMSGID) && env->message_id && !privacy) fprintf (fp, "Message-ID: %s\n", env->message_id); if (env->reply_to) @@ -1771,15 +1803,25 @@ time_t now; struct tm *tm; const char *fqdn; + char symbol; now = time (NULL); tm = gmtime (&now); + if( option (OPTMSGIDUSEFROM) && From) + { + fqdn = NONULL(From->mailbox); + symbol = '%'; + } + else + { if(!(fqdn = mutt_fqdn(0))) fqdn = NONULL(Hostname); + symbol = '@'; + } - snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.G%c%u@%s>", + snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.G%c%d%c%s>", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec, MsgIdPfx, (unsigned int)getpid (), fqdn); + tm->tm_min, tm->tm_sec, MsgIdPfx, (unsigned int)getpid (), symbol, fqdn); MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1; return (safe_strdup (buf)); } --- mutt-1.5.9.orig/protos.h~ 2005-03-19 15:07:15.192142944 +0900 +++ mutt-1.5.9/protos.h 2005-03-19 15:07:52.465476536 +0900 @@ -339,6 +339,7 @@ int mutt_save_message (HEADER *, int, int, int, int *); int mutt_search_command (int, int); int mutt_strwidth (const char *); +int mutt_strwidth_arboreal (const char *); int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); int mutt_thread_set_flag (HEADER *, int, int, int); int mutt_user_is_recipient (HEADER *);