From 564cedb49e758b212e4157df170ff4b729d3ce96 Mon Sep 17 00:00:00 2001 From: Rocco Rutte Date: Fri, 28 Sep 2007 11:06:43 +0200 Subject: [PATCH] Make mutt_FormatString()'s string truncation multibyte aware --- curs_lib.c | 32 ++++++++++++++++++++++++++++++++ muttlib.c | 14 +++++++------- protos.h | 1 + 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/curs_lib.c b/curs_lib.c index 8fdb6816..cb1947ab 100644 --- a/curs_lib.c +++ b/curs_lib.c @@ -822,6 +822,38 @@ void mutt_paddstr (int n, const char *s) addch (' '); } +/* See how many bytes to copy from string so its at most maxlen bytes + * long and maxwid columns wide */ +int mutt_wstr_trunc (const char *src, size_t maxlen, size_t maxwid, size_t *width) +{ + wchar_t wc; + int w = 0, l = 0, cl; + size_t cw, n; + mbstate_t mbstate; + + if (!src) + goto out; + + n = mutt_strlen (src); + + memset (&mbstate, 0, sizeof (mbstate)); + for (w = 0; n && (cl = mbrtowc (&wc, src, n, &mbstate)); src += cl, n -= cl) + { + if (cl == (size_t)(-1) || cl == (size_t)(-2)) + cw = cl = 1; + else + cw = wcwidth (wc); + if (cl + l > maxlen || cw + w > maxwid) + break; + l += cl; + w += cw; + } +out: + if (width) + *width = w; + return l; +} + /* * returns the number of bytes the first (multibyte) character * of input consumes: diff --git a/muttlib.c b/muttlib.c index ca06d27c..2b7be974 100644 --- a/muttlib.c +++ b/muttlib.c @@ -1232,16 +1232,16 @@ void mutt_FormatString (char *dest, /* output buffer */ else if (soft && pad < 0) { /* set wptr and wlen back just enough bytes to make sure buf - * fits on screen, col needs no adjustments as we skip more input - * currently multibyte unaware */ + * fits on screen, \0-terminate dest so mutt_wstr_trunc() + * can correctly compute string's length */ if (pad < -wlen) pad = -wlen; - wlen += pad; - wptr += pad; + *wptr = 0; + wlen = mutt_wstr_trunc (dest, wlen + pad, col + pad, &col); + wptr = dest + wlen; } if (len + wlen > destlen) - len = destlen - wlen; - /* copy as much of buf as possible: multibyte unaware */ + len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL); memcpy (wptr, buf, len); wptr += len; wlen += len; @@ -1304,7 +1304,7 @@ void mutt_FormatString (char *dest, /* output buffer */ } if ((len = mutt_strlen (buf)) + wlen > destlen) - len = (destlen - wlen > 0) ? (destlen - wlen) : 0; + len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL); memcpy (wptr, buf, len); wptr += len; diff --git a/protos.h b/protos.h index 210ef6e7..7a156b69 100644 --- a/protos.h +++ b/protos.h @@ -355,6 +355,7 @@ int mutt_search_command (int, int); int mutt_smtp_send (const ADDRESS *, const ADDRESS *, const ADDRESS *, const ADDRESS *, const char *, int); #endif +int mutt_wstr_trunc (const char *, size_t, size_t, size_t *); int mutt_charlen (const char *s, int *); int mutt_strwidth (const char *); int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); -- 2.40.0