aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/dvtm/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/dvtm/driver.c')
-rw-r--r--sys/cmd/dvtm/driver.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/sys/cmd/dvtm/driver.c b/sys/cmd/dvtm/driver.c
new file mode 100644
index 0000000..3e6a518
--- /dev/null
+++ b/sys/cmd/dvtm/driver.c
@@ -0,0 +1,335 @@
+#include <u.h>
+#include <libn.h>
+#include <vendor/unibilium.h>
+
+typedef struct RGB8 RGB8;
+typedef struct Pen Pen;
+typedef struct Term Term;
+
+struct ExtraInfo
+{
+ char *enteralt;
+ char *exitalt;
+
+ char *entermouse;
+ char *exitmouse;
+};
+
+static
+struct ExtraInfo vt200 =
+{
+ .enteralt = "\e[?1049h",
+ .exitalt = "\e[?1049l",
+
+ .entermouse = "\e[?1049h\e[?1006l",
+ .exitmouse = "\e[?1002l\e[?1006l",
+};
+
+struct RGB8
+{
+ uint8 r, g, b;
+};
+
+struct Pen
+{
+ uint bold : 1;
+ uint italic : 1;
+ uint reverse : 1;
+ uint strike : 1;
+ uint blink : 1;
+
+ /* colors */
+ uint color : 3;
+ union {
+ /* 256 color (legacy) */
+ struct {
+ sint fg : 9, bg : 9; /* 0 - 255 or COLOUR_DEFAULT */
+ } idx;
+ /* true color (modern) */
+ struct {
+ RGB8 fg, bg;
+ } rgb;
+ };
+};
+
+struct Term
+{
+ /* meta data */
+ char *name;
+ unibi_term *info;
+ struct {
+ uint altscreen : 1;
+ uint cursorvis : 1;
+ uint mouse : 1;
+ } mode;
+ struct {
+ uint bce : 1;
+ int colors;
+ } cap;
+
+ /* input capture */
+ // Input *input;
+
+ /* output display */
+ int nrow, ncol;
+
+ /* output raw text */
+ int fd;
+ struct {
+ char *c, b[512];
+ } buf;
+
+ struct {
+ int len;
+ char *b;
+ } tmp;
+
+ /* info */
+ struct {
+ /* Positioning */
+ char *cup; // cursor_address
+ char *vpa; // row_address == vertical position absolute
+ char *hpa; // column_address = horizontal position absolute
+
+ /* Moving */
+ char *cuu; char *cuu1; // Cursor Up
+ char *cud; char *cud1; // Cursor Down
+ char *cuf; char *cuf1; // Cursor Forward == Right
+ char *cub; char *cub1; // Cursor Backward == Left
+
+ /* Editing */
+ char *ich; char *ich1; // Insert Character
+ char *dch; char *dch1; // Delete Character
+ char *il; char *il1; // Insert Line
+ char *dl; char *dl1; // Delete Line
+ char *ech; // Erase Character
+ char *ed2; // Erase Data 2 == Clear screen
+ char *stbm; // Set Top/Bottom Margins
+
+ /* formatting */
+ char *sgr; // Select Graphic Rendition
+ char *sgr0; // Exit Attribute Mode
+ char *sgr_i0, *sgr_i1; // SGR italic off/on
+ char *sgr_fg; // SGR foreground colour
+ char *sgr_bg; // SGR background colour
+
+ // Mode setting/clearing
+ char *sm_csr; char *rm_csr; // Set/reset mode: Cursor visible
+ } esc;
+};
+
+// -----------------------------------------------------------------------
+// methods
+
+static
+char *
+ttmpbuf(Term *t, int len)
+{
+ if (t->tmp.len >= len)
+ return t->tmp.b;
+
+ /* TODO: error handling */
+ return (t->tmp.b = realloc(t->tmp.b, len));
+}
+
+void
+tflush(Term *t)
+{
+ if (t->fd != -1)
+ write(t->fd, t->buf.b, t->buf.c - t->buf.b);
+
+ t->buf.c = t->buf.b;
+}
+
+void
+twrite(Term *t, long len, char *s)
+{
+ int n;
+ if (!len)
+ len = strlen(s);
+
+ while (len > 0) {
+ n = MIN(len, arrend(t->buf.b) - t->buf.c);
+ memcpy(t->buf.c, s, n);
+ t->buf.c += n;
+ len -= n;
+ tflush(t);
+ }
+}
+
+static
+void
+tfmt(Term *t, char *esc, int n, ...)
+{
+ int i;
+ long len;
+ va_list args;
+ unibi_var_t param[9];
+ char buf[64], *c = buf;
+
+ if (!esc)
+ panicf("no terminfo escape string given");
+
+ va_start(args, n);
+ for (i = 0; i < arrlen(param) && i < n; i++)
+ param[i] = unibi_var_from_num(va_arg(args, int));
+ va_end(args);
+
+ len = unibi_run(esc, param, c, sizeof(buf));
+ if (len < arrlen(buf)) {
+ c = ttmpbuf(t, len);
+ unibi_run(esc, param, c, len);
+ }
+
+ twrite(t, len, c);
+}
+
+/* absolute move */
+int
+tgoto(Term *t, int row, int col)
+{
+ if (row != -1 && col != -1)
+ tfmt(t, t->esc.cup, 2, row, col);
+ else if (row != -1) {
+ if (!t->esc.vpa)
+ return 0;
+ tfmt(t, t->esc.vpa, 1, row);
+ } else if (col != -1) {
+ if (col == 0) {
+ twrite(t, 1, "\r");
+ return 1;
+ }
+ if (t->esc.hpa)
+ tfmt(t, t->esc.hpa, 1, col);
+ else if (t->esc.cuf) {
+ twrite(t, 1, "\r");
+ tfmt(t, t->esc.cuf, 1, col);
+ } else
+ return 0;
+ } else
+ return 0; /* unreachable */
+
+ return 1;
+}
+
+/* relative move */
+void
+tjump(Term *t, int down, int right)
+{
+ if (down == 1 && t->esc.cud1)
+ tfmt(t, t->esc.cud1, 0);
+ else if (down == -1 && t->esc.cuu1)
+ tfmt(t, t->esc.cuu1, 0);
+ else if (down > 0)
+ tfmt(t, t->esc.cud, 1, down);
+ else if (down < 0)
+ tfmt(t, t->esc.cuu, 1, -down);
+
+ if (right == 1 && t->esc.cuf1)
+ tfmt(t, t->esc.cuf1, 0);
+ else if (right == -1 && t->esc.cub1)
+ tfmt (t, t->esc.cub1, 0);
+ else if (right > 0)
+ tfmt(t, t->esc.cuf, 1, right);
+ else if( right < 0)
+ tfmt(t, t->esc.cub, 1, -right);
+}
+
+void
+tdel(Term *t, int num)
+{
+ char *c, buf[64];
+ if (num < 1)
+ return;
+
+ /* TODO: allow for not moving */
+ if (t->cap.bce) {
+ tfmt(t, t->esc.ech, 1, num);
+ tjump(t, 0, num);
+ } else {
+ c = buf;
+ memset(c, ' ', arrlen(buf));
+ while(num > 64) {
+ twrite(t, arrlen(buf), c);
+ num -= arrlen(buf);
+ }
+ twrite(t, num, c);
+ }
+}
+
+void
+tclear(Term *t)
+{
+ tfmt(t, t->esc.ed2, 0);
+}
+
+
+// -----------------------------------------------------------------------
+// database lookup
+
+static
+char*
+tryinfostr(Term *t, enum unibi_string s)
+{
+ char *val = (char*)unibi_get_str(t->info, s);
+ /* TODO: provide fallbacks */
+ return val;
+}
+
+static
+char*
+getinfostr(Term *t, enum unibi_string s)
+{
+ char *val = tryinfostr(t, s);
+ if (!val)
+ panicf("required term info string '%s' missing", unibi_name_str(s));
+
+ return val;
+}
+
+int
+main()
+{
+ Term t;
+
+ t.name = getenv("TERM");
+ t.info = unibi_from_term(t.name);
+
+ t.mode.mouse = 0;
+ t.mode.cursorvis = 1;
+ t.mode.altscreen = 0;
+
+ if (!t.info)
+ panicf("could not identify terminal");
+
+ t.esc.cup = getinfostr(&t, unibi_cursor_address);
+ t.esc.vpa = tryinfostr(&t, unibi_row_address);
+ t.esc.hpa = tryinfostr(&t, unibi_column_address);
+ t.esc.cuu = getinfostr(&t, unibi_parm_up_cursor);
+ t.esc.cuu1 = tryinfostr(&t, unibi_cursor_up);
+ t.esc.cud = getinfostr(&t, unibi_parm_down_cursor);
+ t.esc.cud1 = tryinfostr(&t, unibi_cursor_down);
+ t.esc.cuf = getinfostr(&t, unibi_parm_right_cursor);
+ t.esc.cuf1 = tryinfostr(&t, unibi_cursor_right);
+ t.esc.cub = getinfostr(&t, unibi_parm_left_cursor);
+ t.esc.cub1 = tryinfostr(&t, unibi_cursor_left);
+ t.esc.ich = getinfostr(&t, unibi_parm_ich);
+ t.esc.ich1 = tryinfostr(&t, unibi_insert_character);
+ t.esc.dch = getinfostr(&t, unibi_parm_dch);
+ t.esc.dch1 = tryinfostr(&t, unibi_delete_character);
+ t.esc.il = getinfostr(&t, unibi_parm_insert_line);
+ t.esc.il1 = tryinfostr(&t, unibi_insert_line);
+ t.esc.dl = getinfostr(&t, unibi_parm_delete_line);
+ t.esc.dl1 = tryinfostr(&t, unibi_delete_line);
+ t.esc.ech = getinfostr(&t, unibi_erase_chars);
+ t.esc.ed2 = getinfostr(&t, unibi_clear_screen);
+ t.esc.stbm = getinfostr(&t, unibi_change_scroll_region);
+ t.esc.sgr = getinfostr(&t, unibi_set_attributes);
+ t.esc.sgr0 = getinfostr(&t, unibi_exit_attribute_mode);
+ t.esc.sgr_i0 = tryinfostr(&t, unibi_exit_italics_mode);
+ t.esc.sgr_i1 = tryinfostr(&t, unibi_enter_italics_mode);
+ t.esc.sgr_fg = getinfostr(&t, unibi_set_a_foreground);
+ t.esc.sgr_bg = getinfostr(&t, unibi_set_a_background);
+ t.esc.sm_csr = getinfostr(&t, unibi_cursor_normal);
+ t.esc.rm_csr = getinfostr(&t, unibi_cursor_invisible);
+}