From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- sys/libterm/term.c | 489 ----------------------------------------------------- 1 file changed, 489 deletions(-) delete mode 100644 sys/libterm/term.c (limited to 'sys/libterm/term.c') diff --git a/sys/libterm/term.c b/sys/libterm/term.c deleted file mode 100644 index 11591fc..0000000 --- a/sys/libterm/term.c +++ /dev/null @@ -1,489 +0,0 @@ -#include "term.h" - -#include -#include - -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", -}; - -static Term *sigwinchhead; - -// ----------------------------------------------------------------------- -// 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* -guessinfostr(Term *t, enum unibi_string s, char *guess) -{ - char *val = (char*)unibi_get_str(t->info, s); - if (!val) - return guess; - 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; -} - -static -char * -tryextrastr(Term *t, char *name) -{ - const char *nm; - size_t max = unibi_count_ext_str(t->info); - for (size_t i = 0; i < max; i++) { - nm = unibi_get_ext_str_name(t->info, i); - if (nm && !strcmp(nm, name)) { - return (char *)nm; - } - } - return nil; -} - -static -char * -guessextrastr(Term *t, char *name, char *guess) -{ - char *s; - if ((s = tryextrastr(t, name))) - return s; - - return guess; -} - -/* formats escape strings and writes to output */ -static void tfmt(Term *t, char *esc, int n, ...); -static void tclear(Term *t); - -// ----------------------------------------------------------------------- -// exported term 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 twrite(Term *t, long len, char *s); -void tlistensigwinch(Term *t); - -Term* -tmake(void) -{ - Term *t; - - t = calloc(1, sizeof(*t)); - - /* meta data */ - t->name = getenv("TERM"); - t->info = unibi_from_term(t->name); - if (!t->info) - panicf("could not identify terminal"); - - t->fd = 1; // stdout - tlistensigwinch(t); - - t->mode.mouse = 0; - t->mode.cursorvis = 1; - t->mode.altscreen = 0; - - t->cap.colors = unibi_get_num(t->info, unibi_max_colors); - t->cap.bce = unibi_get_bool(t->info, unibi_back_color_erase); - - /* initialize root window (get current size)*/ - struct winsize ws = { 0 }; - if (ioctl(t->fd, TIOCGWINSZ, &ws) == 1) - goto bad; - - t->root = wmake(nil, 0, 0, ws.ws_col, ws.ws_row, 0); - - t->root->curvis = 1; - t->root->blink = 0; - - t->pen = (Pen){ - .state = PenNormal, - .col = {.fg = -1, .bg = -1}, - }; - - /* fill in output buffers */ - t->buf.c = t->buf.b; - t->tmp.b = nil; - t->tmp.len = 0; - - /* get all term info format strings */ - 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); - - /* extensions to terminfo */ - t->esc.ext.rgbf = guessextrastr(t, "setrgbf", "\x1b[38;2;%p1%d;%p2%d;%p3%dm"); - t->esc.ext.rgbb = guessextrastr(t, "setrgbb", "\x1b[48;2;%p1%d;%p2%d;%p3%dm"); - - return t; - -bad: - panicf("failed to initialize terminal instance"); - free(t); - return nil; -} - -void -tfree(Term *t) -{ - if (t->mode.mouse) - twrite(t, 0, vt200.exitmouse); - if (!t->mode.cursorvis) - tfmt(t, t->esc.rm_csr, 0); - if (t->mode.altscreen) - twrite(t, 0, vt200.exitalt); - - tfmt(t, t->esc.sgr0, 0); - tclear(t); - free(t); -} - -/* handle resize events */ -void -tresize(Term *t) -{ - if (t->fd == -1) - return; - - struct winsize ws = { 0 }; - if (ioctl(t->fd, TIOCGWINSZ, &ws) == 1) - return; - - printf("[%d,%d]\n", ws.ws_col, ws.ws_row); - if (t->root->w != ws.ws_col || t->root->h != ws.ws_row) - wresize(t->root, ws.ws_col, ws.ws_row); -} - -static -void -sigwinch(int num) -{ - Term *it; - for (it = sigwinchhead; it; it = it->link) - tresize(it); -} - -void -tlistensigwinch(Term *t) -{ - sigset_t new, old; - Term *it; - - sigemptyset(&new); - sigaddset(&new, SIGWINCH); - sigprocmask(SIG_BLOCK, &new, &old); - - if (!sigwinchhead) { - sigaction(SIGWINCH, &(struct sigaction){ .sa_handler = sigwinch }, nil); - sigwinchhead = t; - } else { - it = sigwinchhead; - while (it->link) - it = it->link; - it->link = t; - } - - sigprocmask(SIG_SETMASK, &old, nil); -} - -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); - -loop: - n = MIN(len, arrend(t->buf.b) - t->buf.c); - memcpy(t->buf.c, s, n); - t->buf.c += n; - len -= n; - if (len) { - tflush(t); - goto loop; - } -} - -void -tsetpen(Term *t, Pen new) -{ - int c; - ushort ic, in; - Pen cur = t->pen; - if (!memcmp(&new, &cur, sizeof(new))) - return; - - /* attributes */ - tfmt(t, t->esc.sgr, 9, - 0, /* standout */ - new.state & PenUnderline, - new.state & PenReverse, - new.state & PenBlink, - new.state & PenDim, - new.state & PenBold, - new.state & PenInvis, - 0, /* protect */ - 0); /* alt */ - - ic = cur.state & PenItalic; - in = new.state & PenItalic; - if (ic & ~in) - tfmt(t, t->esc.sgr_i0, 0); - else if (~ic & in) - tfmt(t, t->esc.sgr_i1, 0); - - /* fg/bg color */ - /* TODO: add a check for if the terminal supports true color */ - /* TODO: deal w/ negative indices properly */ - if (new.state & PenRGB) { - tfmt(t, t->esc.ext.rgbf, 3, new.rgb.fg.r, new.rgb.fg.g, new.rgb.fg.b); - tfmt(t, t->esc.ext.rgbb, 3, new.rgb.bg.r, new.rgb.bg.g, new.rgb.bg.b); - } else { - tfmt(t, t->esc.sgr_fg, 1, new.col.fg); - tfmt(t, t->esc.sgr_bg, 1, new.col.bg); - } - - t->pen = new; -} - -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 */ -static -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 */ -static -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); -} - -static -void -tclear(Term *t) -{ - tfmt(t, t->esc.ed2, 0); -} - -void -tblit(Term *t, Window *win) -{ - int r, c, n, j; - Row *row; - char u[UTFmax+1] = {0}; - - j = 0; - tgoto(t, win->top, win->left); - for (r = 0; r < win->h; r++) { - row = win->row + r; - if (!row->dirty) { - j++; - continue; - } - - if (j) { - tjump(t, j, 0); - j = 0; - } - - for (c = 0; c < win->w; c++) { - tsetpen(t, row->cells[c].pen); - n = utf8·runetobyte(u, &row->cells[c].txt); - twrite(t, n, u); - } - - row->dirty = 0; - } - - tflush(t); -} - -// ----------------------------------------------------------------------- -// testing - -int -main() -{ - int i; - Term *t; - Window *win; - - t = tmake(); - win = t->root; - tclear(t); - - win->pen = (Pen){ - .state = PenNormal, - .col = {.fg=-1, .bg=-1}, - }; - for (i = 0; i < 2000; i++) - wputrune(win, 'a'); - - tblit(t, win); - - win->cur.row = 10; - win->cur.col = 0; - - win->pen = (Pen){ - .state=PenNormal|PenRGB, - .rgb={.fg={200, 100, 100}, .bg={0, 0, 0} }, - }; - - for (i = 0; i < 500; i++) - wputrune(win, 'b'); - - tblit(t, win); - - sleep(5); - wscroll(win, 10); - tblit(t, win); - sleep(5); - - tfree(t); -} -- cgit v1.2.1