summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-11-04 15:16:12 -0500
committerWormHeamer2025-11-04 15:16:12 -0500
commit90b67b81fae38540b7a9257d23c4b50820ca5b1d (patch)
treedcac6f599bc12bf92920866877b0ee1b75c7a8a8 /main.c
parent405f0f393c3ea5b126aafa9e7a6da8c51a1b950b (diff)
stuff, add vui_scroll
Diffstat (limited to 'main.c')
-rw-r--r--main.c243
1 files changed, 155 insertions, 88 deletions
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;
}