From: Stuart Henderson 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 On 2026/09/09 12:55, Kirill A. Korinsky wrote: > On Wed, 08 Jul 2026 11:41:07 +0200, > Stuart Henderson 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 > +#include > > #include > #include > @@ -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 >