about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-01-22 10:14:01 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-01-22 10:14:01 +0000
commit088e8a9c8d19d0675bde3fabdde1b1e35129725b (patch)
tree0fadfdafe4b88d9cff83a5d74eb58778f60fd0ee
parenta199833e23147036edfcddfc3ab2752c7c20a686 (diff)
downloadzsh-088e8a9c8d19d0675bde3fabdde1b1e35129725b.tar.gz
zsh-088e8a9c8d19d0675bde3fabdde1b1e35129725b.tar.xz
zsh-088e8a9c8d19d0675bde3fabdde1b1e35129725b.zip
24434: handle unprintable and zero-width wide characters
by displaying as hex
-rw-r--r--ChangeLog5
-rw-r--r--Src/Zle/zle_refresh.c50
2 files changed, 50 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index c5839bba9..42e341db7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2008-01-22  Peter Stephenson  <pws@csr.com>
+
+	* 24434: Src/Zle/zle_refresh.c: handle unprintable and zero-width
+	wide characters on the command line by displaying as hex.
+
 2008-01-22  Clint Adams  <clint@zsh.org>
 
 	* 24429: configure.ac, Etc/zsh-development-guide:
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index cdda42287..3f3de2c68 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -447,6 +447,10 @@ zrefresh(void)
     int tmpalloced;		/* flag to free tmpline when finished        */
     int remetafy;		/* flag that zle line is metafied            */
     struct rparams rpms;
+#ifdef MULTIBYTE_SUPPORT
+    int width;                  /* width of wide character                   */
+#endif
+
     
     /* If this is called from listmatches() (indirectly via trashzle()), and *
      * that was called from the end of zrefresh(), then we don't need to do  *
@@ -633,8 +637,7 @@ zrefresh(void)
 		while ((++t0) & 7);
 	}
 #ifdef MULTIBYTE_SUPPORT
-	else if (iswprint(*t)) {
-	    int width = wcwidth(*t);
+	else if (iswprint(*t) && (width = wcwidth(*t)) > 0) {
 	    if (width > rpms.sen - rpms.s) {
 		/*
 		 * Too wide to fit.  Insert spaces to end of current line.
@@ -649,7 +652,7 @@ zrefresh(void)
 		    rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln];
 		}
 	    }
-	    if (width > rpms.sen - rpms.s) {
+	    if (width > rpms.sen - rpms.s || width == 0) {
 		/*
 		 * The screen width is too small to fit even one
 		 * occurrence.
@@ -663,7 +666,11 @@ zrefresh(void)
 	    }
 	}
 #endif
-	else if (ZC_icntrl(*t)) {	/* other control character */
+	else if (ZC_icntrl(*t)
+#ifdef MULTIBYTE_SUPPORT
+		 && (unsigned)*t <= 0xffU
+#endif
+	    ) {	/* other control character */
 	    *rpms.s++ = ZWC('^');
 	    if (rpms.s == rpms.sen) {
 		/* text wrapped */
@@ -671,9 +678,42 @@ zrefresh(void)
 		    break;
 	    }
 	    *rpms.s++ = (((unsigned int)*t & ~0x80u) > 31) ? ZWC('?') : (*t | ZWC('@'));
-	} else {			/* normal character */
+	}
+#ifdef MULTIBYTE_SUPPORT
+	else {
+	    /*
+	     * Not printable or zero width.
+	     * Resort to hackery.
+	     */
+	    char dispchars[11];
+	    char *dispptr = dispchars;
+	    wchar_t wc;
+
+	    if ((unsigned)*t > 0xffffU) {
+		sprintf(dispchars, "<%.08x>", (unsigned)*t);
+	    } else {
+		sprintf(dispchars, "<%.04x>", (unsigned)*t);
+	    }
+	    while (*dispptr) {
+		if (mbtowc(&wc, dispptr, 1) == 1 /* paranoia */)
+		{
+		    *rpms.s++ = wc;
+		    if (rpms.s == rpms.sen) {
+			/* text wrapped */
+			if (nextline(&rpms, 1))
+			    break;
+		    }
+		}
+		dispptr++;
+	    }
+	    if (*dispptr) /* nextline said stop processing */
+		break;
+	}
+#else
+	else {			/* normal character */
 	    *rpms.s++ = *t;
 	}
+#endif
 	if (rpms.s == rpms.sen) {
 	    /* text wrapped */
 	    if (nextline(&rpms, 1))