Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
Re: bin/ksh: series of patches which fixes wrong terminal width and UTF-8
To:
tech@openbsd.org
Date:
Wed, 9 Sep 2026 12:23:01 +0100

Download raw body.

Thread
On 2026/09/09 12:55, Kirill A. Korinsky wrote:
> On Wed, 08 Jul 2026 11:41:07 +0200,
> Stuart Henderson <stu@spacehopper.org> wrote:
> > 
> > On 2026/07/07 22:42, Kirill A. Korinsky wrote:
> > > sorry to attached pathces, and not inlined, I think it makes it review
> > > simpler.
> > > 
> > > I use that pathces for last half year in emacs mode and happy with this, but
> > > I think we should fix that bugs and commit it.
> > > 
> > > It should be applied as sequence.
> > > 
> > > Anyone willing to test it? Ok it?
> > 
> > I'm running this on a few machines now. It's a big improvement so far.
> > 
> 
> I still would like to go this series in.

Me too.

> Here it is as one diff with regression tests.
> 
> I use it for months, and haven't discovered any issues.
> 
> This patch fixes terminal resizes which leaves emacs and vi mode using a
> stale width, causing premature scrolling and incorrect cursor placement;
> UTF-8 input at the window edge also produces broken characters and misplaced
> indicators; in vi mode, multibyte input can overrun the window buffers.
> 
> Anyone willing to ok it?

ok sthen, FWIW

