diff options
author | Nicholas Noll <nbnoll@eml.cc> | 2020-06-10 14:49:45 -0700 |
---|---|---|
committer | Nicholas Noll <nbnoll@eml.cc> | 2020-06-10 14:49:45 -0700 |
commit | e41eb5691417ecacade402759231f64778e3147f (patch) | |
tree | c28606655266f2702a30277f283e83b62f9a2cbb /sys/cmd/dvtm/vt.c | |
parent | 5daf8d56cdf6aecd1b7301c622c3e35eaa47bd42 (diff) |
checkin: massive restructuring of dvtm
Diffstat (limited to 'sys/cmd/dvtm/vt.c')
-rw-r--r-- | sys/cmd/dvtm/vt.c | 1258 |
1 files changed, 343 insertions, 915 deletions
diff --git a/sys/cmd/dvtm/vt.c b/sys/cmd/dvtm/vt.c index c48a84f..efaa980 100644 --- a/sys/cmd/dvtm/vt.c +++ b/sys/cmd/dvtm/vt.c @@ -1,23 +1,15 @@ /* See license for details */ #include <u.h> +#include <libn.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> #include <langinfo.h> -#include <limits.h> #include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> +#include <termios.h> + #include <sys/ioctl.h> #include <sys/types.h> -#include <termios.h> -#include <wchar.h> + +#include "buffer.h" #if defined(__linux__) || defined(__CYGWIN__) # include <pty.h> @@ -27,602 +19,122 @@ # include <util.h> #endif -#include "vt.h" - -#ifndef NCURSES_ATTR_SHIFT -# define NCURSES_ATTR_SHIFT 8 -#endif - -#ifndef NCURSES_ACS -# ifdef PDCURSES -# define NCURSES_ACS(c) (acs_map[(uchar)(c)]) -# else /* BSD curses */ -# define NCURSES_ACS(c) (_acs_map[(uchar)(c)]) -# endif -#endif - -#ifdef NCURSES_VERSION - -#ifndef NCURSES_EXT_COLORS -# define NCURSES_EXT_COLORS 0 -#endif - -#if !NCURSES_EXT_COLORS -# define MAX_COLOR_PAIRS MIN(COLOR_PAIRS, 256) -#endif - -#endif - -#ifndef MAX_COLOR_PAIRS -# define MAX_COLOR_PAIRS COLOR_PAIRS -#endif - -#if defined _AIX && defined CTRL -# undef CTRL -#endif -#ifndef CTRL -# define CTRL(k) ((k) & 0x1F) -#endif - #define IS_CONTROL(ch) !((ch) & 0xffffff60UL) -static bool is_utf8, has_default_colors; -static short color_pairs_reserved, color_pairs_max, color_pair_current; -static short *color2palette, default_fg, default_bg; -static char vt_term[32]; - -typedef struct { - wchar_t text; - attr_t attr; - short fg; - short bg; -} Cell; - -typedef struct { - Cell *cells; - uint dirty:1; -} Row; - -/* Buffer holding the current terminal window content (as an array) as well - * as the scroll back buffer content (as a circular/ring buffer). - * - * If new content is added to terminal the view port slides down and the - * previously top most line is moved into the scroll back buffer at postion - * scroll_index. This index will eventually wrap around and thus overwrite - * the oldest lines. - * - * In the scenerio below a scroll up has been performed. That is 'scroll_above' - * lines still lie above the current view port. Further scrolling up will show - * them. Similarly 'scroll_below' is the amount of lines below the current - * viewport. - * - * The function buffer_boundary sets the row pointers to the start/end range - * of the section delimiting the region before/after the viewport. The functions - * buffer_row_{first,last} return the first/last logical row. And - * buffer_row_{next,prev} allows to iterate over the logical lines in either - * direction. - * - * scroll back buffer - * - * scroll_buf->+----------------+-----+ - * | | | ^ \ - * | before | | | | - * current terminal content | viewport | | | | - * | | | | - * +----------------+-----+\ | | | s > scroll_above - * ^ | | i | \ | | i | c | - * | | | n | \ | | n | r | - * | | v | \ | | v | o | - * r | | i | \ | | i | l / - * o | viewport | s | >|<- scroll_index | s | l \ - * w | | i | / | | i | | - * s | | b | / | after | b | s > scroll_below - * | | l | / | viewport | l | i | - * v | | e | / | | e | z / - * +----------------+-----+/ | unused | | e - * <- maxcols -> | scroll back | | - * <- cols -> | buffer | | | - * | | | | - * | | | v - * roll_buf + scroll_size->+----------------+-----+ - * <- maxcols -> - * <- cols -> - */ -typedef struct { - Row *lines; /* array of Row pointers of size 'rows' */ - Row *curs_row; /* row on which the cursor currently resides */ - Row *scroll_buf; /* a ring buffer holding the scroll back content */ - Row *scroll_top; /* row in lines where scrolling region starts */ - Row *scroll_bot; /* row in lines where scrolling region ends */ - bool *tabs; /* a boolean flag for each column whether it is a tab */ - int scroll_size; /* maximal capacity of scroll back buffer (in lines) */ - int scroll_index; /* current index into the ring buffer */ - int scroll_above; /* number of lines above current viewport */ - int scroll_below; /* number of lines below current viewport */ - int rows, cols; /* current dimension of buffer */ - int maxcols; /* allocated cells (maximal cols over time) */ - attr_t curattrs, savattrs; /* current and saved attributes for cells */ - int curs_col; /* current cursor column (zero based) */ - int curs_srow, curs_scol; /* saved cursor row/colmn (zero based) */ - short curfg, curbg; /* current fore and background colors */ - short savfg, savbg; /* saved colors */ -} Buffer; +typedef struct Vt Vt; struct Vt { - Buffer buffer_normal; /* normal screen buffer */ - Buffer buffer_alternate; /* alternate screen buffer */ - Buffer *buffer; /* currently active buffer (one of the above) */ - attr_t defattrs; /* attributes to use for normal/empty cells */ - short deffg, defbg; /* colors to use for back normal/empty cells (white/black) */ - int pty; /* master side pty file descriptor */ - pid_t pid; /* process id of the process running in this vt */ + Buffer buf[2]; /* normal & alternative screen buffer */ + Buffer *buffer; /* currently active buffer (one of the above) */ + Pen pen; /* default pen */ + int pty; /* master side pty file descriptor */ + pid_t pid; /* process id of the process running in this vt */ /* flags */ - uint seen_input:1; - uint insert:1; - uint escaped:1; - uint curshid:1; - uint curskeymode:1; - uint bell:1; - uint relposmode:1; - uint mousetrack:1; - uint graphmode:1; - uint savgraphmode:1; + char title[256]; /* xterm style window title */ + void *data; /* user supplied data */ + uint seen_input : 1; + uint insert : 1; + uint escaped : 1; + uint curshid : 1; + uint curskeymode : 1; + uint bell : 1; + uint relposmode : 1; + uint mousetrack : 1; + uint graphmode : 1; + uint savgraphmode : 1; bool charsets[2]; /* buffers and parsing state */ char rbuf[BUFSIZ]; char ebuf[BUFSIZ]; uint rlen, elen; - int srow, scol; /* last known offset to display start row, start column */ - char title[256]; /* xterm style window title */ - vt_title_handler_t title_handler; /* hook which is called when title changes */ - vt_urgent_handler_t urgent_handler; /* hook which is called upon bell */ - void *data; /* user supplied data */ -}; - -static const char *keytable[KEY_MAX+1] = { - [KEY_ENTER] = "\r", - ['\n'] = "\n", - /* for the arrow keys the CSI / SS3 sequences are not stored here - * because they depend on the current cursor terminal mode - */ - [KEY_UP] = "A", - [KEY_DOWN] = "B", - [KEY_RIGHT] = "C", - [KEY_LEFT] = "D", -#ifdef KEY_SUP - [KEY_SUP] = "\e[1;2A", -#endif -#ifdef KEY_SDOWN - [KEY_SDOWN] = "\e[1;2B", -#endif - [KEY_SRIGHT] = "\e[1;2C", - [KEY_SLEFT] = "\e[1;2D", - [KEY_BACKSPACE] = "\177", - [KEY_IC] = "\e[2~", - [KEY_DC] = "\e[3~", - [KEY_PPAGE] = "\e[5~", - [KEY_NPAGE] = "\e[6~", - [KEY_HOME] = "\e[7~", - [KEY_END] = "\e[8~", - [KEY_BTAB] = "\e[Z", - [KEY_SUSPEND] = "\x1A", /* Ctrl+Z gets mapped to this */ - [KEY_F(1)] = "\e[11~", - [KEY_F(2)] = "\e[12~", - [KEY_F(3)] = "\e[13~", - [KEY_F(4)] = "\e[14~", - [KEY_F(5)] = "\e[15~", - [KEY_F(6)] = "\e[17~", - [KEY_F(7)] = "\e[18~", - [KEY_F(8)] = "\e[19~", - [KEY_F(9)] = "\e[20~", - [KEY_F(10)] = "\e[21~", - [KEY_F(11)] = "\e[23~", - [KEY_F(12)] = "\e[24~", - [KEY_F(13)] = "\e[23~", - [KEY_F(14)] = "\e[24~", - [KEY_F(15)] = "\e[25~", - [KEY_F(16)] = "\e[26~", - [KEY_F(17)] = "\e[28~", - [KEY_F(18)] = "\e[29~", - [KEY_F(19)] = "\e[31~", - [KEY_F(20)] = "\e[32~", - [KEY_F(21)] = "\e[33~", - [KEY_F(22)] = "\e[34~", - [KEY_RESIZE] = "", -#ifdef KEY_EVENT - [KEY_EVENT] = "", -#endif + int srow, scol; /* last known offset to display start row, start column */ }; -static void puttab(Vt *t, int count); -static void process_nonprinting(Vt *t, wchar_t wc); -static void send_curs(Vt *t); - -const static -attr_t -build_attrs(attr_t curattrs) -{ - return ((curattrs & ~A_COLOR) | COLOR_PAIR(curattrs & 0xff)) - >> NCURSES_ATTR_SHIFT; -} - -static -void -row_set(Row *row, int start, int len, Buffer *t) -{ - Cell cell = { - .text = L'\0', - .attr = t ? build_attrs(t->curattrs) : 0, - .fg = t ? t->curfg : -1, - .bg = t ? t->curbg : -1, - }; - - for (int i = start; i < len + start; i++) - row->cells[i] = cell; - row->dirty = true; -} - -static -void -row_roll(Row *start, Row *end, int count) -{ - int n = end - start; - - count %= n; - if (count < 0) - count += n; - - if (count) { - char buf[count * sizeof(Row)]; - memcpy(buf, start, count * sizeof(Row)); - memmove(start, start + count, (n - count) * sizeof(Row)); - memcpy(end - count, buf, count * sizeof(Row)); - for (Row *row = start; row < end; row++) - row->dirty = true; - } -} - -static -void -buffer_clear(Buffer *b) -{ - Cell cell = { - .text = L'\0', - .attr = A_NORMAL, - .fg = -1, - .bg = -1, - }; - - for (int i = 0; i < b->rows; i++) { - Row *row = b->lines + i; - for (int j = 0; j < b->cols; j++) { - row->cells[j] = cell; - row->dirty = true; - } - } -} - -static -void -buffer_free(Buffer *b) -{ - for (int i = 0; i < b->rows; i++) - free(b->lines[i].cells); - free(b->lines); - for (int i = 0; i < b->scroll_size; i++) - free(b->scroll_buf[i].cells); - free(b->scroll_buf); - free(b->tabs); -} - -static -void -buffer_scroll(Buffer *b, int s) -{ - /* work in screenfuls */ - int ssz = b->scroll_bot - b->scroll_top; - if (s > ssz) { - buffer_scroll(b, ssz); - buffer_scroll(b, s - ssz); - return; - } - if (s < -ssz) { - buffer_scroll(b, -ssz); - buffer_scroll(b, s + ssz); - return; - } - - b->scroll_above += s; - if (b->scroll_above >= b->scroll_size) - b->scroll_above = b->scroll_size; - - if (s > 0 && b->scroll_size) { - for (int i = 0; i < s; i++) { - Row tmp = b->scroll_top[i]; - b->scroll_top[i] = b->scroll_buf[b->scroll_index]; - b->scroll_buf[b->scroll_index] = tmp; - - b->scroll_index++; - if (b->scroll_index == b->scroll_size) - b->scroll_index = 0; - } - } - row_roll(b->scroll_top, b->scroll_bot, s); - if (s < 0 && b->scroll_size) { - for (int i = (-s) - 1; i >= 0; i--) { - b->scroll_index--; - if (b->scroll_index == -1) - b->scroll_index = b->scroll_size - 1; - - Row tmp = b->scroll_top[i]; - b->scroll_top[i] = b->scroll_buf[b->scroll_index]; - b->scroll_buf[b->scroll_index] = tmp; - b->scroll_top[i].dirty = true; - } - } -} - -static -void -buffer_resize(Buffer *b, int rows, int cols) -{ - Row *lines = b->lines; - - if (b->rows != rows) { - if (b->curs_row >= lines + rows) { - /* scroll up instead of simply chopping off bottom */ - buffer_scroll(b, (b->curs_row - b->lines) - rows + 1); - } - while (b->rows > rows) { - free(lines[b->rows - 1].cells); - b->rows--; - } - - lines = realloc(lines, sizeof(Row) * rows); - } - - if (b->maxcols < cols) { - for (int row = 0; row < b->rows; row++) { - lines[row].cells = realloc(lines[row].cells, sizeof(Cell) * cols); - if (b->cols < cols) - row_set(lines + row, b->cols, cols - b->cols, nil); - lines[row].dirty = true; - } - Row *sbuf = b->scroll_buf; - for (int row = 0; row < b->scroll_size; row++) { - sbuf[row].cells = realloc(sbuf[row].cells, sizeof(Cell) * cols); - if (b->cols < cols) - row_set(sbuf + row, b->cols, cols - b->cols, nil); - } - b->tabs = realloc(b->tabs, sizeof(*b->tabs) * cols); - for (int col = b->cols; col < cols; col++) - b->tabs[col] = !(col & 7); - b->maxcols = cols; - b->cols = cols; - } else if (b->cols != cols) { - for (int row = 0; row < b->rows; row++) - lines[row].dirty = true; - b->cols = cols; - } - - int deltarows = 0; - if (b->rows < rows) { - while (b->rows < rows) { - lines[b->rows].cells = calloc(b->maxcols, sizeof(Cell)); - row_set(lines + b->rows, 0, b->maxcols, b); - b->rows++; - } - - /* prepare for backfill */ - if (b->curs_row >= b->scroll_bot - 1) { - deltarows = b->lines + rows - b->curs_row - 1; - if (deltarows > b->scroll_above) - deltarows = b->scroll_above; - } - } +/* forward declares */ - b->curs_row += lines - b->lines; - b->scroll_top = lines; - b->scroll_bot = lines + rows; - b->lines = lines; +void vt·noscroll(Vt *t); +void vt·dirty(Vt *t); +void vt·scroll(Vt *t, int rows); - /* perform backfill */ - if (deltarows > 0) { - buffer_scroll(b, -deltarows); - b->curs_row += deltarows; - } -} +static void puttab(Vt *t, int count); +static void process_nonprinting(Vt *t, rune r); +static void sendcurs(Vt *t); -static -bool -buffer_init(Buffer *b, int rows, int cols, int scroll_size) -{ - b->curattrs = A_NORMAL; /* white text over black background */ - b->curfg = b->curbg = -1; - if (scroll_size < 0) - scroll_size = 0; - if (scroll_size && !(b->scroll_buf = calloc(scroll_size, sizeof(Row)))) - return false; - b->scroll_size = scroll_size; - buffer_resize(b, rows, cols); - return true; -} +/* globals */ +static int isutf8; +static char vtname[36]; static void -buffer_boundry(Buffer *b, Row **bs, Row **be, Row **as, Row **ae) -{ - if (bs) - *bs = nil; - if (be) - *be = nil; - if (as) - *as = nil; - if (ae) - *ae = nil; - if (!b->scroll_size) - return; - - if (b->scroll_above) { - if (bs) - *bs = &b->scroll_buf[(b->scroll_index - b->scroll_above + b->scroll_size) % b->scroll_size]; - if (be) - *be = &b->scroll_buf[(b->scroll_index-1 + b->scroll_size) % b->scroll_size]; - } - if (b->scroll_below) { - if (as) - *as = &b->scroll_buf[b->scroll_index]; - if (ae) - *ae = &b->scroll_buf[(b->scroll_index + b->scroll_below-1) % b->scroll_size]; - } -} - -static -Row * -buffer_row_first(Buffer *b) { - Row *bstart; - if (!b->scroll_size || !b->scroll_above) - return b->lines; - buffer_boundry(b, &bstart, nil, nil, nil); - return bstart; -} - -static -Row * -buffer_row_last(Buffer *b) { - Row *aend; - if (!b->scroll_size || !b->scroll_below) - return b->lines + b->rows - 1; - buffer_boundry(b, nil, nil, nil, &aend); - return aend; -} - -static -Row * -buffer_row_next(Buffer *b, Row *row) -{ - Row *before_start, *before_end, *after_start, *after_end; - Row *first = b->lines, *last = b->lines + b->rows - 1; - - if (!row) - return nil; - - buffer_boundry(b, &before_start, &before_end, &after_start, &after_end); - - if (row >= first && row < last) - return ++row; - if (row == last) - return after_start; - if (row == before_end) - return first; - if (row == after_end) - return nil; - if (row == &b->scroll_buf[b->scroll_size - 1]) - return b->scroll_buf; - return ++row; -} - -static -Row * -buffer_row_prev(Buffer *b, Row *row) +cclamp(Vt *t) { - Row *before_start, *before_end, *after_start, *after_end; - Row *first = b->lines, *last = b->lines + b->rows - 1; - - if (!row) - return nil; - - buffer_boundry(b, &before_start, &before_end, &after_start, &after_end); + Buffer *b = t->buffer; + Row *lines = t->relposmode ? b->scroll.top : b->lines; + int rows = t->relposmode ? b->scroll.bot - b->scroll.top : b->rows; - if (row > first && row <= last) - return --row; - if (row == first) - return before_end; - if (row == before_start) - return nil; - if (row == after_start) - return last; - if (row == b->scroll_buf) - return &b->scroll_buf[b->scroll_size - 1]; - return --row; + if (b->crow < lines) + b->crow = lines; + if (b->crow >= lines + rows) + b->crow = lines + rows - 1; + if (b->ccol < 0) + b->ccol = 0; + if (b->ccol >= b->cols) + b->ccol = b->cols - 1; } static void -cursor_clamp(Vt *t) +clinedown(Vt *t) { Buffer *b = t->buffer; - Row *lines = t->relposmode ? b->scroll_top : b->lines; - int rows = t->relposmode ? b->scroll_bot - b->scroll_top : b->rows; - - if (b->curs_row < lines) - b->curs_row = lines; - if (b->curs_row >= lines + rows) - b->curs_row = lines + rows - 1; - if (b->curs_col < 0) - b->curs_col = 0; - if (b->curs_col >= b->cols) - b->curs_col = b->cols - 1; -} - -static -void -cursor_line_down(Vt *t) -{ - Buffer *b = t->buffer; - row_set(b->curs_row, b->cols, b->maxcols - b->cols, nil); - b->curs_row++; - if (b->curs_row < b->scroll_bot) + zero(b->crow, b->cols, b->maxcols - b->cols); + b->crow++; + if (b->crow < b->scroll.bot) return; - vt_noscroll(t); + vt·noscroll(t); - b->curs_row = b->scroll_bot - 1; - buffer_scroll(b, 1); - row_set(b->curs_row, 0, b->cols, b); + b->crow = b->scroll.bot - 1; + bscroll(b, 1); + zero(b->crow, 0, b->cols); } static void -cursor_save(Vt *t) +csave(Vt *t) { Buffer *b = t->buffer; - b->curs_srow = b->curs_row - b->lines; - b->curs_scol = b->curs_col; + b->scrow = b->crow - b->lines; + b->sccol = b->ccol; } static void -cursor_restore(Vt *t) +crestore(Vt *t) { Buffer *b = t->buffer; - b->curs_row = b->lines + b->curs_srow; - b->curs_col = b->curs_scol; - cursor_clamp(t); + b->crow = b->lines + b->scrow; + b->ccol = b->sccol; + cclamp(t); } static void -attributes_save(Vt *t) +savepen(Vt *t) { Buffer *b = t->buffer; - b->savattrs = b->curattrs; - b->savfg = b->curfg; - b->savbg = b->curbg; - t->savgraphmode = t->graphmode; + b->spen = b->pen; } static void -attributes_restore(Vt *t) +loadpen(Vt *t) { Buffer *b = t->buffer; - b->curattrs = b->savattrs; - b->curfg = b->savfg; - b->curbg = b->savbg; - t->graphmode = t->savgraphmode; + b->pen = b->spen; } + static void new_escape_sequence(Vt *t) @@ -658,89 +170,85 @@ interpret_csi_sgr(Vt *t, int param[], int pcount) Buffer *b = t->buffer; if (pcount == 0) { /* special case: reset attributes */ - b->curattrs = A_NORMAL; - b->curfg = b->curbg = -1; + b->pen.state = PenNormal; + b->pen.col.fg = b->pen.col.bg = -1; return; } for (int i = 0; i < pcount; i++) { switch (param[i]) { case 0: - b->curattrs = A_NORMAL; - b->curfg = b->curbg = -1; + b->pen.state = PenNormal; + b->pen.col.fg = b->pen.col.bg = -1; break; case 1: - b->curattrs |= A_BOLD; + b->pen.state |= PenBold; break; case 2: - b->curattrs |= A_DIM; + b->pen.state |= PenDim; break; -#ifdef A_ITALIC case 3: - b->curattrs |= A_ITALIC; + b->pen.state |= PenItalic; break; -#endif case 4: - b->curattrs |= A_UNDERLINE; + b->pen.state |= PenUnderline; break; case 5: - b->curattrs |= A_BLINK; + b->pen.state |= PenBlink; break; case 7: - b->curattrs |= A_REVERSE; + b->pen.state |= PenReverse; break; case 8: - b->curattrs |= A_INVIS; + b->pen.state |= PenInvis; break; case 22: - b->curattrs &= ~(A_BOLD | A_DIM); + b->pen.state &= ~(PenBold | PenDim); break; -#ifdef A_ITALIC case 23: - b->curattrs &= ~A_ITALIC; + b->pen.state &= ~PenItalic; break; -#endif case 24: - b->curattrs &= ~A_UNDERLINE; + b->pen.state &= ~PenUnderline; break; case 25: - b->curattrs &= ~A_BLINK; + b->pen.state &= ~PenBlink; break; case 27: - b->curattrs &= ~A_REVERSE; + b->pen.state &= ~PenReverse; break; case 28: - b->curattrs &= ~A_INVIS; + b->pen.state &= ~PenInvis; break; case 30 ... 37: /* fg */ - b->curfg = param[i] - 30; + b->pen.col.fg = param[i] - 30; break; case 38: if ((i + 2) < pcount && param[i + 1] == 5) { - b->curfg = param[i + 2]; + b->pen.col.fg = param[i + 2]; i += 2; } break; case 39: - b->curfg = -1; + b->pen.col.fg = -1; break; case 40 ... 47: /* bg */ - b->curbg = param[i] - 40; + b->pen.col.bg = param[i] - 40; break; case 48: if ((i + 2) < pcount && param[i + 1] == 5) { - b->curbg = param[i + 2]; + b->pen.col.bg = param[i + 2]; i += 2; } break; case 49: - b->curbg = -1; + b->pen.col.bg = -1; break; - case 90 ... 97: /* hi fg */ - b->curfg = param[i] - 82; + case 90 ... 97: /* hi fg */ + b->pen.col.fg = param[i] - 82; break; case 100 ... 107: /* hi bg */ - b->curbg = param[i] - 92; + b->pen.col.bg = param[i] - 92; break; default: break; @@ -756,27 +264,27 @@ interpret_csi_ed(Vt *t, int param[], int pcount) Row *row, *start, *end; Buffer *b = t->buffer; - attributes_save(t); - b->curattrs = A_NORMAL; - b->curfg = b->curbg = -1; + savepen(t); + b->pen.state = PenNormal; + b->pen.col.fg = b->pen.col.bg = -1; if (pcount && param[0] == 2) { start = b->lines; - end = b->lines + b->rows; + end = b->lines + b->rows; } else if (pcount && param[0] == 1) { start = b->lines; - end = b->curs_row; - row_set(b->curs_row, 0, b->curs_col + 1, b); + end = b->crow; + zero(b->crow, 0, b->ccol + 1); } else { - row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b); - start = b->curs_row + 1; - end = b->lines + b->rows; + zero(b->crow, b->ccol, b->cols - b->ccol); + start = b->crow + 1; + end = b->lines + b->rows; } for (row = start; row < end; row++) - row_set(row, 0, b->cols, b); + zero(row, 0, b->cols); - attributes_restore(t); + loadpen(t); } /* interprets a 'move cursor' (CUP) escape sequence */ @@ -784,21 +292,21 @@ static void interpret_csi_cup(Vt *t, int param[], int pcount) { - Buffer *b = t->buffer; - Row *lines = t->relposmode ? b->scroll_top : b->lines; + Buffer *b = t->buffer; + Row *lines = t->relposmode ? b->scroll.top : b->lines; if (pcount == 0) { - b->curs_row = lines; - b->curs_col = 0; + b->crow = lines; + b->ccol = 0; } else if (pcount == 1) { - b->curs_row = lines + param[0] - 1; - b->curs_col = 0; + b->crow = lines + param[0] - 1; + b->ccol = 0; } else { - b->curs_row = lines + param[0] - 1; - b->curs_col = param[1] - 1; + b->crow = lines + param[0] - 1; + b->ccol = param[1] - 1; } - cursor_clamp(t); + cclamp(t); } /* Interpret the 'relative mode' sequences: CUU, CUD, CUF, CUB, CNL, @@ -812,37 +320,37 @@ interpret_csi_c(Vt *t, char verb, int param[], int pcount) switch (verb) { case 'A': - b->curs_row -= n; + b->crow -= n; break; case 'B': case 'e': - b->curs_row += n; + b->crow += n; break; case 'C': case 'a': - b->curs_col += n; + b->ccol += n; break; case 'D': - b->curs_col -= n; + b->ccol -= n; break; case 'E': - b->curs_row += n; - b->curs_col = 0; + b->crow += n; + b->ccol = 0; break; case 'F': - b->curs_row -= n; - b->curs_col = 0; + b->crow -= n; + b->ccol = 0; break; case 'G': case '`': - b->curs_col = n - 1; + b->ccol = n - 1; break; case 'd': - b->curs_row = b->lines + n - 1; + b->crow = b->lines + n - 1; break; } - cursor_clamp(t); + cclamp(t); } /* Interpret the 'erase line' escape sequence */ @@ -853,13 +361,13 @@ interpret_csi_el(Vt *t, int param[], int pcount) Buffer *b = t->buffer; switch (pcount ? param[0] : 0) { case 1: - row_set(b->curs_row, 0, b->curs_col + 1, b); + zero(b->crow, 0, b->ccol + 1); break; case 2: - row_set(b->curs_row, 0, b->cols, b); + zero(b->crow, 0, b->cols); break; default: - row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b); + zero(b->crow, b->ccol, b->cols - b->ccol); break; } } @@ -870,16 +378,16 @@ void interpret_csi_ich(Vt *t, int param[], int pcount) { Buffer *b = t->buffer; - Row *row = b->curs_row; + Row *row = b->crow; int n = (pcount && param[0] > 0) ? param[0] : 1; - if (b->curs_col + n > b->cols) - n = b->cols - b->curs_col; + if (b->ccol + n > b->cols) + n = b->cols - b->ccol; - for (int i = b->cols - 1; i >= b->curs_col + n; i--) + for (int i = b->cols - 1; i >= b->ccol + n; i--) row->cells[i] = row->cells[i - n]; - row_set(row, b->curs_col, n, b); + zero(row, b->ccol, n); } /* Interpret the 'delete chars' sequence (DCH) */ @@ -888,16 +396,16 @@ void interpret_csi_dch(Vt *t, int param[], int pcount) { Buffer *b = t->buffer; - Row *row = b->curs_row; + Row *row = b->crow; int n = (pcount && param[0] > 0) ? param[0] : 1; - if (b->curs_col + n > b->cols) - n = b->cols - b->curs_col; + if (b->ccol + n > b->cols) + n = b->cols - b->ccol; - for (int i = b->curs_col; i < b->cols - n; i++) + for (int i = b->ccol; i < b->cols - n; i++) row->cells[i] = row->cells[i + n]; - row_set(row, b->cols - n, n, b); + zero(row, b->cols - n, n); } /* Interpret an 'insert line' sequence (IL) */ @@ -908,13 +416,13 @@ interpret_csi_il(Vt *t, int param[], int pcount) Buffer *b = t->buffer; int n = (pcount && param[0] > 0) ? param[0] : 1; - if (b->curs_row + n >= b->scroll_bot) { - for (Row *row = b->curs_row; row < b->scroll_bot; row++) - row_set(row, 0, b->cols, b); + if (b->crow + n >= b->scroll.bot) { + for (Row *row = b->crow; row < b->scroll.bot; row++) + zero(row, 0, b->cols); } else { - row_roll(b->curs_row, b->scroll_bot, -n); - for (Row *row = b->curs_row; row < b->curs_row + n; row++) - row_set(row, 0, b->cols, b); + roll(b->crow, b->scroll.bot, -n); + for (Row *row = b->crow; row < b->crow + n; row++) + zero(row, 0, b->cols); } } @@ -926,13 +434,13 @@ interpret_csi_dl(Vt *t, int param[], int pcount) Buffer *b = t->buffer; int n = (pcount && param[0] > 0) ? param[0] : 1; - if (b->curs_row + n >= b->scroll_bot) { - for (Row *row = b->curs_row; row < b->scroll_bot; row++) - row_set(row, 0, b->cols, b); + if (b->crow + n >= b->scroll.bot) { + for (Row *row = b->crow; row < b->scroll.bot; row++) + zero(row, 0, b->cols); } else { - row_roll(b->curs_row, b->scroll_bot, n); - for (Row *row = b->scroll_bot - n; row < b->scroll_bot; row++) - row_set(row, 0, b->cols, b); + roll(b->crow, b->scroll.bot, n); + for (Row *row = b->scroll.bot - n; row < b->scroll.bot; row++) + zero(row, 0, b->cols); } } @@ -944,10 +452,10 @@ interpret_csi_ech(Vt *t, int param[], int pcount) Buffer *b = t->buffer; int n = (pcount && param[0] > 0) ? param[0] : 1; - if (b->curs_col + n > b->cols) - n = b->cols - b->curs_col; + if (b->ccol + n > b->cols) + n = b->cols - b->ccol; - row_set(b->curs_row, b->curs_col, n, b); + zero(b->crow, b->ccol, n); } /* Interpret a 'set scrolling region' (DECSTBM) sequence */ @@ -960,8 +468,8 @@ interpret_csi_decstbm(Vt *t, int param[], int pcount) switch (pcount) { case 0: - b->scroll_top = b->lines; - b->scroll_bot = b->lines + b->rows; + b->scroll.top = b->lines; + b->scroll.bot = b->lines + b->rows; break; case 2: new_top = param[0] - 1; @@ -979,15 +487,15 @@ interpret_csi_decstbm(Vt *t, int param[], int pcount) /* check for range validity */ if (new_top < new_bot) { - b->scroll_top = b->lines + new_top; - b->scroll_bot = b->lines + new_bot; + b->scroll.top = b->lines + new_top; + b->scroll.bot = b->lines + new_bot; } break; default: return; /* malformed */ } - b->curs_row = b->scroll_top; - b->curs_col = 0; + b->crow = b->scroll.top; + b->ccol = 0; } static @@ -1022,17 +530,17 @@ interpret_csi_priv_mode(Vt *t, int param[], int pcount, bool set) case 47: /* use alternate/normal screen buffer */ case 1047: if (!set) - buffer_clear(&t->buffer_alternate); - t->buffer = set ? &t->buffer_alternate : &t->buffer_normal; - vt_dirty(t); + bclear(&t->buf[1]); + t->buffer = set ? &t->buf[1] : &t->buf[0]; + vt·dirty(t); if (param[i] != 1049) break; /* fall through */ case 1048: /* save/restore cursor */ if (set) - cursor_save(t); + csave(t); else - cursor_restore(t); + crestore(t); break; case 1000: /* enable/disable normal mouse tracking */ t->mousetrack = set; @@ -1125,10 +633,10 @@ interpret_csi(Vt *t) interpret_csi_ech(t, csiparam, param_count); break; case 'S': /* SU: scroll up */ - vt_scroll(t, param_count ? -csiparam[0] : -1); + vt·scroll(t, param_count ? -csiparam[0] : -1); break; case 'T': /* SD: scroll down */ - vt_scroll(t, param_count ? csiparam[0] : 1); + vt·scroll(t, param_count ? csiparam[0] : 1); break; case 'Z': /* CBT: cursor backward tabulation */ puttab(t, param_count ? -csiparam[0] : -1); @@ -1136,7 +644,7 @@ interpret_csi(Vt *t) case 'g': /* TBC: tabulation clear */ switch (param_count ? csiparam[0] : 0) { case 0: - b->tabs[b->curs_col] = false; + b->tabs[b->ccol] = false; break; case 3: memset(b->tabs, 0, sizeof(*b->tabs) * b->maxcols); @@ -1147,14 +655,14 @@ interpret_csi(Vt *t) interpret_csi_decstbm(t, csiparam, param_count); break; case 's': /* save cursor location */ - cursor_save(t); + csave(t); break; case 'u': /* restore cursor location */ - cursor_restore(t); + crestore(t); break; case 'n': /* query cursor location */ if (param_count == 1 && csiparam[0] == 6) - send_curs(t); + sendcurs(t); break; default: break; @@ -1167,8 +675,8 @@ void interpret_csi_ind(Vt *t) { Buffer *b = t->buffer; - if (b->curs_row < b->lines + b->rows - 1) - b->curs_row++; + if (b->crow < b->lines + b->rows - 1) + b->crow++; } /* Interpret a 'reverse index' (RI) sequence */ @@ -1177,11 +685,11 @@ void interpret_csi_ri(Vt *t) { Buffer *b = t->buffer; - if (b->curs_row > b->scroll_top) - b->curs_row--; + if (b->crow > b->scroll.top) + b->crow--; else { - row_roll(b->scroll_top, b->scroll_bot, -1); - row_set(b->scroll_top, 0, b->cols, b); + roll(b->scroll.top, b->scroll.bot, -1); + zero(b->scroll.top, 0, b->cols); } } @@ -1191,9 +699,9 @@ void interpret_csi_nel(Vt *t) { Buffer *b = t->buffer; - if (b->curs_row < b->lines + b->rows - 1) { - b->curs_row++; - b->curs_col = 0; + if (b->crow < b->lines + b->rows - 1) { + b->crow++; + b->ccol = 0; } } @@ -1222,8 +730,8 @@ interpret_osc(Vt *t) switch (command) { case 0: /* icon name and window title */ case 2: /* window title */ - if (t->title_handler) - t->title_handler(t, data+1); + // if (t->title_handler) + // t->title_handler(t, data+1); break; case 1: /* icon name */ break; @@ -1278,12 +786,12 @@ try_interpret_escape_seq(Vt *t) } break; case '7': /* DECSC: save cursor and attributes */ - attributes_save(t); - cursor_save(t); + savepen(t); + csave(t); goto handled; case '8': /* DECRC: restore cursor and attributes */ - attributes_restore(t); - cursor_restore(t); + loadpen(t); + crestore(t); goto handled; case 'D': /* IND: index */ interpret_csi_ind(t); @@ -1295,7 +803,7 @@ try_interpret_escape_seq(Vt *t) interpret_csi_nel(t); goto handled; case 'H': /* HTS: horizontal tab set */ - t->buffer->tabs[t->buffer->curs_col] = true; + t->buffer->tabs[t->buffer->ccol] = true; goto handled; default: goto cancel; @@ -1325,17 +833,17 @@ puttab(Vt *t, int count) { Buffer *b = t->buffer; int direction = count >= 0 ? 1 : -1; - for (int col = b->curs_col + direction; count; col += direction) { + for (int col = b->ccol + direction; count; col += direction) { if (col < 0) { - b->curs_col = 0; + b->ccol = 0; break; } if (col >= b->cols) { - b->curs_col = b->cols - 1; + b->ccol = b->cols - 1; break; } if (b->tabs[col]) { - b->curs_col = col; + b->ccol = col; count -= direction; } } @@ -1343,31 +851,31 @@ puttab(Vt *t, int count) static void -process_nonprinting(Vt *t, wchar_t wc) +process_nonprinting(Vt *t, rune r) { Buffer *b = t->buffer; - switch (wc) { + switch (r) { case '\e': /* ESC */ new_escape_sequence(t); break; case '\a': /* BEL */ - if (t->urgent_handler) - t->urgent_handler(t); + // if (t->urgent_handler) + // t->urgent_handler(t); break; case '\b': /* BS */ - if (b->curs_col > 0) - b->curs_col--; + if (b->ccol > 0) + b->ccol--; break; case '\t': /* HT */ puttab(t, 1); break; case '\r': /* CR */ - b->curs_col = 0; + b->ccol = 0; break; case '\v': /* VT */ case '\f': /* FF */ case '\n': /* LF */ - cursor_line_down(t); + clinedown(t); break; case '\016': /* SO: shift out, invoke the G1 character set */ t->graphmode = t->charsets[1]; @@ -1385,7 +893,7 @@ is_utf8_locale(void) const char *cset = nl_langinfo(CODESET); if (!cset) cset = "ANSI_X3.4-1968"; - is_utf8 = !strcmp(cset, "UTF-8"); + isutf8 = !strcmp(cset, "UTF-8"); } static @@ -1409,17 +917,18 @@ get_vt100_graphic(char c) 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, // 78-7e }; - if (is_utf8) + if (isutf8) return vt100_utf8[c - 0x41]; - else if (strchr(vt100_acs, c)) - return NCURSES_ACS(c); + // else if (strchr(vt100_acs, c)) + // return NCURSES_ACS(c); return '\0'; } static void -put_wc(Vt *t, wchar_t wc) +putrune(Vt *t, rune r) { + Cell blank; int width = 0; if (!t->seen_input) { @@ -1429,54 +938,61 @@ put_wc(Vt *t, wchar_t wc) if (t->escaped) { if (t->elen + 1 < sizeof(t->ebuf)) { - t->ebuf[t->elen] = wc; + t->ebuf[t->elen] = r; t->ebuf[++t->elen] = '\0'; try_interpret_escape_seq(t); } else { cancel_escape_sequence(t); } - } else if (IS_CONTROL(wc)) { - process_nonprinting(t, wc); + } else if (IS_CONTROL(r)) { + process_nonprinting(t, r); } else { if (t->graphmode) { - if (wc >= 0x41 && wc <= 0x7e) { - wchar_t gc = get_vt100_graphic(wc); + if (r >= 0x41 && r <= 0x7e) { + wchar_t gc = get_vt100_graphic(r); if (gc) - wc = gc; + r = gc; } width = 1; - } else if ((width = wcwidth(wc)) < 1) { + } else if ((width = wcwidth(r)) < 1) { width = 1; } Buffer *b = t->buffer; - Cell blank_cell = { L'\0', build_attrs(b->curattrs), b->curfg, b->curbg }; - if (width == 2 && b->curs_col == b->cols - 1) { - b->curs_row->cells[b->curs_col++] = blank_cell; - b->curs_row->dirty = true; + blank = (Cell){ + .r = L'\0', + .pen = (Pen){ + .state = b->pen.state, + .col = b->pen.col + }, + }; + if (width == 2 && b->ccol == b->cols - 1) { + b->crow->cells[b->ccol++] = blank; + b->crow->dirty = true; } - if (b->curs_col >= b->cols) { - b->curs_col = 0; - cursor_line_down(t); + if (b->ccol >= b->cols) { + b->ccol = 0; + clinedown(t); } if (t->insert) { - Cell *src = b->curs_row->cells + b->curs_col; + Cell *src = b->crow->cells + b->ccol; Cell *dest = src + width; - size_t len = b->cols - b->curs_col - width; + size_t len = b->cols - b->ccol - width; memmove(dest, src, len * sizeof *dest); } - b->curs_row->cells[b->curs_col] = blank_cell; - b->curs_row->cells[b->curs_col++].text = wc; - b->curs_row->dirty = true; + b->crow->cells[b->ccol] = blank; + b->crow->cells[b->ccol++].r = r; + b->crow->dirty = true; + if (width == 2) - b->curs_row->cells[b->curs_col++] = blank_cell; + b->crow->cells[b->ccol++] = blank; } } int -vt_process(Vt *t) +vt·process(Vt *t) { int res; uint pos = 0; @@ -1494,10 +1010,11 @@ vt_process(Vt *t) t->rlen += res; while (pos < t->rlen) { - wchar_t wc; - ssize_t len; + rune r; + size_t len; - len = (ssize_t)mbrtowc(&wc, t->rbuf + pos, t->rlen - pos, &ps); + // XXX: convert this to use utf8 functions + len = (ssize_t)mbrtowc((wchar*)&r, t->rbuf + pos, t->rlen - pos, &ps); if (len == -2) { t->rlen -= pos; memmove(t->rbuf, t->rbuf + pos, t->rlen); @@ -1506,11 +1023,11 @@ vt_process(Vt *t) if (len == -1) { len = 1; - wc = t->rbuf[pos]; + r = t->rbuf[pos]; } pos += len ? len : 1; - put_wc(t, wc); + putrune(t, r); } t->rlen -= pos; @@ -1518,16 +1035,9 @@ vt_process(Vt *t) return 0; } -void -vt_default_colors_set(Vt *t, attr_t attrs, short fg, short bg) -{ - t->defattrs = attrs; - t->deffg = fg; - t->defbg = bg; -} - +/* size is the number of rows kept in the scrollback */ Vt * -vt_create(int rows, int cols, int scroll_size) +vt·make(int rows, int cols, int size) { if (rows <= 0 || cols <= 0) return nil; @@ -1537,11 +1047,14 @@ vt_create(int rows, int cols, int scroll_size) return nil; t->pty = -1; - t->deffg = t->defbg = -1; - t->buffer = &t->buffer_normal; - - if (!buffer_init(&t->buffer_normal, rows, cols, scroll_size) || - !buffer_init(&t->buffer_alternate, rows, cols, 0)) { + t->pen = (Pen) { + .state = PenNormal, + .col = {-1, -1}, + }; + t->buffer = &t->buf[0]; + + if (!binit(&t->buf[0], rows, cols, size) || + !binit(&t->buf[1], rows, cols, 0)) { free(t); return nil; } @@ -1550,34 +1063,34 @@ vt_create(int rows, int cols, int scroll_size) } void -vt_resize(Vt *t, int rows, int cols) +vt·resize(Vt *t, int rows, int cols) { struct winsize ws = { .ws_row = rows, .ws_col = cols }; if (rows <= 0 || cols <= 0) return; - vt_noscroll(t); - buffer_resize(&t->buffer_normal, rows, cols); - buffer_resize(&t->buffer_alternate, rows, cols); - cursor_clamp(t); + vt·noscroll(t); + bresize(&t->buf[0], rows, cols); + bresize(&t->buf[1], rows, cols); + cclamp(t); ioctl(t->pty, TIOCSWINSZ, &ws); kill(-t->pid, SIGWINCH); } void -vt_destroy(Vt *t) +vt·free(Vt *t) { if (!t) return; - buffer_free(&t->buffer_normal); - buffer_free(&t->buffer_alternate); + bfree(&t->buf[0]); + bfree(&t->buf[1]); close(t->pty); free(t); } void -vt_dirty(Vt *t) +vt·dirty(Vt *t) { Buffer *b = t->buffer; for (Row *row = b->lines, *end = row + b->rows; row < end; row++) @@ -1585,51 +1098,49 @@ vt_dirty(Vt *t) } void -vt_draw(Vt *t, WINDOW *win, int srow, int scol) +vt·draw(Vt *t, Window *win, int srow, int scol) { + int i, j; + Cell *cell, *prev; Buffer *b = t->buffer; if (srow != t->srow || scol != t->scol) { - vt_dirty(t); + vt·dirty(t); t->srow = srow; t->scol = scol; } - for (int i = 0; i < b->rows; i++) { + for (i = 0; i < b->rows; i++) { Row *row = b->lines + i; if (!row->dirty) continue; wmove(win, srow + i, scol); - Cell *cell = nil; - for (int j = 0; j < b->cols; j++) { - Cell *prev_cell = cell; + for (j = 0; j < b->cols; j++) { + prev = cell; cell = row->cells + j; - if (!prev_cell || cell->attr != prev_cell->attr - || cell->fg != prev_cell->fg - || cell->bg != prev_cell->bg) { - if (cell->attr == A_NORMAL) - cell->attr = t->defattrs; - if (cell->fg == -1) - cell->fg = t->deffg; - if (cell->bg == -1) - cell->bg = t->defbg; - wattrset(win, cell->attr << NCURSES_ATTR_SHIFT); - wcolor_set(win, vt_color_get(t, cell->fg, cell->bg), nil); + if (!prev || !peneq(cell->pen, prev->pen)) { + if (cell->pen.state == PenNormal) + cell->pen.state = t->pen.state; + if (cell->pen.col.fg == -1) + cell->pen.col.fg = t->pen.col.fg; + if (cell->pen.col.bg == -1) + cell->pen.col.bg = t->pen.col.bg; + // wattrset(win, cell->attr << NCURSES_ATTR_SHIFT); + // wcolor_set(win, vt_color_get(t, cell->fg, cell->bg), nil); } - if (is_utf8 && cell->text >= 128) { + if (isutf8 && cell->r >= RuneSync) { char buf[MB_CUR_MAX + 1]; - size_t len = wcrtomb(buf, cell->text, nil); + size_t len = wcrtomb(buf, cell->r, nil); if (len > 0) { waddnstr(win, buf, len); - if (wcwidth(cell->text) > 1) + if (wcwidth(cell->r) > 1) j++; } - } else { - waddch(win, cell->text > ' ' ? cell->text : ' '); - } + } else + waddch(win, cell->r > ' ' ? cell->r: ' '); } int x, y; @@ -1641,36 +1152,36 @@ vt_draw(Vt *t, WINDOW *win, int srow, int scol) row->dirty = false; } - wmove(win, srow + b->curs_row - b->lines, scol + b->curs_col); + wmove(win, srow + b->crow - b->lines, scol + b->ccol); } void -vt_scroll(Vt *t, int rows) +vt·scroll(Vt *t, int rows) { Buffer *b = t->buffer; - if (!b->scroll_size) + if (!b->scroll.size) return; if (rows < 0) { /* scroll back */ - if (rows < -b->scroll_above) - rows = -b->scroll_above; + if (rows < -b->scroll.above) + rows = -b->scroll.above; } else { /* scroll forward */ - if (rows > b->scroll_below) - rows = b->scroll_below; + if (rows > b->scroll.below) + rows = b->scroll.below; } - buffer_scroll(b, rows); - b->scroll_below -= rows; + bscroll(b, rows); + b->scroll.below -= rows; } void -vt_noscroll(Vt *t) +vt·noscroll(Vt *t) { - int scroll_below = t->buffer->scroll_below; - if (scroll_below) - vt_scroll(t, scroll_below); + int below = t->buffer->scroll.below; + if (below) + vt·scroll(t, below); } pid_t -vt_forkpty(Vt *t, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from) +vt·forkpty(Vt *t, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from) { int vt2ed[2], ed2vt[2]; struct winsize ws; @@ -1717,7 +1228,7 @@ vt_forkpty(Vt *t, const char *p, const char *argv[], const char *cwd, const char for (const char **envp = env; envp && envp[0]; envp += 2) setenv(envp[0], envp[1], 1); - setenv("TERM", vt_term, 1); + setenv("TERM", vtname, 1); if (cwd) chdir(cwd); @@ -1746,13 +1257,13 @@ vt_pty_get(Vt *t) return t->pty; } -ssize_t -vt_write(Vt *t, const char *buf, size_t len) +uintptr +vt·write(Vt *t, const char *buf, size_t len) { - ssize_t ret = len; + uintptr res, ret = len; while (len > 0) { - ssize_t res = write(t->pty, buf, len); + res = write(t->pty, buf, len); if (res < 0) { if (errno != EAGAIN && errno != EINTR) return -1; @@ -1767,18 +1278,19 @@ vt_write(Vt *t, const char *buf, size_t len) static void -send_curs(Vt *t) +sendcurs(Vt *t) { Buffer *b = t->buffer; char keyseq[16]; - snprintf(keyseq, sizeof keyseq, "\e[%d;%dR", (int)(b->curs_row - b->lines), b->curs_col); - vt_write(t, keyseq, strlen(keyseq)); + snprintf(keyseq, sizeof keyseq, "\e[%d;%dR", (int)(b->crow - b->lines), b->ccol); + vt·write(t, keyseq, strlen(keyseq)); } +#if 0 void -vt_keypress(Vt *t, int keycode) +vt·keypress(Vt *t, int keycode) { - vt_noscroll(t); + vt·noscroll(t); if (keycode >= 0 && keycode <= KEY_MAX && keytable[keycode]) { switch (keycode) { @@ -1787,26 +1299,23 @@ vt_keypress(Vt *t, int keycode) case KEY_RIGHT: case KEY_LEFT: { char keyseq[3] = { '\e', (t->curskeymode ? 'O' : '['), keytable[keycode][0] }; - vt_write(t, keyseq, sizeof keyseq); + vt·write(t, keyseq, sizeof keyseq); break; } default: - vt_write(t, keytable[keycode], strlen(keytable[keycode])); + vt·write(t, keytable[keycode], strlen(keytable[keycode])); } } else if (keycode <= UCHAR_MAX) { char c = keycode; - vt_write(t, &c, 1); + vt·write(t, &c, 1); } else { -#ifndef NDEBUG fprintf(stderr, "unhandled key %#o\n", keycode); -#endif } } void -vt_mouse(Vt *t, int x, int y, mmask_t mask) +vt·mouse(Vt *t, int x, int y, mmask_t mask) { -#ifdef NCURSES_MOUSE_VERSION char seq[6] = { '\e', '[', 'M' }, state = 0, button = 0; if (!t->mousetrack) @@ -1832,16 +1341,16 @@ vt_mouse(Vt *t, int x, int y, mmask_t mask) seq[4] = 32 + x; seq[5] = 32 + y; - vt_write(t, seq, sizeof seq); + vt·write(t, seq, sizeof seq); if (mask & (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED)) { /* send a button release event */ button = 3; seq[3] = 32 + button + state; - vt_write(t, seq, sizeof seq); + vt·write(t, seq, sizeof seq); } -#endif /* NCURSES_MOUSE_VERSION */ } +#endif static uint @@ -1854,102 +1363,26 @@ color_hash(short fg, short bg) return fg * (COLORS + 2) + bg; } -short -vt_color_get(Vt *t, short fg, short bg) -{ - if (fg >= COLORS) - fg = (t ? t->deffg : default_fg); - if (bg >= COLORS) - bg = (t ? t->defbg : default_bg); - - if (!has_default_colors) { - if (fg == -1) - fg = (t && t->deffg != -1 ? t->deffg : default_fg); - if (bg == -1) - bg = (t && t->defbg != -1 ? t->defbg : default_bg); - } - - if (!color2palette || (fg == -1 && bg == -1)) - return 0; - uint index = color_hash(fg, bg); - if (color2palette[index] == 0) { - short oldfg, oldbg; - for (;;) { - if (++color_pair_current >= color_pairs_max) - color_pair_current = color_pairs_reserved + 1; - pair_content(color_pair_current, &oldfg, &oldbg); - uint old_index = color_hash(oldfg, oldbg); - if (color2palette[old_index] >= 0) { - if (init_pair(color_pair_current, fg, bg) == OK) { - color2palette[old_index] = 0; - color2palette[index] = color_pair_current; - } - break; - } - } - } - - short color_pair = color2palette[index]; - return color_pair >= 0 ? color_pair : -color_pair; -} - -short -vt_color_reserve(short fg, short bg) -{ - if (!color2palette || fg >= COLORS || bg >= COLORS) - return 0; - if (!has_default_colors && fg == -1) - fg = default_fg; - if (!has_default_colors && bg == -1) - bg = default_bg; - if (fg == -1 && bg == -1) - return 0; - uint index = color_hash(fg, bg); - if (color2palette[index] >= 0) { - if (init_pair(color_pairs_reserved + 1, fg, bg) == OK) - color2palette[index] = -(++color_pairs_reserved); - } - short color_pair = color2palette[index]; - return color_pair >= 0 ? color_pair : -color_pair; -} - -static -void -init_colors(void) -{ - pair_content(0, &default_fg, &default_bg); - if (default_fg == -1) - default_fg = COLOR_WHITE; - if (default_bg == -1) - default_bg = COLOR_BLACK; - has_default_colors = (use_default_colors() == OK); - color_pairs_max = MIN(MAX_COLOR_PAIRS, SHRT_MAX); - if (COLORS) - color2palette = calloc((COLORS + 2) * (COLORS + 2), sizeof(short)); - /* - * XXX: On undefined color-pairs NetBSD curses pair_content() set fg - * and bg to default colors while ncurses set them respectively to - * 0 and 0. Initialize all color-pairs in order to have consistent - * behaviour despite the implementation used. - */ - for (short i = 1; i < color_pairs_max; i++) - init_pair(i, 0, 0); - vt_color_reserve(COLOR_WHITE, COLOR_BLACK); -} - void -vt_init(void) +vt·init(void) { init_colors(); is_utf8_locale(); char *term = getenv("DVTM_TERM"); if (!term) term = "dvtm"; - snprintf(vt_term, sizeof vt_term, "%s%s", term, COLORS >= 256 ? "-256color" : ""); + + snprintf(vtname, sizeof vtname, "%s%s", term, COLORS >= 256 ? "-256color" : ""); +} + +void +vt·shutdown(void) +{ } +#if 0 void -vt_keytable_set(const char * const keytable_overlay[], int count) +vt·setkeytable(const char * const keytable_overlay[], int count) { for (int k = 0; k < count && k < KEY_MAX; k++) { const char *keyseq = keytable_overlay[k]; @@ -1959,52 +1392,47 @@ vt_keytable_set(const char * const keytable_overlay[], int count) } void -vt_shutdown(void) -{ - free(color2palette); -} - -void -vt_title_handler_set(Vt *t, vt_title_handler_t handler) +vt·settitlecb(Vt *t, vt_title_handler_t handler) { t->title_handler = handler; } void -vt_urgent_handler_set(Vt *t, vt_urgent_handler_t handler) +vt·seturgentcb(Vt *t, vt_urgent_handler_t handler) { t->urgent_handler = handler; } +#endif void -vt_data_set(Vt *t, void *data) +vt·setdata(Vt *t, void *data) { t->data = data; } void * -vt_data_get(Vt *t) +vt·getdata(Vt *t) { return t->data; } bool -vt_cursor_visible(Vt *t) +vt·cursorvisible(Vt *t) { - return t->buffer->scroll_below ? false : !t->curshid; + return t->buffer->scroll.below ? false : !t->curshid; } pid_t -vt_pid_get(Vt *t) +vt·pid(Vt *t) { return t->pid; } size_t -vt_content_get(Vt *t, char **buf, bool colored) +vt·content(Vt *t, char **buf, bool colored) { - Buffer *b = t->buffer; - int lines = b->scroll_above + b->scroll_below + b->rows + 1; + Buffer *b = t->buffer; + int lines = b->scroll.above + b->scroll.below + b->rows + 1; size_t size = lines * ((b->cols + 1) * ((colored ? 64 : 0) + MB_CUR_MAX)); mbstate_t ps; memset(&ps, 0, sizeof(ps)); @@ -2013,28 +1441,28 @@ vt_content_get(Vt *t, char **buf, bool colored) return 0; char *s = *buf; - Cell *prev_cell = nil; + Cell *prev = nil; - for (Row *row = buffer_row_first(b); row; row = buffer_row_next(b, row)) { + for (Row *row = browfirst(b); row; row = brownext(b, row)) { size_t len = 0; char *last_non_space = s; for (int col = 0; col < b->cols; col++) { Cell *cell = row->cells + col; if (colored) { int esclen = 0; - if (!prev_cell || cell->attr != prev_cell->attr) { + if (!prev || cell->attr != prev->attr) { attr_t attr = cell->attr << NCURSES_ATTR_SHIFT; esclen = sprintf(s, "\033[0%s%s%s%s%s%sm", - attr & A_BOLD ? ";1" : "", - attr & A_DIM ? ";2" : "", - attr & A_UNDERLINE ? ";4" : "", - attr & A_BLINK ? ";5" : "", - attr & A_REVERSE ? ";7" : "", - attr & A_INVIS ? ";8" : ""); + attr & PenBold ? ";1" : "", + attr & PenDim ? ";2" : "", + attr & PenUnderline ? ";4" : "", + attr & PenBlink ? ";5" : "", + attr & PenReverse ? ";7" : "", + attr & PenInvis ? ";8" : ""); if (esclen > 0) s += esclen; } - if (!prev_cell || cell->fg != prev_cell->fg || cell->attr != prev_cell->attr) { + if (!prev || cell->fg != prev->fg || cell->attr != prev->attr) { if (cell->fg == -1) esclen = sprintf(s, "\033[39m"); else @@ -2042,7 +1470,7 @@ vt_content_get(Vt *t, char **buf, bool colored) if (esclen > 0) s += esclen; } - if (!prev_cell || cell->bg != prev_cell->bg || cell->attr != prev_cell->attr) { + if (!prev || cell->bg != prev->bg || cell->attr != prev->attr) { if (cell->bg == -1) esclen = sprintf(s, "\033[49m"); else @@ -2050,7 +1478,7 @@ vt_content_get(Vt *t, char **buf, bool colored) if (esclen > 0) s += esclen; } - prev_cell = cell; + prev = cell; } if (cell->text) { len = wcrtomb(s, cell->text, &ps); @@ -2072,7 +1500,7 @@ vt_content_get(Vt *t, char **buf, bool colored) } int -vt_content_start(Vt *t) +vt·contentstart(Vt *t) { - return t->buffer->scroll_above; + return t->buffer->scroll.above; } |