summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vui.c133
1 files changed, 74 insertions, 59 deletions
diff --git a/vui.c b/vui.c
index ffd5800..5427c8f 100644
--- a/vui.c
+++ b/vui.c
@@ -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;