--- ChangeLog	10 Jan 2006 16:57:02 -0000	1.2995
+++ ChangeLog	12 Jan 2006 01:06:03 -0000	1.2997
@@ -1,3 +1,10 @@
+2006-01-11  Wayne Davison  <wayned@users.sourceforge.net>
+
+	* unposted: zsh.h, prompt.c, utils.c, Zle/complist.c, Zle/compmatch.c,
+	Zle/zle_main.c, Zle/zle_refresh.c, Zle/zle_tricky.c, Zle/zle_utils.c:
+	more multibyte cleanup, including the MB_INVALID and MB_INCOMPLETE
+	defines to make the mbrtowc() and mbsrtowcs() return values clearer.
+
 2006-01-10  Peter Stephenson  <pws@csr.com>
 
 	* 22151: Src/text.c: a here-string got too many quotes when
--- Src/prompt.c	28 Oct 2005 17:34:33 -0000	1.31
+++ Src/prompt.c	12 Jan 2006 00:51:41 -0000	1.32
@@ -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 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,
 	    }
 
 #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 
 		    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 
 			     */
 			    char inchar;
 			    wchar_t cc;
-			    int ret;
 
 			    /*
 			     * careful: string is still metafied (we
@@ -1130,20 +1139,21 @@ prompttrunc(int arg, int truncchar, int 
 			    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 
 		    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 
 #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)
--- Src/utils.c	9 Jan 2006 17:44:02 -0000	1.111
+++ Src/utils.c	12 Jan 2006 00:51:44 -0000	1.114
@@ -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,23 +3469,30 @@ mb_niceformat(const char *s, FILE *strea
     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);
 
-	if (cnt != (size_t)-1 && cnt != (size_t)-2) {
-	    /* Careful:  converting '\0' returns 0, but a '\0' is a
-	     * real character for us, so we should consume 1 byte. */
-	    if (cnt == 0)
-		cnt = 1;
-	    fmt = wcs_nicechar(c, &newl, NULL);
-	} else {
+	switch (cnt) {
+	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
+	     * real character for us, so we should consume 1 byte. */
+	    cnt = 1;
+	    /* FALL THROUGH */
+	default:
+	    fmt = wcs_nicechar(c, &newl, NULL);
+	    break;
 	}
 
 	umlen -= cnt;
@@ -3547,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
@@ -3559,21 +3566,31 @@ mb_width(const char *s)
      * a NUL and we might have embedded NULs.
      */
     while (umlen > 0) {
+	int wret;
 	wchar_t cc;
-	int ret = mbrtowc(&cc, umptr, umlen, &mbs);
+	size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, umptr, umlen, &mbs);
 
-	if (ret <= 0) {
+	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++;
-	    ret = 1;
-	} else {
-	    int wret = wcwidth(cc);
+	    cnt = 1;
+	    break;
+	default:
+	    wret = wcwidth(cc);
 	    if (wret > 0)
 		width += wret;
+	    break;
 	}
 
-	umlen -= ret;
-	umptr += ret;
+	umlen -= cnt;
+	umptr += cnt;
     }
 
     free(ums);
@@ -3887,7 +3904,7 @@ dquotedztrdup(char const *s)
 		    if(pending)
 			*p++ = '\\';
 		    *p++ = '\\';
-		    /* fall through */
+		    /* FALL THROUGH */
 		default:
 		    *p++ = c;
 		    pending = 0;
@@ -3984,7 +4001,7 @@ getkeystring(char *s, int *len, int from
     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)
@@ -4093,7 +4110,7 @@ getkeystring(char *s, int *len, int from
 		}
 #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););
