diff options
| -rw-r--r-- | vui.c | 133 |
1 files changed, 74 insertions, 59 deletions
@@ -187,8 +187,10 @@ void vui_curs_vis(int vis) { win.curs_vis = vis; if (vis) { fputs(CSI "?25h", stdout); + fflush(stdout); } else { fputs(CSI "?25l", stdout); + fflush(stdout); } } @@ -327,7 +329,9 @@ static inline void vui_outc(char c) { /* it doesn't make sense to do so, and assuming non-zero lets us dodge a branch * in stdc_leading_zeros() */ static inline void vui_outvc(VuiChar c) { - ASSUME(c > 0 && c <= 0x110000); + //ASSUME(c > 0 && c <= 0x110000); + ASSUME(c > 0); + ASSUME(c <= 0x110000); uint8_t len = UTF8_CP_LEN(c); vui_out_fit(vui_outn + len); ASSUME(len > 0 && len < 5); @@ -361,10 +365,12 @@ static inline void vui_outs(const char *s) { } static inline void vui_out_flush(void) { - fwrite(vui_out, 1, vui_outn, stdout); - fflush(stdout); - //write(STDOUT_FILENO, vui_out, vui_outn); -#if 0 + /*fwrite(vui_out, 1, vui_outn, stdout); + fflush(stdout);*/ + + write(STDOUT_FILENO, vui_out, vui_outn); + +#if 1 static unsigned out_frame = 0; FILE *f = fopen("out_log.txt", "a"); assert(f); @@ -372,6 +378,7 @@ static inline void vui_out_flush(void) { fwrite(vui_out, 1, vui_outn, f); fclose(f); #endif + vui_outn = 0; } @@ -500,14 +507,46 @@ chg_colors:; void vui_scroll_buf(VuiBuffer *b, int dx, int dy); +static VuiAttr attr_last = ATTR_DEFAULT; +static unsigned cur_x = 0; +static unsigned cur_y = 0; + +static void emit_scroll_x(u32 y) { + if (win.scroll_x < 0) { + /* delete chars at start of line */ + attr_chg(&attr_last, ATTR_DEFAULT); + curs_move(&cur_x, &cur_y, 0, y); + vui_outf(CSI "%dP", -win.scroll_x); + } else if (win.scroll_x > 0) { + /* insert spaces at start of line */ + attr_chg(&attr_last, ATTR_DEFAULT); + curs_move(&cur_x, &cur_y, 0, y); + vui_outf(CSI "%d@", win.scroll_x); + } +} + +static void emit_scroll_y(void) { + /* xterm has \x1b[S and \x1b[T to scroll directly */ + /* but these don't work in linux vtty */ + if (win.scroll_y < 0) { + /* delete lines at top */ + curs_move(&cur_x, &cur_y, 0, 0); + attr_chg(&attr_last, ATTR_DEFAULT); + if (win.scroll_y == -1) vui_outs(CSI "M"); + else vui_outf(CSI "%dM", -win.scroll_y); + } else if (win.scroll_y > 0) { + /* insert blank lines at top */ + curs_move(&cur_x, &cur_y, 0, 0); + attr_chg(&attr_last, ATTR_DEFAULT); + if (win.scroll_y == 1) vui_outs(CSI "L"); + else vui_outf(CSI "%dL", win.scroll_y); + } +} + void vui_blit(void) { VuiBuffer *front = win.front; VuiBuffer *back = win.back; - static VuiAttr attr_last = ATTR_DEFAULT; - static unsigned cur_x = 0; - static unsigned cur_y = 0; - if (win.redraw_all) { vui_outs(CSI "H" CSI "2J" CSI "0m"); attr_last = ATTR_DEFAULT; @@ -525,52 +564,11 @@ void vui_blit(void) { goto end; } - if (win.scroll_x || win.scroll_y) { - if ((unsigned)abs(win.scroll_x) >= COLS || (unsigned)abs(win.scroll_y) > LINES) { - vui_outs(CSI "2J"); - goto scrolled; - } - - /* spaces inserted by scrolling will have the last-used attribute */ - /* which we don't really want */ - attr_chg(&attr_last, ATTR_DEFAULT); - - if (win.scroll_x < 0) { - /* delete chars at start of line */ - for (unsigned y = 0; y < LINES; y++) { - curs_move(&cur_x, &cur_y, 0, y); - vui_outf(CSI "%dP", -win.scroll_x); - } - } else if (win.scroll_x > 0) { - /* insert spaces at start of line */ - for (unsigned y = 0; y < LINES; y++) { - curs_move(&cur_x, &cur_y, 0, y); - vui_outf(CSI "%d@", win.scroll_x); - } - } - - /* xterm has \x1b[S and \x1b[T to scroll directly */ - /* but these don't work in linux vtty */ - if (win.scroll_y < 0) { - /* delete lines at top */ - curs_move(&cur_x, &cur_y, 0, 0); - if (win.scroll_y == -1) vui_outs(CSI "M"); - else vui_outf(CSI "%dM", -win.scroll_y); - } else if (win.scroll_y > 0) { - /* insert blank lines at top */ - curs_move(&cur_x, &cur_y, 0, 0); - if (win.scroll_y == 1) vui_outs(CSI "L"); - else vui_outf(CSI "%dL", win.scroll_y); - } - -scrolled: - vui_scroll_buf(back, win.scroll_x, win.scroll_y); - win.scroll_x = 0; - win.scroll_y = 0; - } - + emit_scroll_y(); + vui_scroll_buf(back, win.scroll_x, win.scroll_y); for (unsigned y = 0; y < LINES; y++) { unsigned x = 0; + emit_scroll_x(y); while (x < COLS) { while (x < COLS && bchr_equiv(back, front, (y * COLS) + x)) x++; if (x >= COLS) break; @@ -587,6 +585,9 @@ scrolled: } end: + win.scroll_x = 0; + win.scroll_y = 0; + if (win.curs_vis) { curs_move(&cur_x, &cur_y, win.curs_x, win.curs_y); } @@ -643,13 +644,27 @@ static void utf8_decode(uint32_t *dst, const char *src, unsigned n) { while (src < end) src = utf8_next(dst++, src); } -void vui_putsna(int x, int y, const char *s, unsigned n, VuiAttr a) { - if (x >= (int)COLS) return; - if (n > COLS - x) n = COLS - x; - if (x < 0) { - n += x; - x = 0; +static void truncate_span(int *x, unsigned *nptr) { + int n = (int)*nptr; + if (*x < 0) { + n += *x; + *x = 0; + } + if (*x >= (int)COLS) { + *nptr = 0; + return; } + if (*x + n >= (int)COLS) { + n = COLS - *x - 1; + } + if (n < 0) n = 0; + assert(n >= 0); + assert(*x + n < (int)COLS); + *nptr = n; +} + +void vui_putsna(int x, int y, const char *s, unsigned n, VuiAttr a) { + truncate_span(&x, &n); if (n < 1 || y < 0 || y >= (int)LINES) return; utf8_decode(&CHR(x, y), s, n); for (uint16_t *pa = &ATTR(x, y); n--;) *pa++ = a; |
