summary refs log tree commit diff
path: root/Src/Zle/zle_utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2005-09-29 17:32:34 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2005-09-29 17:32:34 +0000
commit046f4cf49e1a082f78b0acadadae8855db5cb37e (patch)
tree1c4191795ecab9f349cadb17f9c60102ec1809e6 /Src/Zle/zle_utils.c
parent6183db6faa0815f09267062769c602a1de3d9e81 (diff)
downloadzsh-046f4cf49e1a082f78b0acadadae8855db5cb37e.tar.gz
zsh-046f4cf49e1a082f78b0acadadae8855db5cb37e.tar.xz
zsh-046f4cf49e1a082f78b0acadadae8855db5cb37e.zip
21784: Improved character widths for formatted multibyte character output
Diffstat (limited to 'Src/Zle/zle_utils.c')
-rw-r--r--Src/Zle/zle_utils.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 2e358f489..cfc77de27 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -769,19 +769,75 @@ printbind(char *str, FILE *stream)
     return ret;
 }
 
-/* Display a message where the completion list normally goes. *
- * The message must be metafied.                              */
+/*
+ * Display a message where the completion list normally goes.
+ * The message must be metafied.
+ *
+ * TODO: there's some advantage in using a ZLE_STRING_T array here,
+ * together with improvements in other places, but messages don't
+ * need to be particularly efficient.
+ */
 
 /**/
 mod_export void
 showmsg(char const *msg)
 {
     char const *p;
-    int up = 0, cc = 0, c;
+    int up = 0, cc = 0;
+    ZLE_CHAR_T c;
+#ifdef ZLE_UNICODE_SUPPORT
+    char *umsg;
+    int ulen, ret, width;
+    mbstate_t ps;
+#endif
 
     trashzle();
     clearflag = isset(USEZLE) && !termflags && isset(ALWAYSLASTPROMPT);
 
+#ifdef ZLE_UNICODE_SUPPORT
+    umsg = ztrdup(msg);
+    p = unmetafy(umsg, &ulen);
+    memset(&ps, 0, sizeof(ps));
+
+    while (ulen > 0) {
+	char const *n;
+	if (*p == '\n') {
+	    ulen--;
+	    p++;
+
+	    putc('\n', shout);
+	    up += 1 + cc / columns;
+	    cc = 0;
+	} else {
+	    /*
+	     * Extract the next wide character from the multibyte string.
+	     */
+	    ret = mbrtowc(&c, p, ulen, &ps);
+
+	    if (ret <= 0) {
+		/*
+		 * This really shouldn't be happening here, but...
+		 * Treat it as a single byte character; it may get
+		 * prettified.
+		 */
+		n = nicechar(*p);
+		ret = 1;
+		width = strlen(n);
+	    }
+	    else
+	    {
+		n = wcs_nicechar(c, &width, NULL);
+	    }
+	    ulen -= ret;
+	    p += ret;
+
+	    zputs(n, shout);
+	    cc += width;
+	}
+    }
+
+    free(umsg);
+#else
     for(p = msg; (c = *p); p++) {
 	if(c == Meta)
 	    c = *++p ^ 32;
@@ -791,10 +847,11 @@ showmsg(char const *msg)
 	    cc = 0;
 	} else {
 	    char const *n = nicechar(c);
-	    fputs(n, shout);
+	    zputs(n, shout);
 	    cc += strlen(n);
 	}
     }
+#endif
     up += cc / columns;
 
     if (clearflag) {