about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Src/utils.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/Src/utils.c b/Src/utils.c
index d90b128e9..bb993e74d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2577,7 +2577,8 @@ inittyptab(void)
 	char *wordchars_unmeta;
 	const char *wordchars_ptr;
 	mbstate_t mbs;
-	int nchars, unmetalen;
+	size_t nchars;
+	int unmetalen;
 
 	wordchars_unmeta = dupstring(wordchars);
 	wordchars_ptr = unmetafy(wordchars_unmeta, &unmetalen);
@@ -2586,12 +2587,11 @@ inittyptab(void)
 	wordchars_wide = (wchar_t *)
 	    zrealloc(wordchars_wide, (unmetalen+1)*sizeof(wchar_t));
 	nchars = mbsrtowcs(wordchars_wide, &wordchars_ptr, unmetalen, &mbs);
-	if (nchars == -1) {
+	if (nchars == MB_INVALID || nchars == MB_INCOMPLETE) {
 	    /* Conversion state is undefined: better just set to null */
-	    *wordchars_wide = L'\0';
-	} else {
-	    wordchars_wide[nchars] = L'\0';
+	    nchars = 0;
 	}
+	wordchars_wide[nchars] = L'\0';
     } else {
 	wordchars_wide = zrealloc(wordchars_wide, sizeof(wchar_t));
 	*wordchars_wide = L'\0';
@@ -3447,10 +3447,10 @@ mod_export size_t
 mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap)
 {
     size_t l = 0, newl;
-    int umlen, outalloc, outleft;
+    int umlen, outalloc, outleft, eol = 0;
     wchar_t c;
     char *ums, *ptr, *fmt, *outstr, *outptr;
-    mbstate_t ps;
+    mbstate_t mbs;
 
     if (outstrp) {
 	outleft = outalloc = 5 * strlen(s);
@@ -3469,19 +3469,21 @@ mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap)
     untokenize(ums);
     ptr = unmetafy(ums, &umlen);
 
-    memset(&ps, 0, sizeof(ps));
+    memset(&mbs, 0, sizeof mbs);
     while (umlen > 0) {
-	size_t cnt = mbrtowc(&c, ptr, umlen, &ps);
+	size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs);
 
 	switch (cnt) {
-	case (size_t)-1:
-	case (size_t)-2:
+	case MB_INCOMPLETE:
+	    eol = 1;
+	    /* FALL THROUGH */
+	case MB_INVALID:
 	    /* The byte didn't convert, so output it as a \M-... sequence. */
 	    fmt = nicechar(STOUC(*ptr));
 	    newl = strlen(fmt);
 	    cnt = 1;
-	    /* Get ps out of its undefined state. */
-	    memset(&ps, 0, sizeof ps);
+	    /* Get mbs out of its undefined state. */
+	    memset(&mbs, 0, sizeof mbs);
 	    break;
 	case 0:
 	    /* Careful:  converting '\0' returns 0, but a '\0' is a
@@ -3552,11 +3554,11 @@ mod_export int
 mb_width(const char *s)
 {
     char *ums = ztrdup(s), *umptr;
-    int umlen;
+    int umlen, eol = 0;
     int width = 0;
     mbstate_t mbs;
 
-    memset(&mbs, 0, sizeof(mbs));
+    memset(&mbs, 0, sizeof mbs);
     umptr = unmetafy(ums, &umlen);
     /*
      * Convert one wide character at a time.  We could convet
@@ -3564,17 +3566,27 @@ mb_width(const char *s)
      * a NUL and we might have embedded NULs.
      */
     while (umlen > 0) {
+	int wret;
 	wchar_t cc;
-	size_t cnt = mbrtowc(&cc, umptr, umlen, &mbs);
+	size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, umptr, umlen, &mbs);
 
-	if (cnt == 0 || cnt == (size_t)-1 || cnt == (size_t)-2) {
+	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;
-	} else {
-	    int wret = wcwidth(cc);
+	    break;
+	default:
+	    wret = wcwidth(cc);
 	    if (wret > 0)
 		width += wret;
+	    break;
 	}
 
 	umlen -= cnt;
@@ -3989,7 +4001,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
     int i;
 #if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
     wint_t wval;
-    size_t count;
+    int count;
 #else
     unsigned int wval;
 # if defined(HAVE_NL_LANGINFO) && defined(CODESET) && defined(HAVE_ICONV)
@@ -4098,7 +4110,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		}
 #if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
 		count = wctomb(t, (wchar_t)wval);
-		if (count == (size_t)-1) {
+		if (count == -1) {
 		    zerr("character not in range", NULL, 0);
 		    if (fromwhere == 4) {
 			for (u = t; (*u++ = *++s););