diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2006-09-13 20:55:29 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2006-09-13 20:55:29 +0000 |
commit | a242b1eb35863b73cbc63699fafe920e8b92c858 (patch) | |
tree | 141db2c3c4a20d1a44d7fe357a39d0ba4aab9d4f /Src/utils.c | |
parent | efd061cdc9bdc0ba692387ec25eb6d01616d0425 (diff) | |
download | zsh-a242b1eb35863b73cbc63699fafe920e8b92c858.tar.gz zsh-a242b1eb35863b73cbc63699fafe920e8b92c858.tar.xz zsh-a242b1eb35863b73cbc63699fafe920e8b92c858.zip |
22705: make ${(l...)...} and ${(r...)...} handle multibyte characters
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 88 |
1 files changed, 31 insertions, 57 deletions
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; |