From 90b67b81fae38540b7a9257d23c4b50820ca5b1d Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Tue, 4 Nov 2025 15:16:12 -0500 Subject: stuff, add vui_scroll --- main.c | 243 +++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 155 insertions(+), 88 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index a765669..d3ceecd 100644 --- a/main.c +++ b/main.c @@ -83,16 +83,16 @@ typedef struct { int redraw_all; } VuiWindow; -static struct termios vui_init_stdin_tos, vui_raw_stdin_tos; -static VuiWindow win = { - .front = &win.buf1, - .back = &win.buf2, +static struct termios vui_init_stdin_tos, vui_init_stdout_tos, vui_raw_stdin_tos, vui_raw_stdout_tos; +VuiWindow vui_win = { + .front = &vui_win.buf1, + .back = &vui_win.buf2, }; #define BCHR(b,x,y) ((b)->chr[(x) + (y) * (b)->width]) #define BATTR(b,x,y) ((b)->attr[(x) + (y) * (b)->width]) -#define CHR(x,y) BCHR(win.front, x, y) -#define ATTR(x,y) BATTR(win.front, x, y) +#define CHR(x,y) BCHR(vui_win.front, x, y) +#define ATTR(x,y) BATTR(vui_win.front, x, y) void vui_getwinsz(unsigned *w, unsigned *h) { struct winsize wsz; @@ -117,7 +117,7 @@ static void clear_buf(VuiBuffer *buf) { } static void vui_clear(void) { - clear_buf(win.front); + clear_buf(vui_win.front); } static void resize_buf(VuiBuffer *buf, unsigned nw, unsigned nh) { @@ -146,18 +146,18 @@ static void resize_buf(VuiBuffer *buf, unsigned nw, unsigned nh) { } static void vui_resize(unsigned nw, unsigned nh) { - resize_buf(&win.buf1, nw, nh); - resize_buf(&win.buf2, nw, nh); - win.width = nw; - win.height = nh; + resize_buf(&vui_win.buf1, nw, nh); + resize_buf(&vui_win.buf2, nw, nh); + vui_win.width = nw; + vui_win.height = nh; } static void vui_adjust(void) { unsigned w, h; vui_getwinsz(&w, &h); - if (w != win.width || h != win.height) { + if (w != vui_win.width || h != vui_win.height) { vui_resize(w, h); - win.redraw_all = 1; + vui_win.redraw_all = 1; } } @@ -174,6 +174,12 @@ void vui_init(void) { vui_raw_stdin_tos = vui_init_stdin_tos; vui_raw_stdin_tos.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); tcsetattr(STDIN_FILENO, TCSANOW, &vui_raw_stdin_tos); + + tcgetattr(STDOUT_FILENO, &vui_init_stdout_tos); + vui_raw_stdout_tos = vui_init_stdout_tos; + vui_raw_stdout_tos.c_oflag &= ~OPOST; + tcsetattr(STDOUT_FILENO, TCSANOW, &vui_raw_stdout_tos); + vui_adjust(); } @@ -189,9 +195,10 @@ static void free_buf(VuiBuffer *buf) { void vui_fini(void) { tcsetattr(STDIN_FILENO, TCSANOW, &vui_init_stdin_tos); + tcsetattr(STDOUT_FILENO, TCSANOW, &vui_init_stdout_tos); vui_curs_vis(1); - free_buf(&win.buf1); - free_buf(&win.buf2); + free_buf(&vui_win.buf1); + free_buf(&vui_win.buf2); printf("\x1b[H\x1b[2J\x1b[0m"); } @@ -218,18 +225,22 @@ static inline void curs_move(int src_x, int src_y, int dst_x, int dst_y) { static void attr_chg(VuiAttr *ptr, VuiAttr to) { VuiAttr from = *ptr; if (from == to) return; + char buf[64] = { 0 }; + char *s = buf; int chg_attr = (ATTR_A(from) != ATTR_A(to)); chg_attr = 0; if (chg_attr) { - printf("\x1b[0"); - if (to & A_BOLD) printf(";1"); - if (to & A_DIM) printf(";2"); - if (to & A_ITALIC) printf(";3"); - if (to & A_UNDERSCORE) printf(";4"); - if (to & A_BLINK) printf(";5"); - if (to & A_REVERSE) printf(";7"); + *s++ = '\x1b'; + *s++ = '['; + *s++ = '0'; + if (to & A_BOLD) *s++ = ';', *s++ = '1'; + if (to & A_DIM) *s++ = ';', *s++ = '1'; + if (to & A_ITALIC) *s++ = ';', *s++ = '3'; + if (to & A_UNDERSCORE) *s++ = ';', *s++ = '4'; + if (to & A_BLINK) *s++ = ';', *s++ = '5'; + if (to & A_REVERSE) *s++ = ';', *s++ = '7'; from = ATTR_DEFAULT; assert(ATTR_FG(from) == FG_WHITE); assert(ATTR_BG(from) == BG_BLACK); @@ -243,52 +254,68 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) { int chg_fg = (t_fg != f_fg); int chg_bg = (t_bg != f_bg); if (chg_fg || chg_bg) { - if (chg_attr) putchar(';'); - else printf("\x1b["); - if (chg_fg) printf("%d", t_fg > 7 ? 90 + (t_fg&7) : 30 + t_fg); + if (chg_attr) *s++ = ';'; + else *s++ = '\x1b', *s++ = '['; + if (chg_fg) { + *s++ = (t_fg > 7 ? '9' : '3'); + *s++ = (t_fg & 7) + '0'; + } if (chg_bg) { - if (chg_fg) putchar(';'); - printf("%d", t_bg > 7 ? 100 + (t_bg&7) : 40 + t_bg); + if (chg_fg) *s++ = ';'; + if (t_bg > 7) { + *s++ = '1'; + *s++ = '0'; + } else { + *s++ = '4'; + } + *s++ = (t_bg & 7) + '0'; } } - if (chg_fg || chg_bg || chg_attr) putchar('m'); + if (chg_fg || chg_bg || chg_attr) { + *s++ = 'm'; + *s = '\0'; + fputs(buf, stdout); + } *ptr = to; } unsigned vui_changes = 0; unsigned vui_max_change = 0; +unsigned vui_repainted = 0; void vui_blit(void) { - VuiBuffer *front = win.front; - VuiBuffer *back = win.back; + VuiBuffer *front = vui_win.front; + VuiBuffer *back = vui_win.back; printf("\x1b[H\x1b[0m"); VuiAttr attr_last = ATTR_DEFAULT; - if (win.redraw_all) { - vui_changes = win.width * win.height; - for (unsigned y = 0; y < win.height; y++) { - for (unsigned x = 0; x < win.width; x++) { + if (vui_win.redraw_all) { + vui_changes = vui_win.width * vui_win.height; + for (unsigned y = 0; y < vui_win.height; y++) { + for (unsigned x = 0; x < vui_win.width; x++) { attr_chg(&attr_last, ATTR(x, y)); putchar(CHR(x, y)); } } - win.redraw_all = 0; + vui_repainted = vui_win.width * vui_win.height; + vui_win.redraw_all = 0; goto copy_buf; } vui_changes = 0; vui_max_change = 0; + vui_repainted = 0; unsigned cur_x = 0, cur_y = 0; - for (unsigned y = 0; y < win.height; y++) { + for (unsigned y = 0; y < vui_win.height; y++) { unsigned x = 0; - while (x < win.width) { - while (x < win.width && bchr_equiv(back, front, x, y)) x++; - if (x >= win.width) break; + while (x < vui_win.width) { + while (x < vui_win.width && bchr_equiv(back, front, x, y)) x++; + if (x >= vui_win.width) break; unsigned x0 = x; VuiAttr a = ATTR(x0, y); - while (x < win.width && !bchr_equiv(back, front, x, y) && ATTR(x, y) == a) x++; + while (x < vui_win.width && !bchr_equiv(back, front, x, y) && ATTR(x, y) == a) x++; if (x0 != x) { vui_changes++; curs_move(cur_x, cur_y, x0, y); @@ -296,6 +323,7 @@ void vui_blit(void) { printf("%.*s", x - x0, &CHR(x0, y)); cur_x = x; cur_y = y; + vui_repainted += x - x0; if (x - x0 > vui_max_change) vui_max_change = x - x0; } } @@ -305,12 +333,12 @@ copy_buf: fflush(stdout); memcpy(back->chr, front->chr, sizeof(*back->chr) * (back->width * back->height)); memcpy(back->attr, front->attr, sizeof(*back->attr) * (back->width * back->height)); - win.front = back; - win.back = front; + vui_win.front = back; + vui_win.back = front; } void vui_chra(int x, int y, char c, VuiAttr a) { - if (x >= 0 && x < (int)win.width && y >= 0 && y < (int)win.height) { + if (x >= 0 && x < (int)vui_win.width && y >= 0 && y < (int)vui_win.height) { CHR(x, y) = c; ATTR(x, y) = a; } @@ -324,13 +352,13 @@ int vui_avprintf(int x, int y, VuiAttr a, const char *fmt, va_list ap) { va_list ap2; va_copy(ap2, ap); int n = vsnprintf(NULL, 0, fmt, ap); - if (x < 0) x = win.width + x - (n - 1); - if (y < 0) y = win.height + y; + if (x < 0) x = vui_win.width + x - (n - 1); + if (y < 0) y = vui_win.height + y; if (n > 0) { char buf[n + 1]; vsnprintf(buf, n + 1, fmt, ap2); - memcpy(&CHR(x,y), buf, n < win.width - x ? n : win.width - x); - for (unsigned x1 = x; x1 < win.width && x1 < x + n; x1++) { + memcpy(&CHR(x,y), buf, n < vui_win.width - x ? n : vui_win.width - x); + for (unsigned x1 = x; x1 < vui_win.width && x1 < x + n; x1++) { ATTR(x1, y) = a; } } @@ -369,6 +397,39 @@ unsigned isqrt(unsigned x) { return a; } +void vui_scroll_buf(VuiBuffer *b, int dx, int dy) { + if (abs(dx) >= b->width || abs(dy) >= b->height) { + clear_buf(b); + return; + } + if (dy > 0) { + memmove(b->chr + (b->width * dy), b->chr, sizeof(*b->chr) * b->width * (b->height - dy)); + memmove(b->attr + (b->width * dy), b->attr, sizeof(*b->attr) * b->width * (b->height - dy)); + } else if (dy < 0) { + memmove(b->chr, b->chr + (b->width * -dy), sizeof(*b->chr) * b->width * (b->height + dy)); + memmove(b->attr, b->attr + (b->width * -dy), sizeof(*b->attr) * b->width * (b->height + dy)); + } + if (dx > 0) { + for (unsigned i = 0; i < b->height; i++) { + memmove(b->chr + (i * b->width) + dx, b->chr + (i * b->width), sizeof(*b->chr) * (b->width - dx)); + } + for (unsigned i = 0; i < b->height; i++) { + memmove(b->attr + (i * b->width) + dx, b->attr + (i * b->width), sizeof(*b->attr) * (b->width - dx)); + } + } else if (dx < 0) { + for (unsigned i = 0; i < b->height; i++) { + memmove(b->chr + (i * b->width), b->chr + (i * b->width) - dx, sizeof(*b->chr) * (b->width + dx)); + } + for (unsigned i = 0; i < b->height; i++) { + memmove(b->attr + (i * b->width), b->attr + (i * b->width) - dx, sizeof(*b->attr) * (b->width + dx)); + } + } +} + +void vui_scroll(int dx, int dy) { + vui_scroll_buf(vui_win.front, dx, dy); +} + int main(int argc, const char **argv) { vui_init(); vui_curs_vis(0); @@ -378,18 +439,36 @@ int main(int argc, const char **argv) { int camx = 0, camy = 0; int C = '*'; unsigned frame = 0; + int half_y = 0; for (;;) { frame++; - camx += dx; + //camx += dx; x += dx; - if (frame & 1) { - camy += dy; + if ((frame & 1) || !(half_y)) { + // camy += dy; y += dy; } + + unsigned left = 32; + unsigned right = vui_win.width - (left + 1); + unsigned top = left >> half_y; + unsigned bottom = vui_win.height - (top + 1); + + int lcamx = camx, lcamy = camy; + if (x < left) { camx += x - left; x = left; } + if (x > right) { camx += x - right; x = right; } + if (y < top) { camy += y - top; y = top; } + if (y > bottom) { camy += y - bottom; y = bottom; } + + int dcx = camx - lcamx, dcy = camy - lcamy; + vui_scroll(-dcx, -dcy); + + /* if (x < 0) x += win.width; if (x > win.width) x -= win.width; if (y < 0) y += win.height; if (y > win.height) y -= win.height; + */ static int paused = 0; @@ -397,39 +476,32 @@ int main(int argc, const char **argv) { /* weird cellular automata */ if (!paused) { // int dx = 0, dy = 0; /* shadow on purpose */ - for (int y = 0; y < win.height; y++) { - for (int x = 0; x < win.width; x++) { - int tx = x - dx, ty = y - dy; - int txa = tx, txc = tx, tya = ty, tyc = ty; + + for (int y = 0; y < vui_win.height; y++) { + for (int x = 0; x < vui_win.width; x++) { if (frame & 1) { - /* - txa += (random() & 1) * 2 - 1; - tya += (random() & 1) * 2 - 1; - txc += (random() & 1) * 2 - 1; - tyc += (random() & 1) * 2 - 1; - */ + int txa = x, tya = y, txc = x, tyc = y; txa += (random() % 3) - 1; tya += (random() % 3) - 1; txc += (random() % 3) - 1; tyc += (random() % 3) - 1; - } - if (txa >= 0 && txa < win.width && tya >= 0 && tya < win.height) { - //ATTR(txa, tya) = BATTR(win.back, x, y); - ATTR(txa, tya) = (BATTR(win.back,x,y) & ~0xf) | (ATTR(txa,tya) & 0xf); - if (!(random() & 127)) ATTR(x,y) = ATTR_DEFAULT; - //ATTR(txc, tyc) = (ATTR(txc, tyc) & ~0xf) | (ATTR(x, y) & 0xf); - } - if (txc >= 0 && txc < win.width && tyc >= 0 && tyc < win.height) { - CHR(txc, tyc) = BCHR(win.back, x, y); - ATTR(txc, tyc) = (ATTR(txc,tyc) & ~0xf) | (BATTR(win.back,x,y) & 0xf); - if (!(random() & 127)) CHR(x,y) = ' '; + if (txa >= 0 && txa < vui_win.width && tya >= 0 && tya < vui_win.height) { + ATTR(txa, tya) = (BATTR(vui_win.back,x,y) & ~0xf) | (ATTR(txa,tya) & 0xf); + if (!(random() & 127)) ATTR(x,y) = ATTR_DEFAULT; + } + if (txc >= 0 && txc < vui_win.width && tyc >= 0 && tyc < vui_win.height) { + CHR(txc, tyc) = BCHR(vui_win.back, x, y); + ATTR(txc, tyc) = (ATTR(txc,tyc) & ~0xf) | (BATTR(vui_win.back,x,y) & 0xf); + if (!(random() & 127)) CHR(x,y) = ' '; + } } } } - for (unsigned i = 0; i < isqrt(win.width * win.height) / 10; i++) { - int tx = random() % win.width; - int ty = random() % win.height; + //vui_win.redraw_all = 1; + for (unsigned i = 0; i < isqrt(vui_win.width * vui_win.height) / 10; i++) { + int tx = random() % vui_win.width; + int ty = random() % vui_win.height; VuiAttr a = ((random()&15) << 4) | (random()&15); vui_chra(tx, ty, ' ' + (random() % 0x5f), a); } @@ -437,8 +509,8 @@ int main(int argc, const char **argv) { #else vui_clear(); - for (unsigned y = 0; y < win.height; y++) { - for (unsigned x = 0; x < win.width; x++) { + for (unsigned y = 0; y < vui_win.height; y++) { + for (unsigned x = 0; x < vui_win.width; x++) { int tx = x + camx, ty = y + camy; char ch = " ',."[(tx^ty)&3]; ch = ' '; @@ -454,9 +526,9 @@ int main(int argc, const char **argv) { vui_chra(x, y-1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); vui_chra(x, y+1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); - vui_printf(-1, -1, "(%u, %u)", win.width, win.height); - vui_printf(0, -1, "front buffer = %p", (void*)win.front); - vui_printf(-1, 0, "longest change = %02u, changes = %04u, chars = %04u", vui_max_change, vui_changes, win.width * win.height); + vui_printf(-1, -1, "(%u, %u)", vui_win.width, vui_win.height); + vui_printf(0, -1, "front buffer = %p", (void*)vui_win.front); + vui_printf(-1, 0, "longest change = %3u, changes = %5u, repainted%% = %02u%%, chars = %5u", vui_max_change, vui_changes, vui_repainted * 100 / (vui_win.width * vui_win.height), vui_win.width * vui_win.height); // win.redraw_all = 1; vui_blit(); @@ -467,19 +539,14 @@ int main(int argc, const char **argv) { if (c == 'q') break; if (c > 0x20 && c < 0x7f) C = c; switch (c) { - case 'k': dx=0; dy=-1; break; - case 'j': dx=0; dy=1; break; - case 'h': dx=-1; dy=0; break; + case 'j': dx=-1; dy=0; break; + case 'i': dx=0; dy=-1; break; + case 'k': dx=0; dy=1; break; case 'l': dx=1; dy=0; break; - case 'y': dx=-1; dy=-1; break; - case 'u': dx=1; dy=-1; break; - case 'b': dx=-1; dy=1; break; - case 'n': dx=1; dy=1; break; case ' ': paused = !paused; break; - default: dx=1; dy=0; break; } } vui_fini(); - printf("\x1b[2J\x1b[H %u, %u\n", win.width, win.height); + printf("\x1b[2J\x1b[H %u, %u\n", vui_win.width, vui_win.height); return 0; } -- cgit v1.2.3