From: YASUOKA Masahiko Subject: watch: tab + holizontal scroll To: tedu@openbsd.org, job@openbsd.org Cc: tech@openbsd.org Date: Fri, 27 Jun 2025 13:40:54 +0900 Hi, More care about TAB spaces seems to be needed for scrolling horizontally. ok? Index: usr.bin/watch/watch.c =================================================================== RCS file: /cvs/src/usr.bin/watch/watch.c,v diff -u -p -r1.32 watch.c --- usr.bin/watch/watch.c 26 Jun 2025 21:34:45 -0000 1.32 +++ usr.bin/watch/watch.c 27 Jun 2025 04:37:59 -0000 @@ -85,8 +85,16 @@ time_t lastupdate; int xflag = 0; struct timespec prev_start, start, prev_stop, stop; -#define addwch(_x) addnwstr(&(_x), 1); -#define WCWIDTH(_x) ((wcwidth((_x)) > 0)? wcwidth((_x)) : 1) +#define WCWIDTH(_c) (wcwidth((_c)) > 0)? wcwidth((_c)) : 1 +#define WCWIDTHX(_x, _c) \ + (((_c) == '\t')? TABSPACE - ((_x) % TABSPACE) : WCWIDTH(_c)) +#define ADDWCHX0(_x0, _c) \ + do { \ + if ((_c) != '\t' || ((_x0) % TABSPACE) == 0) \ + addnwstr(&(_c), 1); \ + else \ + addnstr(" ", 8); /* untabify */ \ + } while (0) static char *cmdstr; static size_t cmdlen; @@ -305,18 +313,19 @@ display(BUFFER * cur, BUFFER * prev, hig for (line = start_line, screen_y = 2; screen_y < LINES && line < MAXLINE && (*cur)[line][0]; line++, screen_y++) { - wchar_t *cur_line, *prev_line, *p, *pp; + wchar_t *cur_line, *prev_line, *p, *p0, *pp; rl = 0; /* reversing line */ cur_line = (*cur)[line]; prev_line = (*prev)[line]; for (p = cur_line, cw = 0; cw < start_column; p++) - cw += WCWIDTH(*p); + cw += WCWIDTHX(cw, *p); screen_x = cw - start_column; for (pp = prev_line, cw = 0; cw < start_column; pp++) - cw += WCWIDTH(*pp); + cw += WCWIDTHX(cw, *pp); + p0 = p; switch (hm) { case HIGHLIGHT_LINE: if (wcscmp(cur_line, prev_line)) { @@ -333,10 +342,11 @@ display(BUFFER * cur, BUFFER * prev, hig move(screen_y, screen_x); while (screen_x < COLS) { if (*p && *p != L'\n') { - cw = wcwidth(*p); + cw = WCWIDTHX(screen_x, *p); if (screen_x + cw >= COLS) break; - addwch(*p++); + ADDWCHX0(start_column, *p); + p++; pp++; screen_x += cw; } else if (rl) { @@ -352,14 +362,12 @@ display(BUFFER * cur, BUFFER * prev, hig case HIGHLIGHT_CHAR: move(screen_y, screen_x); while (*p && screen_x < COLS) { - if (*p == '\t') - cw = TABSPACE - (screen_x % TABSPACE); - else - cw = wcwidth(*p); + cw = WCWIDTHX(screen_x, *p); if (screen_x + cw >= COLS) break; if (*p == *pp) { - addwch(*p++); + ADDWCHX0(start_column, *p); + p++; pp++; screen_x += cw; continue; @@ -370,19 +378,19 @@ display(BUFFER * cur, BUFFER * prev, hig * back to the beginning of the word. */ if (hm == HIGHLIGHT_WORD && !iswspace(*p)) { - while (cur_line + start_column < p && - !iswspace(*(p - 1))) { + while (p0 < p && !iswspace(*(p - 1))) { p--; pp--; - screen_x -= wcwidth(*p); + screen_x -= WCWIDTH(*p); } move(screen_y, screen_x); - cw = wcwidth(*p); + cw = WCWIDTH(*p); } standout(); /* Print character itself. */ - addwch(*p++); + ADDWCHX0(start_column, *p); + p++; pp++; screen_x += cw; @@ -395,8 +403,9 @@ display(BUFFER * cur, BUFFER * prev, hig if (hm == HIGHLIGHT_WORD) { while (*p && !iswspace(*p) && screen_x < COLS) { - cw = wcwidth(*p); - addwch(*p++); + cw = WCWIDTH(*p); + ADDWCHX0(start_column, *p); + p++; pp++; screen_x += cw; }