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

Mikael Magnusson <[email protected]>
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.