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

Re: Fun redraw issue with double-width characters



On Sun, 24 Oct 2010 14:11:08 +0200
Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
> I got a random thought, "what if i enter five doublewidth characters,
> then go back to the start and enter a bunch of spaces". Turns out
> doing that causes the line to clear and cursor to move up one line.
> Doesn't happen with four or less.

I think that may depend on what you're inserting: if you're inserting
stuff such that the character you're inserting changes the line near
the start, it may happen early.   But this may be a wild goose chase.

> Long story short, it happens only if
> ich1 is defined in the terminfo for the current $TERM, which it
> happens to be for rxvt-unicode, but also for rxvt. It doesn't matter
> if you're using xterm or rxvt or urxvt, just set TERM=rxvt, enter five
> ã and go back to the start and hold down space. I don't really know
> where to begin debugging this.

Actually, there's only one use of insert in the entire source, which is
in a quite short chunk in zle_refresh.c, so localising it was the easy
bit.

After staring enough I think I've worked out what's going on, but you
might want to stare at it, too.  Much of this is reformatting for
clarity, the important bit is near the end where I've moved an extra
chunk inside an #ifdef MULTIBYTE_SUPPORT with a new comment.

Index: Src/Zle/zle_refresh.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v
retrieving revision 1.81
diff -p -u -r1.81 zle_refresh.c
--- Src/Zle/zle_refresh.c	17 Oct 2010 17:59:27 -0000	1.81
+++ Src/Zle/zle_refresh.c	24 Oct 2010 18:06:22 -0000
@@ -2000,7 +2000,7 @@ refreshline(int ln)
 		   newline: foobar	 / characters, then we have six matches */
 		if (tccan(TCDEL)) {
 		    int first = 1;
-		    for (i = 1; ol[i].chr; i++)
+		    for (i = 1; ol[i].chr; i++) {
 			if (tcdelcost(i) < wpfxlen(ol + i, nl)) {
 			    /*
 			     * Some terminals will output the current
@@ -2023,15 +2023,19 @@ refreshline(int ln)
 			    i = 0;
 			    break;
 			}
+		    }
 		    if (!i)
 			continue;
 		}
-		/* inserting characters - characters pushed off the right should be
-		   annihilated, but we don't do this if we're on the last line lest
-		   undesired scrolling occurs due to `illegal' characters on screen */
-
-		if (tccan(TCINS) && (vln != lines - 1)) {	/* not on last line */
-		    for (i = 1; nl[i].chr; i++)
+		/*
+		 * inserting characters - characters pushed off the right
+		 * should be annihilated, but we don't do this if we're on the
+		 * last line lest undesired scrolling occurs due to `illegal'
+		 * characters on screen
+		 */ 
+		if (tccan(TCINS) && (vln != lines - 1)) {
+		    /* not on last line */
+		    for (i = 1; nl[i].chr; i++) {
 			if (tcinscost(i) < wpfxlen(ol, nl + i)) {
 			    tc_inschars(i);
 			    zwrite(nl, i);
@@ -2044,19 +2048,37 @@ refreshline(int ln)
 #endif
 			    char_ins += i;
 			    ccs = (vcs += i);
-			    /* if we've pushed off the right, truncate oldline */
-			    for (i = 0; ol[i].chr && i < winw - ccs; i++);
+			    /*
+			     * if we've pushed off the right, truncate
+			     * oldline
+			     */
+			    for (i = 0; ol[i].chr && i < winw - ccs; i++)
+				;
 #ifdef MULTIBYTE_SUPPORT
 			    while (ol[i].chr == WEOF)
 				i++;
-#endif
 			    if (i >= winw - ccs) {
+				/*
+				 * Yes, we're over the right.
+				 * Make sure we truncate at the real
+				 * character, not a WEOF added to
+				 * make up the width.
+				 */
+				while (ol[i-1].chr == WEOF)
+				    i--;
 				ol[i] = zr_zr;
 				ins_last = 1;
 			    }
+#else
+			    if (i >= winw - ccs) {
+				ol[i] = zr_zr;
+				ins_last = 1;
+			    }
+#endif
 			    i = 0;
 			    break;
 			}
+		    }
 		    if (!i)
 			continue;
 		}

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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