--- Src/zsh.h	15 Nov 2005 08:44:21 -0000	1.83
+++ Src/zsh.h	12 Jan 2006 00:51:38 -0000	1.84
@@ -1931,4 +1931,7 @@ typedef char *(*ZleGetLineFn) _((int *, 
 
 #ifdef MULTIBYTE_SUPPORT
 #define nicezputs(str, outs)	(void)mb_niceformat((str), (outs), NULL, 0)
+
+#define MB_INCOMPLETE	((size_t)-2)
+#define MB_INVALID	((size_t)-1)
 #endif
--- Src/Zle/complist.c	9 Jan 2006 00:37:10 -0000	1.80
+++ Src/Zle/complist.c	12 Jan 2006 00:51:50 -0000	1.82
@@ -572,14 +572,14 @@ clnicezputs(Listcols colors, char *s, in
      * umlen is the full length of the unmetafied string
      * width is the full printing width of a prettified character,
      *  including both ASCII prettification and the wide character itself.
-     * ps is the shift state of the conversion to wide characters.
+     * mbs is the shift state of the conversion to wide characters.
      */
     char *ums, *uptr, *sptr, *wptr;
-    int umleft, umlen;
+    int umleft, umlen, eol = 0;
     size_t width;
-    mbstate_t ps;
+    mbstate_t mbs;
 
-    memset(&ps, 0, sizeof(ps));
+    memset(&mbs, 0, sizeof mbs);
     ums = ztrdup(s);
     untokenize(ums);
     uptr = unmetafy(ums, &umlen);
@@ -589,31 +589,42 @@ clnicezputs(Listcols colors, char *s, in
 	initiscol(colors);
 
     while (umleft > 0) {
-	size_t ret = mbrtowc(&cc, uptr, umleft, &ps);
+	size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, uptr, umleft, &mbs);
 
-	if (ret == 0 || ret == (size_t)-1 || ret == (size_t)-2) {
-	    /* This handles a '\0' in the input (which is a real char
-	     * to us, not a terminator) and byte values that aren't
-	     * valid wide-character sequences. */
+	switch (cnt) {
+	case MB_INCOMPLETE:
+	    eol = 1;
+	    /* FALL THROUGH */
+	case MB_INVALID:
+	    /* This handles byte values that aren't valid wide-character
+	     * sequences. */
 	    sptr = nicechar(STOUC(*uptr));
 	    /* everything here is ASCII... */
 	    width = strlen(sptr);
 	    wptr = sptr + width;
-	    ret = 1;
-	    /* Get ps out of its undefined state when ret < 0. */
-	    memset(&ps, 0, sizeof ps);
-	} else
+	    cnt = 1;
+	    /* Get mbs out of its undefined state. */
+	    memset(&mbs, 0, sizeof mbs);
+	    break;
+	case 0:
+	    /* This handles a '\0' in the input (which is a real char
+	     * to us, not a terminator). */
+	    cnt = 1;
+	    /* FALL THROUGH */
+	default:
 	    sptr = wcs_nicechar(cc, &width, &wptr);
+	    break;
+	}
 
-	umleft -= ret;
-	uptr += ret;
+	umleft -= cnt;
+	uptr += cnt;
 	if (colors) {
 	    /*
 	     * The code for the colo[u]ri[s/z]ation is obscure (surprised?)
 	     * but if we do it for every input character, as we do in
 	     * the simple case, we shouldn't go too far wrong.
 	     */
-	    while (ret--)
+	    while (cnt--)
 		doiscol(colors, i++);
 	}
 
--- Src/Zle/compmatch.c	9 Jan 2006 17:39:44 -0000	1.47
+++ Src/Zle/compmatch.c	12 Jan 2006 00:51:51 -0000	1.48
@@ -1587,7 +1587,7 @@ sub_match(Cmdata md, char *str, int len,
 #ifdef MULTIBYTE_SUPPORT
     int fulllen = len;
     char *fullstr = str;
-    mbstate_t ps;
+    mbstate_t mbs;
 #endif
 
     if (sfx) {
@@ -1629,7 +1629,7 @@ sub_match(Cmdata md, char *str, int len,
 	 */
 	q = sfx ? str - l : str + l;
 	if (q != fullstr) {
-	    memset(&ps, 0, sizeof(ps));
+	    memset(&mbs, 0, sizeof mbs);
 	    /*
 	     * Otherwise read characters from the start of the original
 	     * string until we reach or pass the match point.  This
@@ -1645,7 +1645,7 @@ sub_match(Cmdata md, char *str, int len,
 		 * ret must, in fact, be set by the current logic,
 		 * but gcc doesn't realise (at least some versions don't).
 		 */
-		size_t cnt = (size_t)-1;
+		size_t cnt = MB_INVALID;
 		int diff;
 		char *p2;
 
@@ -1655,12 +1655,12 @@ sub_match(Cmdata md, char *str, int len,
 		 */
 		for (p2 = p; p2 < fullstr + fulllen; p2++) {
 		    char curchar = (*p2 == Meta) ? (*++p2 ^ 32) : *p2;
-		    cnt = mbrtowc(&wc, &curchar, 1, &ps);
+		    cnt = mbrtowc(&wc, &curchar, 1, &mbs);
 		    /* Continue while character is incomplete. */
-		    if (cnt != (size_t)-2)
+		    if (cnt != MB_INCOMPLETE)
 			break;
 		}
-		if (cnt == (size_t)-1 || cnt == (size_t)-2) {
+		if (cnt == MB_INVALID || cnt == MB_INCOMPLETE) {
 		    /* not a valid character, give up test */
 		    break;
 		}
--- Src/Zle/zle_main.c	24 Nov 2005 10:25:35 -0000	1.81
+++ Src/Zle/zle_main.c	12 Jan 2006 00:51:51 -0000	1.83
@@ -760,8 +760,8 @@ getrestchar(int inchar)
 {
     char c = inchar;
     wchar_t outchar;
-    int ret, timeout;
-    static mbstate_t ps;
+    int timeout;
+    static mbstate_t mbs;
 
     /*
      * We are guaranteed to set a valid wide last character,
@@ -772,7 +772,7 @@ getrestchar(int inchar)
 
     if (inchar == EOF) {
 	/* End of input, so reset the shift state. */
-	memset(&ps, 0, sizeof(ps));
+	memset(&mbs, 0, sizeof mbs);
 	return lastchar_wide = WEOF;
     }
 
@@ -780,14 +780,17 @@ getrestchar(int inchar)
      * Return may be zero if we have a NULL; handle this like
      * any other character.
      */
-    while ((ret = mbrtowc(&outchar, &c, 1, &ps)) < 0) {
-	if (ret == -1) {
+    while (1) {
+	size_t cnt = mbrtowc(&outchar, &c, 1, &mbs);
+	if (cnt == MB_INVALID) {
 	    /*
 	     * Invalid input.  Hmm, what's the right thing to do here?
 	     */
-	    memset(&ps, 0, sizeof(ps));
+	    memset(&mbs, 0, sizeof mbs);
 	    return lastchar_wide = WEOF;
 	}
+	if (cnt != MB_INCOMPLETE)
+	    break;
 
 	/*
 	 * Always apply KEYTIMEOUT to the remains of the input
@@ -799,7 +802,7 @@ getrestchar(int inchar)
 	/* getbyte deliberately resets lastchar_wide_valid */
 	lastchar_wide_valid = 1;
 	if (inchar == EOF) {
-	    memset(&ps, 0, sizeof(ps));
+	    memset(&mbs, 0, sizeof mbs);
 	    if (timeout)
 	    {
 		/*
--- Src/Zle/zle_refresh.c	9 Jan 2006 00:17:24 -0000	1.43
+++ Src/Zle/zle_refresh.c	12 Jan 2006 00:51:51 -0000	1.44
@@ -1446,6 +1446,7 @@ singlerefresh(ZLE_STRING_T tmpline, int 
 	refreshop = *obuf;	/* pointer to old video buffer */
     int t0,			/* tmp			       */
 	vsiz,			/* size of new video buffer    */
+	eol = 0,		/* has mbrtowc() returned -2?  */
 	nvcs = 0;		/* new video cursor column     */
 #ifdef MULTIBYTE_SUPPORT
     /*
@@ -1455,7 +1456,7 @@ singlerefresh(ZLE_STRING_T tmpline, int 
     ZLE_STRING_T lpwbuf, lpwp;
     char *lpptr,		/* pointer into multibyte lprompt */
 	*lpend;			/* end of multibyte lprompt */
-    mbstate_t ps;		/* shift state */
+    mbstate_t mbs;		/* shift state */
 #endif
 
     nlnct = 1;
@@ -1490,18 +1491,26 @@ singlerefresh(ZLE_STRING_T tmpline, int 
     lpwp = lpwbuf = (ZLE_STRING_T)zalloc((lpend - lpromptbuf)
 					 * sizeof(*lpwbuf));
     /* Reset shift state, maybe. */
-    memset(&ps, '\0', sizeof(ps));
+    memset(&mbs, '\0', sizeof mbs);
     for (lpptr = lpromptbuf; lpptr < lpend; ) {
-	size_t cnt = mbrtowc(lpwp, lpptr, lpend - lpptr, &ps);
-	if (cnt != 0 && cnt != (size_t)-1 && cnt != (size_t)-2) {
-	    /* successfully converted */
-	    lpptr += cnt;
-	    lpwp++;
-	} else {
+	size_t cnt = mbrtowc(lpwp, lpptr, lpend - lpptr, &mbs);
+	switch (cnt) {
+	case MB_INCOMPLETE:
+	    eol = 1;
+	    /* FALL THROUGH */
+	case MB_INVALID:
+	    memset(&mbs, '\0', sizeof mbs);
+	    /* FALL THROUGH */
+	case 0:
 	    /* dunno, try to recover */
 	    lpptr++;
 	    *lpwp++ = ZWC('?');
-	    memset(&ps, '\0', sizeof(ps));
+	    break;
+	default:
+	    /* successfully converted */
+	    lpptr += cnt;
+	    lpwp++;
+	    break;
 	}
     }
     if (lpwp - lpwbuf < lpromptw) {
--- Src/Zle/zle_tricky.c	18 Nov 2005 17:26:10 -0000	1.62
+++ Src/Zle/zle_tricky.c	12 Jan 2006 00:51:53 -0000	1.64
@@ -1911,11 +1911,12 @@ pfxlen(char *s, char *t)
 
 #ifdef MULTIBYTE_SUPPORT
     wchar_t wc;
-    mbstate_t ps;
-    int ret, lasti = 0;
+    mbstate_t mbs;
+    size_t cnt;
+    int lasti = 0;
     char inc;
 
-    memset(&ps, 0, sizeof(mbstate_t));
+    memset(&mbs, 0, sizeof mbs);
     while (*s) {
 	if (*s == Meta) {
 	    if (*t != Meta || t[1] != s[1])
@@ -1933,11 +1934,12 @@ pfxlen(char *s, char *t)
 	    t++;
 	}
 
-	ret = mbrtowc(&wc, &inc, 1, &ps);
-	if (ret == -1) {
+	cnt = mbrtowc(&wc, &inc, 1, &mbs);
+	if (cnt == MB_INVALID) {
 	    /* error */
 	    break;
-	} else if (ret >= 0) {
+	}
+	if (cnt != MB_INCOMPLETE) {
 	    /* successfully found complete character, record position */
 	    lasti = i;
 	}
--- Src/Zle/zle_utils.c	9 Jan 2006 17:58:57 -0000	1.35
+++ Src/Zle/zle_utils.c	12 Jan 2006 01:04:17 -0000	1.36
@@ -235,7 +235,7 @@ stringaszleline(char *instr, int incs, i
     ZLE_STRING_T outstr;
     int ll, sz;
 #ifdef MULTIBYTE_SUPPORT
-    mbstate_t ps;
+    mbstate_t mbs;
 #endif
 
     if (outcs) {
@@ -272,28 +272,26 @@ stringaszleline(char *instr, int incs, i
 	wchar_t *outptr = outstr;
 
 	/* Reset shift state to input complete string */
-	memset(&ps, '\0', sizeof(ps));
+	memset(&mbs, '\0', sizeof mbs);
 
 	while (ll > 0) {
-	    size_t cnt = mbrtowc(outptr, inptr, ll, &ps);
+	    size_t cnt = mbrtowc(outptr, inptr, ll, &mbs);
 
 	    /*
 	     * At this point we don't handle either incomplete (-2) or
 	     * invalid (-1) multibyte sequences.  Use the current length
 	     * and return.
 	     */
-	    if (cnt == (size_t)-1 || cnt == (size_t)-2)
+	    if (cnt == MB_INCOMPLETE || cnt == MB_INVALID)
 		break;
 
-	    /*
-	     * Careful: converting a wide NUL returns zero, but we
-	     * want to treat NULs as regular characters.
-	     * Assume it was represented by a single ASCII NUL;
-	     * certainly true for Unicode and unlikely to be false
-	     * in any non-pathological multibyte representation.
-	     */
-	    if (cnt == 0)
+	    if (cnt == 0) {
+		/* Converting '\0' returns 0, but a '\0' is a real
+		 * character for us, so we should consume 1 byte
+		 * (certainly true for Unicode and unlikely to be false
+		 * in any non-pathological multibyte representation). */
 		cnt = 1;
+	    }
 
 	    if (outcs) {
 		int offs = inptr - instr;
@@ -777,9 +775,9 @@ showmsg(char const *msg)
     ZLE_CHAR_T c;
 #ifdef MULTIBYTE_SUPPORT
     char *umsg;
-    int ulen;
+    int ulen, eol = 0;
     size_t width;
-    mbstate_t ps;
+    mbstate_t mbs;
 #endif
 
     trashzle();
@@ -788,7 +786,7 @@ showmsg(char const *msg)
 #ifdef MULTIBYTE_SUPPORT
     umsg = ztrdup(msg);
     p = unmetafy(umsg, &ulen);
-    memset(&ps, 0, sizeof(ps));
+    memset(&mbs, 0, sizeof mbs);
 
     while (ulen > 0) {
 	char const *n;
@@ -803,21 +801,32 @@ showmsg(char const *msg)
 	    /*
 	     * Extract the next wide character from the multibyte string.
 	     */
-	    size_t ret = mbrtowc(&c, p, ulen, &ps);
+	    size_t cnt = eol ? MB_INVALID : mbrtowc(&c, p, ulen, &mbs);
 
-	    if (ret == 0 || ret == (size_t)-1 || ret == (size_t)-2) {
+	    switch (cnt) {
+	    case MB_INCOMPLETE:
+		eol = 1;
+		/* FALL THROUGH */
+	    case MB_INVALID:
 		/*
 		 * This really shouldn't be happening here, but...
 		 * Treat it as a single byte character; it may get
 		 * prettified.
 		 */
+		memset(&mbs, 0, sizeof mbs);
 		n = nicechar(STOUC(*p));
-		ret = 1;
+		cnt = 1;
 		width = strlen(n);
-	    } else
+		break;
+	    case 0:
+		cnt = 1;
+		/* FALL THROUGH */
+	    default:
 		n = wcs_nicechar(c, &width, NULL);
-	    ulen -= ret;
-	    p += ret;
+		break;
+	    }
+	    ulen -= cnt;
+	    p += cnt;
 
 	    zputs(n, shout);
 	    cc += width;
