From eebfabe5487484b3d1e732386989e739bd3d869e Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Thu, 12 Jan 2006 00:51:41 +0000 Subject: - The return value of mbrtowc() is a size_t (unsigned), so don't assign it to an int and then check for negativity, as that won't work on a system where an int is larger than a size_t. - When mbrtowc() returns -2 when given all the remaining chars in a string, set an end-of-line flag and avoid calling mbrtowc() again for any of the incomplete characters that remain in the string. - Use STOUC() when passing a char value to nicechar(). - Use "mbs" for the multi-byte state variable name (for consistency). - Be sure to reset the mbs state if mbrtowc() returns -1. - Use the new MB_INVALID and MB_INCOMPLETE defines for the size_t -1 and -2 values (respectively). --- Src/prompt.c | 132 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/Src/prompt.c b/Src/prompt.c index d21029a37..cf0e75adb 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -738,10 +738,10 @@ stradd(char *d) { #ifdef MULTIBYTE_SUPPORT char *ums, *ups; - int upslen; - mbstate_t ps; + int upslen, eol = 0; + mbstate_t mbs; - memset(&ps, 0, sizeof(ps)); + memset(&mbs, 0, sizeof mbs); ums = ztrdup(d); ups = unmetafy(ums, &upslen); @@ -752,22 +752,31 @@ stradd(char *d) while (upslen > 0) { wchar_t cc; char *pc; - int ret = mbrtowc(&cc, ups, upslen, &ps); + size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, ups, upslen, &mbs); - if (ret <= 0) - { + switch (cnt) { + case MB_INCOMPLETE: + eol = 1; + /* FALL THROUGH */ + case MB_INVALID: /* Bad character. Take the next byte on its own. */ - pc = nicechar(*ups); - ret = 1; - } else { + pc = nicechar(STOUC(*ups)); + cnt = 1; + memset(&mbs, 0, sizeof mbs); + break; + case 0: + cnt = 1; + /* FALL THROUGH */ + default: /* Take full wide character in one go */ pc = wcs_nicechar(cc, NULL, NULL); + break; } /* Keep output as metafied string. */ addbufspc(strlen(pc)); - upslen -= ret; - ups += ret; + upslen -= cnt; + ups += cnt; /* Put printed representation into the buffer */ while (*pc) @@ -862,7 +871,7 @@ countprompt(char *str, int *wp, int *hp, int overf) int w = 0, h = 1; int s = 1; #ifdef MULTIBYTE_SUPPORT - int mbret, wcw, multi = 0; + int wcw, multi = 0; char inchar; mbstate_t mbs; wchar_t wc; @@ -918,24 +927,25 @@ countprompt(char *str, int *wp, int *hp, int overf) } #ifdef MULTIBYTE_SUPPORT - mbret = mbrtowc(&wc, &inchar, 1, &mbs); - if (mbret >= -1) { - if (mbret > 0) { - /* - * If the character isn't printable, this returns -1. - */ - wcw = wcwidth(wc); - if (wcw > 0) - w += wcw; - } - /* - * else invalid character or possibly null: assume no - * output - */ - multi = 0; - } else { - /* else character is incomplete, keep looking. */ + switch (mbrtowc(&wc, &inchar, 1, &mbs)) { + case MB_INCOMPLETE: + /* Character is incomplete -- keep looking. */ multi = 1; + break; + case MB_INVALID: + memset(&mbs, 0, sizeof mbs); + /* FALL THROUGH */ + case 0: + /* Invalid character or null: assume no output. */ + multi = 0; + break; + default: + /* If the character isn't printable, wcwidth() returns -1. */ + wcw = wcwidth(wc); + if (wcw > 0) + w += wcw; + multi = 0; + break; } #else w++; @@ -1078,7 +1088,7 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar) int remw; #ifdef MULTIBYTE_SUPPORT mbstate_t mbs; - memset(&mbs, 0, sizeof(mbstate_t)); + memset(&mbs, 0, sizeof mbs); #endif fulltextptr = fulltext = ptr + ntrunc; @@ -1117,7 +1127,6 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar) */ char inchar; wchar_t cc; - int ret; /* * careful: string is still metafied (we @@ -1130,20 +1139,21 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar) else inchar = *fulltextptr; fulltextptr++; - ret = mbrtowc(&cc, &inchar, 1, &mbs); - - if (ret != -2) { - /* complete */ - if (ret <= 0) { - /* assume a single-byte character */ - remw--; - if (ret < 0) { - /* need to reset invalid state */ - memset(&mbs, 0, sizeof(mbstate_t)); - } - } else { - remw -= wcwidth(cc); - } + switch (mbrtowc(&cc, &inchar, 1, &mbs)) { + case MB_INCOMPLETE: + /* Incomplete multibyte character. */ + break; + case MB_INVALID: + /* Reset invalid state. */ + memset(&mbs, 0, sizeof mbs); + /* FALL THROUGH */ + case 0: + /* Assume a single-byte character. */ + remw--; + break; + default: + remw -= wcwidth(cc); + break; } #else /* Single byte character */ @@ -1172,7 +1182,7 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar) char *skiptext = ptr; #ifdef MULTIBYTE_SUPPORT mbstate_t mbs; - memset(&mbs, 0, sizeof(mbstate_t)); + memset(&mbs, 0, sizeof mbs); #endif while (maxwidth > 0 && *skiptext) { @@ -1183,27 +1193,27 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar) #ifdef MULTIBYTE_SUPPORT char inchar; wchar_t cc; - int ret; if (*skiptext == Meta) inchar = *++skiptext ^ 32; else inchar = *skiptext; skiptext++; - ret = mbrtowc(&cc, &inchar, 1, &mbs); - - if (ret != -2) { - /* complete or invalid character */ - if (ret <= 0) { - /* assume single byte */ - maxwidth--; - if (ret < 0) { - /* need to reset invalid state */ - memset(&mbs, 0, sizeof(mbstate_t)); - } - } else { - maxwidth -= wcwidth(cc); - } + switch (mbrtowc(&cc, &inchar, 1, &mbs)) { + case MB_INCOMPLETE: + /* Incomplete character. */ + break; + case MB_INVALID: + /* Reset invalid state. */ + memset(&mbs, 0, sizeof mbs); + /* FALL THROUGH */ + case 0: + /* Assume a single-byte character. */ + maxwidth--; + break; + default: + maxwidth -= wcwidth(cc); + break; } #else if (*skiptext == Meta) -- cgit 1.4.1