summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-11-04 17:06:28 -0500
committerWormHeamer2025-11-04 17:06:28 -0500
commit9441c63a9fbb61aeece177214f0352c52c2338cc (patch)
treeb592302a0d67ff6bda7281e7d2ceed8c290690b2 /main.c
parent449adbac9263ef77d7fe134e1036f8435bf88d24 (diff)
scrolling scrolling
Diffstat (limited to 'main.c')
-rw-r--r--main.c123
1 files changed, 94 insertions, 29 deletions
diff --git a/main.c b/main.c
index 0aeb63d..fa0821d 100644
--- a/main.c
+++ b/main.c
@@ -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;