Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: fix for ctrl-r with combining characters or nonprintable wide chars



Typing one of these characters in isearch caused the terminal cursor to
jump to the wrong row, and various other problems, because we totally
lost track of things.

Make use of addmultiword() to draw the combining characters, analogously
to how the main input line does it. This resolves ccs/vcs getting out of
sync with the display, because there are no top level glyphs of zero
width anymore.

The code seems to simply have forgotten about nonprintable wide
characters that weren't ascii control characters, so handle those like
in the main line redraw code.

I didn't bother handling the ZSH_INVALID_WCHAR range because I don't see
how you could possibly insert one of those in the isearch buffer. If you
manage to do this, congratulations.
---

Issue originally reported in 27474.

 Src/Zle/zle_refresh.c | 93 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 75 insertions(+), 18 deletions(-)

diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 3881821c46..8c2a645df4 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1437,26 +1437,60 @@ zrefresh(void)
 #ifdef MULTIBYTE_SUPPORT
 	    if (WC_ISPRINT(*u)) {
 		int width = WCWIDTH(*u);
-		/* Handle wide characters as above */
-		if (width > rpms.sen - rpms.s) {
-		    do {
-			*rpms.s++ = zr_sp;
-		    } while (rpms.s < rpms.sen);
-		    nbuf[rpms.ln][winw + 1] = zr_nl;
-		    snextline(&rpms);
-		}
-		if (width > rpms.sen - rpms.s) {
-		    rpms.s->chr = ZWC('?');
-		    rpms.s->atr = all_attr;
-		    rpms.s++;
-		} else {
-		    rpms.s->chr = *u;
-		    rpms.s->atr = 0;
-		    rpms.s++;
-		    while (--width > 0) {
-			rpms.s->chr = WEOF;
+		if (width > 0) {
+		    int ichars = 1;
+		    if (isset(COMBININGCHARS) && IS_BASECHAR(*u)) {
+			for (ichars = 1; u + ichars < outputline + outll; ichars++)
+			    if (!IS_COMBINING(u[ichars]))
+				break;
+		    }
+		    /* Handle wide characters as above */
+		    if (width > rpms.sen - rpms.s) {
+			do {
+			    *rpms.s++ = zr_sp;
+			} while (rpms.s < rpms.sen);
+			nbuf[rpms.ln][winw + 1] = zr_nl;
+			snextline(&rpms);
+		    }
+		    if (width > rpms.sen - rpms.s) {
+			rpms.s->chr = ZWC('?');
+			rpms.s->atr = all_attr;
+			rpms.s++;
+		    } else {
 			rpms.s->atr = 0;
+			if (ichars > 1)
+			    addmultiword(rpms.s, u, ichars);
+			else
+			    rpms.s->chr = *u;
 			rpms.s++;
+			while (--width > 0) {
+			    rpms.s->chr = WEOF;
+			    rpms.s->atr = 0;
+			    rpms.s++;
+			}
+		    }
+		    u += ichars - 1;
+		} else {
+		    /* either the COMBINING_CHARS option is off,
+		       or there was no base character, then render as special */
+		    char dispchars[11];
+		    char *dispptr = dispchars;
+		    wchar_t wc;
+		    if ((unsigned)*u > 0xffffU)
+			sprintf(dispchars, "<%.08x>", (unsigned)*u);
+		    else
+			sprintf(dispchars, "<%.04x>", (unsigned)*u);
+		    while (*dispptr) {
+			if (mbtowc(&wc, dispptr, 1) == 1) {
+			    rpms.s->chr = wc;
+			    rpms.s->atr = all_attr;
+			    rpms.s++;
+			    if (rpms.s == rpms.sen) {
+				nbuf[rpms.ln][winw + 1] = zr_nl;
+				snextline(&rpms);
+			    }
+			}
+			dispptr++;
 		    }
 		}
 	    }
@@ -1475,9 +1509,32 @@ zrefresh(void)
 		rpms.s->atr = all_attr;
 		rpms.s++;
 	    } else {
+#ifdef MULTIBYTE_SUPPORT
+		/* non-printable wide char */
+		char dispchars[11];
+		char *dispptr = dispchars;
+		wchar_t wc;
+		if ((unsigned)*u > 0xffffU)
+		    sprintf(dispchars, "<%.08x>", (unsigned)*u);
+		else
+		    sprintf(dispchars, "<%.04x>", (unsigned)*u);
+		while (*dispptr) {
+		    if (mbtowc(&wc, dispptr, 1) == 1) {
+			rpms.s->chr = wc;
+			rpms.s->atr = all_attr;
+			rpms.s++;
+			if (rpms.s == rpms.sen) {
+			    nbuf[rpms.ln][winw + 1] = zr_nl;
+			    snextline(&rpms);
+			}
+		    }
+		    dispptr++;
+		}
+#else
 		rpms.s->chr = *u;
 		rpms.s->atr = 0;
 		rpms.s++;
+#endif
 	    }
 	    if (rpms.s == rpms.sen) {
 		nbuf[rpms.ln][winw + 1] = zr_nl;	/* text wrapped */
-- 
2.38.1





Messages sorted by: Reverse Date, Date, Thread, Author