From 342886a098683a054c4cd15283d07f7d0c448bf9 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Tue, 9 Sep 2025 11:25:59 +1000 Subject: [PATCH] test custom curses implementation --- lib/cursed.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/cursed.h | 41 +++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 lib/cursed.c create mode 100644 lib/cursed.h diff --git a/lib/cursed.c b/lib/cursed.c new file mode 100644 index 0000000..49c17c6 --- /dev/null +++ b/lib/cursed.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + +#include "cursed.h" +#include "termios.h" + +struct s_state *glstate; + +PRIVATE inline int termenable(struct s_state *st) { + struct termios term; + + // if (!st) + // return 1; + + if (ioctl(0, TCGETS, &term) == -1) + return 1; + memcpy(&st->term, &term, sizeof(struct termios)); + // control characters + // term.c_cc[VMIN] = 1; + // term.c_cc[VTIME] = 0; + // io flags + term.c_iflag &= ~(IXON | INPCK | ICRNL | ISTRIP | BRKINT); + term.c_oflag &= ~(OPOST); // disable post-processing (using \r\n manually now) + term.c_cflag |= (CS8); + // misc flags + term.c_lflag &= ~(ECHO | ICANON | IEXTEN); + if (ioctl(0, TCSETS, &term)) + return 1; + + // unbuffer stdin + // if (setvbuf(stdin, NULL, _IOLBF, 0)) + // return 1; + + return 0; +} + +PRIVATE inline int termdisable(struct s_state *st) { + if (!st) + return 1; + + if (ioctl(0, TCSETS, &st->term)) + return 1; + + return 0; +} + +PRIVATE struct s_framebuffer *init_framebuffer(pos cols, pos rows) { + unsigned long int fbsz, bmsz; // framebuf + bitmap sizes + struct s_framebuffer *buf; +} + +PRIVATE struct s_state *init_state(void) { + struct s_state *st = (struct s_state*)malloc(sizeof(struct s_state)); + if (st == NULL) exit(1); // BUG: WARNING: TODO + return st; +} + +PUBLIC _INIT void initlib(void) { + // atexit(destroylib) + glstate = init_state(); + termenable(glstate); + // (volatile void)init_window(glstate, 90, 25); +} + +PUBLIC _FINI void destroylib(void) { + // if (glstate != NULL) + termdisable(glstate); +} + + + +int main(int argc, char **argv) { + // TODO: use STDIN_FILENO instead for 0 + char c, s[10]; + int pad; + while (read(STDIN_FILENO, &c, 1) == 1) { + sprintf(s, "%d", c); + pad = 3 - strlen(s); // max is 256 (strlen 3) + + printf("0x%.02hhx %s", c, s); + if (!iscntrl(c)) { + for (int i=0; i < pad; i++) + putchar(' '); + printf(" (%c)", c); + } + printf("\r\n"); + } + + return EXIT_SUCCESS; +} diff --git a/lib/cursed.h b/lib/cursed.h new file mode 100644 index 0000000..439f51c --- /dev/null +++ b/lib/cursed.h @@ -0,0 +1,41 @@ +#ifndef CURSED_H +#define CURSED_H + +#include +#include + +#define PACKED __attribute__((packed, aligned(1))) +#define PUBLIC __attribute((visibility("default"))) +#define PROTECTED __attribute__((visibility("hidden"))) +#define PRIVATE static + +#define _INIT __attribute__((constructor)) +#define _FINI __attribute__((destructor)) + +typedef unsigned char uid; // >= 8B +typedef unsigned short int pos; // >= 16B + +struct s_framebuffer { + pos *buf; // framebuffer + bool bitmap[]; +} PACKED; + +struct s_window { + uid id; + pos cols; + pos rows; + struct s_framebuffer frame; + + pos x; + pos y; +} PACKED; + +struct s_state { + struct termios term; +} PACKED; + +// === Public API === +PRIVATE struct s_framebuffer *init_framebuffer(pos cols, pos rows); +PUBLIC struct s_window *init_window(uid id, pos cols, pos rows); + +#endif /* CURSED_H */