From a242b1eb35863b73cbc63699fafe920e8b92c858 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 13 Sep 2006 20:55:29 +0000 Subject: 22705: make ${(l...)...} and ${(r...)...} handle multibyte characters --- Src/utils.c | 88 ++++++++++++++++++++++--------------------------------------- 1 file changed, 31 insertions(+), 57 deletions(-) (limited to 'Src/utils.c') diff --git a/Src/utils.c b/Src/utils.c index a72ddfcc5..37017bdc7 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -524,8 +524,12 @@ wcs_nicechar(wchar_t c, size_t *widthp, char **swidep) return buf; } - if (widthp) - *widthp = (s - buf) + wcwidth(c); + if (widthp) { + int wcw = wcwidth(c); + *widthp = (s - buf); + if (wcw > 0) + *widthp += wcw; + } if (swidep) *swidep = s; for (mbptr = mbstr; ret; s++, mbptr++, ret--) { @@ -539,6 +543,22 @@ wcs_nicechar(wchar_t c, size_t *widthp, char **swidep) *s = 0; return buf; } + +/**/ +mod_export int +zwcwidth(wint_t wc) +{ + int wcw; + /* assume a single-byte character if not valid */ + if (wc == WEOF) + return 1; + wcw = wcwidth(wc); + /* if not printable, assume zero width */ + if (wcw <= 0) + return 0; + return wcw; +} + /**/ #endif /* MULTIBYTE_SUPPORT */ @@ -3953,58 +3973,6 @@ nicedup(const char *s, int heap) return retstr; } -/* - * Return the screen width of a multibyte string. The input - * string is metafied. - */ -/**/ -mod_export int -mb_width(const char *s) -{ - char *ums = ztrdup(s), *umptr; - int umlen, eol = 0; - int width = 0; - mbstate_t mbs; - - memset(&mbs, 0, sizeof mbs); - umptr = unmetafy(ums, ¨en); - /* - * Convert one wide character at a time. We could convet - * the entire string using mbsrtowcs(), but that terminates on - * a NUL and we might have embedded NULs. - */ - while (umlen > 0) { - int wret; - wchar_t cc; - size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, umptr, umlen, &mbs); - - switch (cnt) { - case MB_INCOMPLETE: - eol = 1; - /* FALL THROUGH */ - case MB_INVALID: - memset(&mbs, 0, sizeof mbs); - /* FALL THROUGH */ - case 0: - /* Assume a single-width character. */ - width++; - cnt = 1; - break; - default: - wret = wcwidth(cc); - if (wret > 0) - width += wret; - break; - } - - umlen -= cnt; - umptr += cnt; - } - - free(ums); - - return width; -} /* * Length of metafied string s which contains the next multibyte @@ -4107,9 +4075,15 @@ mb_metastrlen(char *ptr, int width) memset(&mb_shiftstate, 0, sizeof(mb_shiftstate)); ptr = laststart + (*laststart == Meta) + 1; num++; - } else if (width) - num += wcwidth(wc); - else + } else if (width) { + /* + * Returns -1 if not a printable character; best + * just to ignore these. + */ + int wcw = wcwidth(wc); + if (wcw > 0) + num += wcw; + } else num++; laststart = ptr; num_in_char = 0; -- cgit 1.4.1