diff options
| -rw-r--r-- | main.c | 123 |
1 files changed, 94 insertions, 29 deletions
@@ -11,9 +11,11 @@ #include <sys/ioctl.h> #include <signal.h> #include <poll.h> +#include <time.h> /* TODO * + * - one fwrite() per blit * - utf-8 input * - arrow keys * - KEY_RESIZE or draw callback @@ -80,7 +82,10 @@ typedef struct { unsigned width, height; VuiBuffer buf1, buf2; VuiBuffer *front, *back; + void (*redraw_fn)(void *ctx); + void *redraw_ctx; int redraw_all; + int scroll_x, scroll_y; } VuiWindow; static struct termios vui_init_stdin_tos, vui_init_stdout_tos, vui_raw_stdin_tos, vui_raw_stdout_tos; @@ -173,6 +178,13 @@ void vui_curs_vis(int vis) { } } +void vui_on_sigwinch(int _) { + vui_adjust(); + if (vui_win.redraw_fn) { + vui_win.redraw_fn(vui_win.redraw_ctx); + } +} + void vui_init(void) { tcgetattr(STDIN_FILENO, &vui_init_stdin_tos); vui_raw_stdin_tos = vui_init_stdin_tos; @@ -185,6 +197,7 @@ void vui_init(void) { tcsetattr(STDOUT_FILENO, TCSANOW, &vui_raw_stdout_tos); vui_adjust(); + signal(SIGWINCH, vui_on_sigwinch); } @@ -287,6 +300,9 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) { unsigned vui_changes = 0; unsigned vui_max_change = 0; unsigned vui_repainted = 0; + +void vui_scroll_buf(VuiBuffer *b, int dx, int dy); + void vui_blit(void) { VuiBuffer *front = vui_win.front; VuiBuffer *back = vui_win.back; @@ -311,6 +327,47 @@ void vui_blit(void) { vui_max_change = 0; vui_repainted = 0; unsigned cur_x = 0, cur_y = 0; + + + /* TODO: + * + * Scroll without repainting whole screen: + * + * - \x1b[#L to insert blank lines + * - \x1b[#@ to insert blank chars + * - \x1b[#M to delete lines + * - \x1b[#P to delete chars + * + */ + + if (vui_win.scroll_x || vui_win.scroll_y) { + if (vui_win.scroll_x < 0) { + for (unsigned y = 0; y < vui_win.height; y++) { + curs_move(cur_x, cur_y, 0, y); + printf("\x1b[%dP", -vui_win.scroll_x); + cur_y = y; + } + } else if (vui_win.scroll_x > 0) { + for (unsigned y = 0; y < vui_win.height; y++) { + curs_move(cur_x, cur_y, 0, y); + printf("\x1b[%d@", vui_win.scroll_x); + cur_y = y; + } + } + if (vui_win.scroll_y < 0) { + curs_move(cur_x, cur_y, 0, 0); + cur_x = (cur_y = 0); + printf("\x1b[%dM", -vui_win.scroll_y); + } else if (vui_win.scroll_y > 0) { + curs_move(cur_x, cur_y, 0, 0); + cur_x = (cur_y = 0); + printf("\x1b[%dL", vui_win.scroll_y); + } + vui_scroll_buf(back, vui_win.scroll_x, vui_win.scroll_y); + vui_win.scroll_x = 0; + vui_win.scroll_y = 0; + } + for (unsigned y = 0; y < vui_win.height; y++) { unsigned x = 0; while (x < vui_win.width) { @@ -353,11 +410,13 @@ void vui_chr(int x, int y, char c) { } int vui_avprintf(int x, int y, VuiAttr a, const char *fmt, va_list ap) { + //return 0; va_list ap2; va_copy(ap2, ap); int n = vsnprintf(NULL, 0, fmt, ap); if (x < 0) x = vui_win.width + x - (n - 1); if (y < 0) y = vui_win.height + y; + if (x >= vui_win.width || y >= vui_win.height) return n; if (n > 0) { char buf[n + 1]; vsnprintf(buf, n + 1, fmt, ap2); @@ -385,11 +444,6 @@ int vui_printf(int x, int y, const char *fmt, ...) { return r; } -void on_sigwinch(int _) { - vui_adjust(); - vui_blit(); -} - int wait_for_input(int fd, int ms) { return poll(&(struct pollfd) { .fd = fd, .events = POLLIN }, 1, ms); } @@ -441,26 +495,46 @@ void vui_scroll_buf(VuiBuffer *b, int dx, int dy) { void vui_scroll(int dx, int dy) { vui_scroll_buf(vui_win.front, dx, dy); + vui_win.scroll_x += dx; + vui_win.scroll_y += dy; +} + +int x = 0, y = 0; +int dx = 0, dy = 0; +int camx = 0, camy = 0; +int C = '*'; +unsigned frame = 0; +int half_y = 1; + +void draw(void *ctx) { + (void)ctx; + + vui_chra(x, y, C, ((x + y) & 0xf) | BG_BBLUE); + vui_chra(x-1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); + vui_chra(x+1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); + 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)", 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); + + vui_blit(); } int main(int argc, const char **argv) { vui_init(); vui_curs_vis(0); - signal(SIGWINCH, on_sigwinch); - int x = 0, y = 0; - int dx = 0, dy = 0; - int camx = 0, camy = 0; - int C = '*'; - unsigned frame = 0; - int half_y = 0; + for (;;) { frame++; //camx += dx; x += dx; - if ((frame & 1) || !(half_y)) { - // camy += dy; - y += dy; + int ydy = dy; + if (half_y) { + ydy = (frame & 1) ? (dy / 2) : dy - (dy / 2); } + y += ydy; unsigned left = 32; unsigned right = vui_win.width - (left + 1); @@ -484,8 +558,9 @@ int main(int argc, const char **argv) { */ static int paused = 0; + vui_win.redraw_fn = draw; -#if 1 +#if 0 /* weird cellular automata */ if (!paused) { // int dx = 0, dy = 0; /* shadow on purpose */ @@ -532,21 +607,11 @@ int main(int argc, const char **argv) { } } #endif - - vui_chra(x, y, C, ((x + y) & 0xf) | BG_BBLUE); - vui_chra(x-1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); - vui_chra(x+1, y, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE); - 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)", 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(); + draw(NULL); - if (!wait_for_input(STDIN_FILENO, 20)) continue; + clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) { .tv_nsec = 15 * 1000000 }, NULL); + if (!wait_for_input(STDIN_FILENO, 0)) continue; int c = getchar(); if (c == 'q') break; |