> Index: bin/ksh/edit.c
> ===================================================================
> RCS file: /home/cvs/src/bin/ksh/edit.c,v
> diff -u -p -r1.72 edit.c
> --- bin/ksh/edit.c	22 May 2026 18:11:08 -0000	1.72
> +++ bin/ksh/edit.c	9 Sep 2026 10:44:49 -0000
> @@ -26,7 +26,8 @@ X_chars edchars;
>  
>  static void x_sigwinch(int);
>  volatile sig_atomic_t got_sigwinch;
> -static void check_sigwinch(void);
> +void check_sigwinch(void);
> +void (*x_resize_cb)(void);	/* callback for resize during edit */
>  
>  static int	x_file_glob(int, const char *, int, char ***, int);
>  static char	*x_tilde_expand(const char *);
> @@ -64,7 +65,7 @@ x_sigwinch(int sig)
>  	got_sigwinch = 1;
>  }
>  
> -static void
> +void
>  check_sigwinch(void)
>  {
>  	if (got_sigwinch) {
> @@ -81,11 +82,16 @@ check_sigwinch(void)
>  			 * see the change cause the environ doesn't change.
>  			 */
>  			if (ws.ws_col) {
> +				int old_cols = x_cols;
> +
>  				x_cols = ws.ws_col < MIN_COLS ? MIN_COLS :
>  				    ws.ws_col;
>  
>  				if ((vp = typeset("COLUMNS", 0, 0, 0, 0)))
>  					setint(vp, (int64_t) ws.ws_col);
> +
> +				if (x_cols != old_cols && x_resize_cb)
> +					(*x_resize_cb)();
>  			}
>  			if (ws.ws_row && (vp = typeset("LINES", 0, 0, 0, 0)))
>  				setint(vp, (int64_t) ws.ws_row);
> @@ -126,12 +132,14 @@ x_getc(void)
>  	char c;
>  	int n;
>  
> -	while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR)
> +	while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR) {
> +		check_sigwinch();
>  		if (trap) {
>  			x_mode(false);
>  			runtraps(0);
>  			x_mode(true);
>  		}
> +	}
>  	if (n != 1)
>  		return -1;
>  	return (int) (unsigned char) c;
> Index: bin/ksh/edit.h
> ===================================================================
> RCS file: /home/cvs/src/bin/ksh/edit.h,v
> diff -u -p -r1.14 edit.h
> --- bin/ksh/edit.h	22 May 2026 18:11:08 -0000	1.14
> +++ bin/ksh/edit.h	9 Sep 2026 10:44:49 -0000
> @@ -39,6 +39,8 @@ extern X_chars edchars;
>  #define XCF_COMMAND_FILE (XCF_COMMAND|XCF_FILE)
>  
>  /* edit.c */
> +void	check_sigwinch(void);
> +extern void (*x_resize_cb)(void);
>  int	x_getc(void);
>  void	x_flush(void);
>  int	x_putc(int);
> Index: bin/ksh/emacs.c
> ===================================================================
> RCS file: /home/cvs/src/bin/ksh/emacs.c,v
> diff -u -p -r1.92 emacs.c
> --- bin/ksh/emacs.c	22 May 2026 18:11:08 -0000	1.92
> +++ bin/ksh/emacs.c	9 Sep 2026 10:44:49 -0000
> @@ -105,6 +105,7 @@ static int	xlp_valid;
>  /* end from 4.9 edit.h } */
>  static	int	x_tty;		/* are we on a tty? */
>  static	int	x_bind_quiet;	/* be quiet when binding keys */
> +static void	x_emacs_resize(void);
>  static int	(*x_last_command)(int);
>  
>  static	char   **x_histp;	/* history position */
> @@ -129,6 +130,7 @@ static int	x_size_str(char *);
>  static int	x_size(int);
>  static void	x_zots(char *);
>  static void	x_zotc(int);
> +static void	x_zotcp(char *);
>  static void	x_load_hist(char **);
>  static int	x_search(char *, int, int);
>  static int	x_match(char *, char *);
> @@ -286,6 +288,9 @@ x_emacs(char *buf, size_t len)
>  	xmp = NULL;
>  	x_histp = histptr + 1;
>  
> +	x_resize_cb = NULL;
> +	check_sigwinch();
> +	x_resize_cb = x_emacs_resize;
>  	xx_cols = x_cols;
>  	x_col = promptlen(prompt, &p);
>  	prompt_skip = p - prompt;
> @@ -316,8 +321,11 @@ x_emacs(char *buf, size_t len)
>  	x_last_command = NULL;
>  	while (1) {
>  		x_flush();
> -		if ((at = x_e_getu8(line, at)) < 0)
> +		if ((at = x_e_getu8(line, at)) < 0) {
> +			x_resize_cb = NULL;
>  			return 0;
> +		}
> +
>  		ntries++;
>  
>  		if (x_arg == -1) {
> @@ -378,6 +386,7 @@ x_emacs(char *buf, size_t len)
>  				x_last_command = NULL;
>  			break;
>  		case KEOL:
> +			x_resize_cb = NULL;
>  			ret = xep - xbuf;
>  			return (ret);
>  			break;
> @@ -635,16 +644,17 @@ x_fword(void)
>  static void
>  x_goto(char *cp)
>  {
> -	if (cp < xbp || cp >= (xbp + x_displen)) {
> +	x_lastcp();
> +	if (cp < xbp || cp > xlp) {
>  		/* we are heading off screen */
>  		xcp = cp;
>  		x_adjust();
>  	} else if (cp < xcp) {		/* move back */
>  		while (cp < xcp)
> -			x_bs((unsigned char)*--xcp);
> +			x_bs(*--xcp);
>  	} else if (cp > xcp) {		/* move forward */
>  		while (cp > xcp)
> -			x_zotc((unsigned char)*xcp++);
> +			x_zotcp(xcp++);
>  	}
>  }
>  
> @@ -663,7 +673,7 @@ x_size_str(char *cp)
>  {
>  	int size = 0;
>  	while (*cp)
> -		size += x_size(*cp++);
> +		size += x_size((unsigned char)*cp++);
>  	return size;
>  }
>  
> @@ -691,7 +701,7 @@ x_zots(char *str)
>  	}
>  	x_lastcp();
>  	while (*str && str < xlp && adj == x_adj_done)
> -		x_zotc(*str++);
> +		x_zotcp(str++);
>  }
>  
>  static void
> @@ -707,6 +717,39 @@ x_zotc(int c)
>  		x_e_putc(c);
>  }
>  
> +static void
> +x_zotcp(char *p)
> +{
> +	unsigned char uc = (unsigned char)*p;
> +
> +	if (uc == '\t') {
> +		/*  Kludge, tabs are always four spaces.  */
> +		x_e_puts("    ");
> +		return;
> +	}
> +	if (isu8cont(uc)) {
> +		if (x_col <= xx_cols) {
> +			x_putc(uc);
> +		}
> +		if (x_adj_ok && !isu8cont((unsigned char)p[1]) &&
> +		    (x_col < 0 || x_col >= (xx_cols - 2)))
> +			x_adjust();
> +		return;
> +	}
> +	if (iscntrl(uc)) {
> +		x_e_putc('^');
> +		x_e_putc(UNCTRL(uc));
> +	} else {
> +		if (x_col < xx_cols) {
> +			x_putc(uc);
> +			x_col++;
> +		}
> +		if (x_adj_ok && !isu8cont((unsigned char)p[1]) &&
> +		    (x_col < 0 || x_col >= (xx_cols - 2)))
> +			x_adjust();
> +	}
> +}
> +
>  static int
>  x_mv_back(int c)
>  {
> @@ -1026,7 +1069,7 @@ x_clear_screen(int c)
>  static void
>  x_redraw(int limit)
>  {
> -	int	i, j, truncate = 0;
> +	int	i, j, truncate = 0, dcols;
>  	char	*cp;
>  
>  	x_adj_ok = 0;
> @@ -1068,10 +1111,12 @@ x_redraw(int limit)
>  	if (xbp != xbuf || xep > xlp)
>  		limit = xx_cols;
>  	if (limit >= 0) {
> -		if (xep > xlp)
> -			i = 0;			/* we fill the line */
> -		else
> -			i = limit - (xlp - xbp);
> +		dcols = 0;
> +		for (cp = xbp; cp < xlp; cp++)
> +			dcols += x_size((unsigned char)*cp);
> +		i = limit - dcols;
> +		if (i < 0)
> +			i = 0;
>  
>  		for (j = 0; j < i && x_col < (xx_cols - 2); j++)
>  			x_e_putc(' ');
> @@ -1128,8 +1173,8 @@ x_transpose(int c)
>  		 */
>  		x_bs(xcp[-1]);
>  		x_bs(xcp[-2]);
> -		x_zotc(xcp[-1]);
> -		x_zotc(xcp[-2]);
> +		x_zotcp(&xcp[-1]);
> +		x_zotcp(&xcp[-2]);
>  		tmp = xcp[-1];
>  		xcp[-1] = xcp[-2];
>  		xcp[-2] = tmp;
> @@ -1138,8 +1183,8 @@ x_transpose(int c)
>  		 * cursor, move cursor position along one.
>  		 */
>  		x_bs(xcp[-1]);
> -		x_zotc(xcp[0]);
> -		x_zotc(xcp[-1]);
> +		x_zotcp(&xcp[0]);
> +		x_zotcp(&xcp[-1]);
>  		tmp = xcp[-1];
>  		xcp[-1] = xcp[0];
>  		xcp[0] = tmp;
> @@ -1802,12 +1847,22 @@ do_complete(int flags,	/* XCF_{COMMAND,F
>  static void
>  x_adjust(void)
>  {
> +	char *cp;
> +	int col;
> +
>  	x_adj_done++;			/* flag the fact that we were called. */
>  	/*
>  	 * we had a problem if the prompt length > xx_cols / 2
>  	 */
> -	if ((xbp = xcp - (x_displen / 2)) < xbuf)
> -		xbp = xbuf;
> +	col = x_displen / 2;
> +	cp = xcp;
> +	while (cp > xbuf && col > 0) {
> +		cp--;
> +		while (cp > xbuf && isu8cont(*cp))
> +			cp--;
> +		col -= x_size((unsigned char)*cp);
> +	}
> +	xbp = cp;
>  	xlp_valid = false;
>  	x_redraw(xx_cols);
>  	x_flush();
> @@ -2161,9 +2216,58 @@ x_lastcp(void)
>  		for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++)
>  			i += x_size((unsigned char)*rcp);
>  		xlp = rcp;
> +		while (xlp < xep && isu8cont(*xlp))
> +			xlp++;
>  	}
>  	xlp_valid = true;
>  	return (xlp);
> +}
> +
> +static void
> +x_emacs_resize(void)
> +{
> +	int cr_done = 0, cleared = 0;
> +
> +#ifndef SMALL
> +	if (cur_term != NULL) {
> +		if (carriage_return != NULL &&
> +		    tputs(carriage_return, 1, x_putc) != ERR)
> +			cr_done = 1;
> +		if (clr_eos != NULL &&
> +		    tputs(clr_eos, 1, x_putc) != ERR)
> +			cleared = 1;
> +	}
> +#endif
> +	if (!cr_done)
> +		x_putc('\r');
> +	if (!cleared) {
> +		x_putc('\033');
> +		x_putc('[');
> +		x_putc('J');
> +	}
> +
> +	xx_cols = x_cols;
> +	x_col = promptlen(prompt, NULL);
> +	if (x_col > xx_cols)
> +		x_col = x_col - (x_col / xx_cols) * xx_cols;
> +	x_displen = xx_cols - 2 - x_col;
> +	if (x_displen < 1) {
> +		x_col = 0;
> +		x_displen = xx_cols - 2;
> +		prompt_redraw = 0;
> +	} else {
> +		xbp = xbuf;
> +		xlp_valid = false;
> +		if (xcp <= x_lastcp()) {
> +			x_redraw(0);
> +			x_flush();
> +			return;
> +		}
> +	}
> +
> +	x_col = 0;
> +	x_displen = xx_cols - 2;
> +	x_adjust();
>  }
>  
>  #endif /* EMACS */
> Index: bin/ksh/vi.c
> ===================================================================
> RCS file: /home/cvs/src/bin/ksh/vi.c,v
> diff -u -p -r1.71 vi.c
> --- bin/ksh/vi.c	15 Aug 2026 11:54:18 -0000	1.71
> +++ bin/ksh/vi.c	9 Sep 2026 10:44:49 -0000
> @@ -24,6 +24,7 @@
>  
>  #undef CTRL
>  #define	CTRL(x)		((x) & 0x1F)	/* ASCII */
> +#define UTF8_MAXBYTES	4
>  
>  struct edstate {
>  	char	*cbuf;		/* main buffer to build the command line */
> @@ -75,6 +76,8 @@ static void	vi_error(void);
>  static void	vi_macro_reset(void);
>  static int	x_vi_putbuf(const char *, size_t);
>  static int	isu8cont(unsigned char);
> +static void	x_vi_resize(void);
> +static void	calc_winsize(void);
>  
>  #define C_	0x1		/* a valid command that isn't a M_, E_, U_ */
>  #define M_	0x2		/* movement command (h, l, etc.) */
> @@ -200,6 +203,9 @@ x_vi(char *buf, size_t len)
>  {
>  	int	c;
>  
> +	x_resize_cb = NULL;
> +	check_sigwinch();
> +	x_resize_cb = x_vi_resize;
>  	vi_reset(buf, len > LINE ? LINE : len);
>  	vi_pprompt(1);
>  	x_flush();
> @@ -242,6 +248,7 @@ x_vi(char *buf, size_t len)
>  		x_flush();
>  	}
>  
> +	x_resize_cb = NULL;
>  	x_putc('\r'); x_putc('\n'); x_flush();
>  
>  	if (c == -1 || len <= (size_t)es->linelen)
> @@ -1363,7 +1370,7 @@ static int	prompt_trunc;		/* how much of
>  static int	prompt_skip;		/* how much of prompt to skip */
>  static int	winwidth;		/* available column positions */
>  static char	*wbuf[2];		/* current & previous window buffer */
> -static int	wbuf_len;		/* length of window buffers (x_cols-3)*/
> +static int	wbuf_len;		/* length of window buffers */
>  static int	win;			/* number of window buffer in use */
>  static char	morec;			/* more character at right of window */
>  static char	holdbuf[LINE];		/* place to hold last edit buffer */
> @@ -1423,8 +1430,6 @@ free_edstate(struct edstate *old)
>  static void
>  edit_reset(char *buf, size_t len)
>  {
> -	const char *p;
> -
>  	es = &ebuf;
>  	es->cbuf = buf;
>  	es->cbufsize = len;
> @@ -1435,6 +1440,18 @@ edit_reset(char *buf, size_t len)
>  	es->cursor = undo->cursor = 0;
>  	es->winleft = undo->winleft = 0;
>  
> +	calc_winsize();
> +	win = 0;
> +	morec = ' ';
> +	holdlen = 0;
> +}
> +
> +static void
> +calc_winsize(void)
> +{
> +	const char *p;
> +	int newlen;
> +
>  	cur_col = pwidth = promptlen(prompt, &p);
>  	prompt_skip = p - prompt;
>  	if (pwidth > x_cols - 3 - MIN_EDIT_SPACE) {
> @@ -1443,17 +1460,15 @@ edit_reset(char *buf, size_t len)
>  		pwidth -= prompt_trunc;
>  	} else
>  		prompt_trunc = 0;
> -	if (!wbuf_len || wbuf_len != x_cols - 3) {
> -		wbuf_len = x_cols - 3;
> +	newlen = (x_cols - 3) * UTF8_MAXBYTES;
> +	if (!wbuf_len || wbuf_len != newlen) {
> +		wbuf_len = newlen;
>  		wbuf[0] = aresize(wbuf[0], wbuf_len, APERM);
>  		wbuf[1] = aresize(wbuf[1], wbuf_len, APERM);
>  	}
>  	(void) memset(wbuf[0], ' ', wbuf_len);
>  	(void) memset(wbuf[1], ' ', wbuf_len);
>  	winwidth = x_cols - pwidth - 3;
> -	win = 0;
> -	morec = ' ';
> -	holdlen = 0;
>  }
>  
>  /*
> @@ -1870,6 +1885,7 @@ display(char *wb1, char *wb2, int leftsi
>  	int	 ncol;	/* display column of the cursor */
>  	int	 cnt;	/* remaining display columns to fill */
>  	int	 moreright;
> +	int	 trailu8;
>  	char	 mc;	/* new "more character" at the right of window */
>  	unsigned char ch;
>  
> @@ -1881,8 +1897,11 @@ display(char *wb1, char *wb2, int leftsi
>  	ncol = col = 0;
>  	cur = es->winleft;
>  	moreright = 0;
> +	trailu8 = 0;
>  	twb1 = wb1;
> -	while (col < winwidth && cur < es->linelen) {
> +	while (cur < es->linelen &&
> +	    (col < winwidth ||
> +	    (col == winwidth && isu8cont(es->cbuf[cur])))) {
>  		if (cur == es->cursor && leftside)
>  			ncol = col + pwidth;
>  		if ((ch = es->cbuf[cur]) == '\t') {
> @@ -1898,7 +1917,8 @@ display(char *wb1, char *wb2, int leftsi
>  				}
>  				ch &= 0x7f;
>  			}
> -			if (col < winwidth) {
> +			if (col < winwidth ||
> +			    (col == winwidth && isu8cont(ch))) {
>  				if (ch < ' ' || ch == 0x7f) {
>  					*twb1++ = '^';
>  					if (++col < winwidth) {
> @@ -1906,6 +1926,8 @@ display(char *wb1, char *wb2, int leftsi
>  						col++;
>  					}
>  				} else {
> +					if (col == winwidth && isu8cont(ch))
> +						trailu8 = 1;
>  					*twb1++ = ch;
>  					if (col == 0 || !isu8cont(ch))
>  						col++;
> @@ -1998,8 +2020,10 @@ display(char *wb1, char *wb2, int leftsi
>  		mc = '>';
>  	else
>  		mc = ' ';
> -	if (mc != morec) {
> -		ed_mov_opt(pwidth + winwidth + 1, wb1);
> +	if (mc != morec || trailu8) {
> +		ed_mov_opt(pwidth + winwidth, wb1);
> +		x_putc(' ');
> +		cur_col++;
>  		x_putc(mc);
>  		cur_col++;
>  		morec = mc;
> @@ -2302,5 +2326,43 @@ static int
>  isu8cont(unsigned char c)
>  {
>  	return !Flag(FVISHOW8) && (c & (0x80 | 0x40)) == 0x80;
> +}
> +
> +static void
> +x_vi_resize(void)
> +{
> +	int cur = 0, col = 0;
> +	int cr_done = 0, cleared = 0;
> +
> +#ifndef SMALL
> +	if (cur_term != NULL) {
> +		if (carriage_return != NULL &&
> +		    tputs(carriage_return, 1, x_putc) != ERR)
> +			cr_done = 1;
> +		if (clr_eos != NULL &&
> +		    tputs(clr_eos, 1, x_putc) != ERR)
> +			cleared = 1;
> +	}
> +#endif
> +	if (!cr_done)
> +		x_putc('\r');
> +	if (!cleared) {
> +		x_putc('\033');
> +		x_putc('[');
> +		x_putc('J');
> +	}
> +
> +	calc_winsize();
> +
> +	while (cur < es->linelen)
> +		col = newcol((unsigned char) es->cbuf[cur++], col);
> +	if (col <= winwidth)
> +		es->winleft = 0;
> +	else if (outofwin())
> +		rewindow();
> +
> +	redraw_line(0, 0);
> +	refresh_line(insert != 0);
> +	x_flush();
>  }
>  #endif	/* VI */
> Index: regress/bin/ksh/edit/edit.c
> ===================================================================
> RCS file: /home/cvs/src/regress/bin/ksh/edit/edit.c,v
> diff -u -p -r1.8 edit.c
> --- regress/bin/ksh/edit/edit.c	10 Jul 2021 07:10:31 -0000	1.8
> +++ regress/bin/ksh/edit/edit.c	9 Sep 2026 10:44:49 -0000
> @@ -16,6 +16,7 @@
>   */
>  
>  #include <sys/wait.h>
> +#include <sys/ioctl.h>
>  
>  #include <err.h>
>  #include <errno.h>
> @@ -49,6 +50,7 @@ main(int argc, char *argv[])
>  	ssize_t		 n;
>  	size_t		 nin, nprompt, nread, nwrite;
>  	int		 c, nready, ptyfd, readprompt, ret, status, timeout;
> +	int		 pending_resize, pending_cols, pending_quiet, pending_post;
>  
>  	while ((c = getopt(argc, argv, "p:")) != -1) {
>  		switch (c) {
> @@ -96,14 +98,20 @@ main(int argc, char *argv[])
>  	}
>  
>  	nprompt = nread = nwrite = ret = 0;
> +	pending_resize = pending_cols = pending_quiet = pending_post = 0;
>  	readprompt = 1;
>  	while (!gotsig) {
>  		pfd.fd = ptyfd;
> -		if (!readprompt && nwrite < nin)
> +		if (pending_resize || pending_post) {
> +			pfd.events = POLLIN;
> +			timeout = WRTIM;
> +		} else if (!readprompt && nwrite < nin) {
>  			pfd.events = POLLOUT;
> -		else
> +			timeout = WRTIM;
> +		} else {
>  			pfd.events = POLLIN;
> -		timeout = readprompt ? PRTIM : WRTIM;
> +			timeout = readprompt ? PRTIM : WRTIM;
> +		}
>  		nready = poll(&pfd, 1, timeout);
>  		if (nready == -1) {
>  			if (errno == EINTR)
> @@ -111,6 +119,22 @@ main(int argc, char *argv[])
>  			err(1, "poll");
>  		}
>  		if (nready == 0) {
> +			if (pending_resize) {
> +				if (++pending_quiet >= 2) {
> +					ws.ws_col = pending_cols;
> +					if (ioctl(ptyfd, TIOCSWINSZ, &ws) == -1)
> +						err(1, "ioctl TIOCSWINSZ");
> +					kill(pid, SIGWINCH);
> +					pending_resize = pending_cols = 0;
> +					pending_quiet = 0;
> +					pending_post = 1;
> +				}
> +				continue;
> +			}
> +			if (pending_post) {
> +				pending_post = 0;
> +				continue;
> +			}
>  			if (timeout == PRTIM) {
>  				warnx("timeout waiting from prompt");
>  				ret = 1;
> @@ -136,6 +160,28 @@ main(int argc, char *argv[])
>  				readprompt = 0;
>  			}
>  		} else if (pfd.revents & POLLOUT) {
> +			if (in[nwrite] == '\0' && nwrite + 3 < nin &&
> +			    in[nwrite + 1] == 'R' &&
> +			    in[nwrite + 2] == 'S' &&
> +			    in[nwrite + 3] >= '0' && in[nwrite + 3] <= '9') {
> +				size_t i = nwrite + 3;
> +				int cols = 0, nd = 0;
> +
> +				while (i < nin && nd < 3 &&
> +				    in[i] >= '0' && in[i] <= '9') {
> +					cols = cols * 10 + (in[i] - '0');
> +					i++;
> +					nd++;
> +				}
> +				if (nd > 0 && (i == nin ||
> +				    in[i] < '0' || in[i] > '9') &&
> +				    cols > 0) {
> +					pending_resize = 1;
> +					pending_cols = cols;
> +					nwrite = i;
> +					continue;
> +				}
> +			}
>  			if (strchr(linefeed, in[nwrite]) != NULL)
>  				readprompt = 1;
>  
> @@ -143,6 +189,8 @@ main(int argc, char *argv[])
>  			if (n == -1)
>  				err(1, "write");
>  			nwrite += n;
> +			if (pending_resize)
> +				pending_quiet = 0;
>  		}
>  	}
>  	close(ptyfd);
> Index: regress/bin/ksh/edit/emacs.sh
> ===================================================================
> RCS file: /home/cvs/src/regress/bin/ksh/edit/emacs.sh,v
> diff -u -p -r1.15 emacs.sh
> --- regress/bin/ksh/edit/emacs.sh	2 Sep 2021 07:14:15 -0000	1.15
> +++ regress/bin/ksh/edit/emacs.sh	9 Sep 2026 10:44:49 -0000
> @@ -52,6 +52,62 @@ testseq "z\0002\0363\0277\0277\0277" " #
>  testseq "z\0002\0364\0200\0200\0200" " # z\b\0364\0200\0200\0200z\b"
>  testseq "z\0002\0364\0217\0277\0277" " # z\b\0364\0217\0277\0277z\b"
>  
> +# ASCII resize: cols=1/11/12
> +testseq "aaaaaaaaaabbbbbbbbbb\0001\000RS1" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J\r # aaaaaaa>\b\b\b\b\b\b\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\003310\0002\000RS11" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\r\033[J\raaaaabbbbb*\b\b\b\b\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\000RS12" \
> +	" # aaaaaaaaaabbbbbbbbbb\r\033[J\rbbbbb     <\b\b\b\b\b\b"
> +
> +# ASCII resize: cols=13, cursor -1/0/+1
> +testseq "aaaaaaaaaabbbbbbbbbb\003313\0002\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J\r # aaaaaaaa>\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\003312\0002\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J\r # aaaaaaaa>\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\003311\0002\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\r\033[J\raaaaaabbbbb*\b\b\b\b\b\b\b"
> +
> +# ASCII resize: cols=79/80/81
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0001\000RS79" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\rbbbbbbbbbbbbccccccccccccccccccccccccc                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J\r # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccc>\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0001\000RS80" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\rbbbbbbbbbbbbccccccccccccccccccccccccc                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0001\000RS81" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\rbbbbbbbbbbbbccccccccccccccccccccccccc                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J\r # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# ASCII window indicator at left edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 window indicator at left edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# ASCII redraw at right edge
> +PS1='012345678901234567890123456789012345678901234567890123456789'
> +testseq "#aaaaaaaaaaaaaaaaab\0033#" "012345678901234567890123456789012345678901234567890123456789#aaaaaaaaaaaaaaaaa\raaaaaaaaa                                                                     <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bb\r012345678901234567890123456789012345678901234567890123456789aaaaaaaaaaaaaaaaab \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 redraw at right edge
> +testseq "#aaaaaaaaaaaaaaaaa\0303\0266\0033#" "012345678901234567890123456789012345678901234567890123456789#aaaaaaaaaaaaaaaaa\raaaaaaaaa                                                                     <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\0303\0266\r012345678901234567890123456789012345678901234567890123456789aaaaaaaaaaaaaaaaa\0303\0266 \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +PS1=' # '
> +
> +# ASCII window indicator at right edge
> +testseq "\003342ab\003397b\0001" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\raaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 window indicator at right edge
> +testseq "\003342a\0303\0266\003397b\0001" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\raaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# ASCII window indicator on both sides
> +testseq "\003342ab\003397b\0001\003379\0006" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\raaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb*\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 window indicator on both sides
> +testseq "\003342a\0303\0266\003397b\0001\003379\0006" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\raaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                         <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\ra\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb*\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
>  # insertion of incomplete UTF-8
>  testseq "z\0002\0302\0006" " # z\b\0302z\bz"
>  testseq "z\0002\0377\0006" " # z\b\0377z\bz"
> Index: regress/bin/ksh/edit/vi.sh
> ===================================================================
> RCS file: /home/cvs/src/regress/bin/ksh/edit/vi.sh,v
> diff -u -p -r1.14 vi.sh
> --- regress/bin/ksh/edit/vi.sh	4 Apr 2026 09:33:18 -0000	1.14
> +++ regress/bin/ksh/edit/vi.sh	9 Sep 2026 10:44:49 -0000
> @@ -233,3 +233,59 @@ testseq "(x)\00330%hrc" " # (x)\b\b\b(x\
>  
>  # ^R: Redraw.
>  testseq "test\0033h\0022" " # test\b\b\r\r\n # test\b\b"
> +
> +# ASCII resize: cols=1/11/12
> +testseq "aaaaaaaaaabbbbbbbbbb\0033hhhhhhhhhhhhhhhhhhh\000RS1" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J# aaaaaaa >\r# "
> +testseq "aaaaaaaaaabbbbbbbbbb\0033hhhhhhhhh\000RS11" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\r\033[J# aaabbbb +\b\b\b\b\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\0033\000RS12" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\r\033[J# bbbb    <\b\b\b\b\b\b"
> +
> +# ASCII resize: cols=13, cursor -1/0/+1
> +testseq "aaaaaaaaaabbbbbbbbbb\0033hhhhhhhhhhhhh\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J # aaaaaaa >\b\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\0033hhhhhhhhhhhh\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J # aaaaaab +\b\b\b\b\b\b"
> +testseq "aaaaaaaaaabbbbbbbbbb\0033hhhhhhhhhhh\000RS13" \
> +	" # aaaaaaaaaabbbbbbbbbb\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J # aaaaabb +\b\b\b\b\b\b"
> +
> +# ASCII resize: cols=79/80/81
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0033hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\000RS79" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc\r # bbbbbbbbbbbbbcccccccccccccccccccccccc                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bc\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\baaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccc >\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc >\r # "
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0033hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\000RS80" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc\r # bbbbbbbbbbbbbcccccccccccccccccccccccc                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bc\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\baaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccc >\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc\0033hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\000RS81" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc\r # bbbbbbbbbbbbbcccccccccccccccccccccccc                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bc\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\baaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccc >\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r\033[J # aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccc >\r # "
> +
> +# ASCII window indicator at left edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbb" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbb                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 window indicator at left edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbb" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbb\r # aaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbb                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# ASCII window indicator at right edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb\00330" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbb\b\baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # "
> +
> +# UTF-8 window indicator at right edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266b\00330" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\0303\0266b\b\baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # "
> +
> +# ASCII window indicator on both sides
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\003340h" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\baaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                    \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbb +\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# UTF-8 window indicator on both sides
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\003340h" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\baaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r # aaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                    \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266bbbbbbbbbbbbbbbbbbbbbbbbbb +\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
> +
> +# ASCII redraw at right edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb\00330\0022" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bbb\b\baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # \r\r\n # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # "
> +
> +# UTF-8 redraw at right edge
> +testseq "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0303\0266b\00330\0022" \
> +	" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b                                      <\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\0303\0266b\b\baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # \r\r\n # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\r # "
> 
> 
> -- 
> wbr, Kirill
>