[PATCH] Make mutt_FormatString multibyte aware
For the %> and %| expandos in format strings, mutt used 'ch = *src++' to
extract the pad character which works for single-byte locales only.
We now use a multibyte aware get_mbchar() to extract it.
---
Note that this a rather crude hack using a static get_mbchar() routine
in muttlib.c which likely could be of some valid use in other places,
too. Also note that I don't have much experience with the multibyte
string functions, so please test heavily and use with care. At least it
appears to work... :)
For example, we can use %>U+2014 in $status_format to get a horizontal
bar without gaps, I didn't test any other format strings.
muttlib.c | 45 +++++++++++++++++++++++++++++++++++++++------
1 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/muttlib.c b/muttlib.c
index 32495f3..a405d30 100644
--- a/muttlib.c
+++ b/muttlib.c
@@ -985,6 +985,33 @@ void mutt_safe_path (char *s, size_t l, ADDRESS *a)
*p = '_';
}
+/* extract first (possibly multibyte) character from src into dst;
+ * return number of bytes char consists of */
+static int get_mbchar (char *dst, const char* src)
+{
+ mbstate_t st;
+ wchar_t wc;
+ int i;
+ char *p = (char *) src;
+
+ memset (&st, 0, sizeof (st));
+ memset (&wc, 0, sizeof (wc));
+
+ i = mbrtowc (&wc, p, MB_LEN_MAX, &st);
+ if (i == (size_t)(-1) || i == (size_t)(-2) || i == 0)
+ goto bail;
+ p += i;
+ i = wctomb (dst, wc);
+ if (i == (size_t)(-1) || i == 0)
+ goto bail;
+
+ return p - src;
+
+bail:
+ /* in case of conversion error: take first byte from src */
+ *dst = *src;
+ return 1;
+}
void mutt_FormatString (char *dest, /* output buffer */
size_t destlen, /* output buffer len */
@@ -1000,6 +1027,7 @@ void mutt_FormatString (char *dest, /*
output buffer */
FILE *filter;
int n;
char *recycler;
+ char pad[MB_LEN_MAX] = "";
prefix[0] = '\0';
destlen--; /* save room for the terminal \0 */
@@ -1191,7 +1219,8 @@ void mutt_FormatString (char *dest, /*
output buffer */
if (ch == '>')
{
/* right justify to EOL */
- ch = *src++; /* pad char */
+ size_t padlen = get_mbchar (pad, src); /* pad char */
+ src += padlen;
/* calculate space left on line. if we've already written more data
than will fit on the line, ignore the rest of the line */
count = (COLS < destlen ? COLS : destlen);
@@ -1203,9 +1232,10 @@ void mutt_FormatString (char *dest, /*
output buffer */
wid = mutt_strwidth (buf);
if (count > wid)
{
+ int i;
count -= wid; /* how many chars to pad */
- memset (wptr, ch, count);
- wptr += count;
+ for (i = 0; i < count; i++, wptr += padlen)
+ memcpy (wptr, pad, padlen);
wlen += count;
col += count;
}
@@ -1221,14 +1251,17 @@ void mutt_FormatString (char *dest, /*
output buffer */
else if (ch == '|')
{
/* pad to EOL */
- ch = *src++;
+ size_t padlen = get_mbchar (pad, src); /* pad char */
+ src += padlen;
+
if (destlen > COLS)
destlen = COLS;
if (destlen > wlen)
{
+ int i;
count = destlen - wlen;
- memset (wptr, ch, count);
- wptr += count;
+ for (i = 0; i < count; i++, wptr += padlen)
+ memcpy (wptr, pad, padlen);
}
break; /* skip rest of input */
}
--
1.5.0.4.1009.g31b4