Download raw body.
bin/ksh: fix vi mode UTF-8 window display
tech@
here the last my patch for ksh which address issues with UTF-8 disply logic
which was discovered by testing of resize terminal.
It also included a fix for a crush reported by Walter Alejandro Iglesias.
The vi line editor sizes its window buffers by column count and stops
rendering at the right edge. With UTF-8 input, a continuation byte can
land at the edge, producing garbage like "\\xb9<" and misplacing the
indicator; small-window resizes can also overrun the window buffer.
Size the window buffers for UTF-8 and allow trailing continuation bytes
at the right edge. When a trailing UTF-8 byte is present, force the
indicator to print as a space plus the marker in the usual position.
diff --git bin/ksh/vi.c bin/ksh/vi.c
index def7aeeae24..c16bef9a78f 100644
--- bin/ksh/vi.c
+++ bin/ksh/vi.c
@@ -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 */
@@ -1369,7 +1370,7 @@ static int prompt_trunc; /* how much of prompt to truncate */
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 */
@@ -1449,6 +1450,7 @@ static void
calc_winsize(void)
{
const char *p;
+ int newlen;
cur_col = pwidth = promptlen(prompt, &p);
prompt_skip = p - prompt;
@@ -1458,8 +1460,9 @@ calc_winsize(void)
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);
}
@@ -1880,6 +1883,7 @@ display(char *wb1, char *wb2, int leftside)
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;
@@ -1891,8 +1895,11 @@ display(char *wb1, char *wb2, int leftside)
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') {
@@ -1908,7 +1915,8 @@ display(char *wb1, char *wb2, int leftside)
}
ch &= 0x7f;
}
- if (col < winwidth) {
+ if (col < winwidth ||
+ (col == winwidth && isu8cont(ch))) {
if (ch < ' ' || ch == 0x7f) {
*twb1++ = '^';
if (++col < winwidth) {
@@ -1916,6 +1924,8 @@ display(char *wb1, char *wb2, int leftside)
col++;
}
} else {
+ if (col == winwidth && isu8cont(ch))
+ trailu8 = 1;
*twb1++ = ch;
if (col == 0 || !isu8cont(ch))
col++;
@@ -2008,8 +2018,10 @@ display(char *wb1, char *wb2, int leftside)
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;
bin/ksh: fix vi mode UTF-8 window display