diff options
Diffstat (limited to 'sys/cmd/dvtm/term.h')
-rw-r--r-- | sys/cmd/dvtm/term.h | 356 |
1 files changed, 350 insertions, 6 deletions
diff --git a/sys/cmd/dvtm/term.h b/sys/cmd/dvtm/term.h index 3102458..53c0850 100644 --- a/sys/cmd/dvtm/term.h +++ b/sys/cmd/dvtm/term.h @@ -3,13 +3,179 @@ #include <u.h> #include <libn.h> -#define iota(x) 1 << (x) +#include <termios.h> +#include <unibilium.h> +#define iota(x) 1 << (x) +/* + * obtained from: + * https://invisible-island.net/ncurses/man/curs_add_wch.3x.html + */ +#define ACSRUNES \ + /* name utf8 ascii acsc*/ \ + ACSRUNE("block", 0x25ae, '#', '0') \ + ACSRUNE("board", 0x2592, '#', 'h') \ + ACSRUNE("btee", 0x2534, '+', 'v') \ + ACSRUNE("bullet", 0x00b7, 'o', '~') \ + ACSRUNE("ckboard", 0x2592, ':', 'a') \ + ACSRUNE("darrow", 0x2193, 'v', '.') \ + ACSRUNE("degree", 0x00b0, '\'','f') \ + ACSRUNE("diamond", 0x25c6, '+', '`') \ + ACSRUNE("gequal", 0x2265, '>', '>') \ + ACSRUNE("hline", 0x2500, '-', 'q') \ + ACSRUNE("antern", 0x2603, '#', 'i') \ + ACSRUNE("larrow", 0x2190, '<', ',') \ + ACSRUNE("lequal", 0x2264, '<', 'y') \ + ACSRUNE("llcorner", 0x2514, '+', 'm') \ + ACSRUNE("lrcorner", 0x2518, '+', 'j') \ + ACSRUNE("ltee", 0x2524, '+', 't') \ + ACSRUNE("nequal", 0x2260, '!', '|') \ + ACSRUNE("pi", 0x03c0, '*', '{') \ + ACSRUNE("plminus", 0x00b1, '#', 'g') \ + ACSRUNE("plus", 0x253c, '+', 'n') \ + ACSRUNE("rarrow", 0x2192, '>', '+') \ + ACSRUNE("rtee", 0x251c, '+', 'u') \ + ACSRUNE("s1", 0x23ba, '-', 'o') \ + ACSRUNE("s3", 0x23bb, '-', 'p') \ + ACSRUNE("s7", 0x23bc, '-', 'r') \ + ACSRUNE("s9", 0x23bd, '_', 's') \ + ACSRUNE("sterling", 0x00a3, 'f', '}') \ + ACSRUNE("ttee", 0x252c, '+', 'w') \ + ACSRUNE("uarrow", 0x2191, '^', '-') \ + ACSRUNE("ulcorner", 0x250c, '+', 'l') \ + ACSRUNE("urcorner", 0x2510, '+', 'k') \ + ACSRUNE("vline", 0x2502, '|', 'x') \ + /* thick versions */ \ + ACSRUNE("t_btee", 0x253b, '+', 'V') \ + ACSRUNE("t_hline", 0x2501, '-', 'Q') \ + ACSRUNE("t_llcorner", 0x2517, '+', 'M') \ + ACSRUNE("t_lrcorner", 0x251b, '+', 'J') \ + ACSRUNE("t_ltee", 0x252b, '+', 'T') \ + ACSRUNE("t_plus", 0x254b, '+', 'N') \ + ACSRUNE("t_rtee", 0x2523, '+', 'U') \ + ACSRUNE("t_ttee", 0x2533, '+', 'W') \ + ACSRUNE("t_ulcorner", 0x250f, '+', 'L') \ + ACSRUNE("t_urcorner", 0x2513, '+', 'K') \ + ACSRUNE("t_vline", 0x2503, '|', 'X') \ + /* double version */ \ + ACSRUNE("d_btee", 0x2569, '+', 'H') \ + ACSRUNE("d_hline", 0x2550, '-', 'R') \ + ACSRUNE("d_llcorner", 0x255a, '+', 'D') \ + ACSRUNE("d_lrcorner", 0x255d, '+', 'A') \ + ACSRUNE("d_ltee", 0x2560, '+', 'F') \ + ACSRUNE("d_plus", 0x256c, '+', 'E') \ + ACSRUNE("d_rtee", 0x2563, '+', 'G') \ + ACSRUNE("d_ttee", 0x2566, '+', 'I') \ + ACSRUNE("d_ulcorner", 0x2554, '+', 'C') \ + ACSRUNE("d_urcorner", 0x2557, '+', 'B') \ + ACSRUNE("d_vline", 0x2551, '|', 'Y') + +/* enums */ + +/* key symbols */ +enum +{ + SymUnknown = -1, + SymNone = 0, + + /* special names in c0 */ + SymBackspace, SymTab, SymEnter, SymEscape, + + /* special names in g0 */ + SymSpace, SymDel, + + /* special keys */ + SymUp, SymDown, SymLeft, SymRight, SymBegin, SymFind, SymInsert, + SymDelete, SymSelect, SymPageup, SymPagedown, SymHome, SymEnd, + + /* special keys from terminfo */ + SymCancel, SymClear, SymClose, SymCommand, SymCopy, SymExit, + SymHelp, SymMark, SymMessage, SymMove, SymOpen, SymOptions, + SymPrint, SymRedo, SymReference, SymRefresh, SymReplace, + SymRestart, SymResume, SymSave, SymSuspend, SymUndo, + + /* numeric keypad special keys */ + SymKp0, SymKp1, SymKp2, SymKp3, SymKp4, SymKp5, SymKp6, SymKp7, SymKp8, + SymKp9, SymKpenter, SymKpplus, SymKpminus, SymKpmult, SymKpdiv, SymKpcomma, + SymKpperiod, SymKpequals, + + /* et cetera ad nauseum */ + NumSyms +}; + +/* key type */ +enum +{ + KeyUnicode, + KeyFunc, + KeySym, + KeyMouse, + KeyPosition, + KeyModeReport, + KeyDCS, + KeyOSC, + /* add other recognised types here */ + + KeyUnknownCSI = -1 +}; + +/* key events */ +enum KeyEvent +{ + EvNil, + EvKey, + EvEOF, + EvAgain, + EvErr, +}; + +enum MouseEvent +{ + MouseNil, + MousePress, + MouseDrag, + MouseRelease, +}; + +enum +{ + ModShift = iota(0), + ModAlt = iota(1), + ModCtrl = iota(2), +}; + +enum +{ + FlagNoInterpret = iota(0), + FlagConvertKP = iota(1), + FlagRaw = iota(2), + FlagUTF8 = iota(3), + FlagNoTermIOS = iota(4), + FlagSpaceSymbol = iota(5), + FlagCtrlC = iota(6), + FlagEintr = iota(7), +}; + +enum +{ + HarmonizeSpace = iota(0), + HarmonizeDelBS = iota(1), +}; + +/* types */ typedef struct RGB8 RGB8; typedef struct Pen Pen; + typedef struct Cell Cell; typedef struct Row Row; typedef struct Buffer Buffer; +typedef struct Window Window; + +typedef struct Node Node; +typedef struct Key Key; +typedef struct Input Input; + +typedef struct Term Term; struct RGB8 { @@ -28,13 +194,12 @@ enum PenUnderline = iota(6), PenBlink = iota(7), /* ... */ - PenTC = iota(15), + PenTrueClr = iota(15), }; struct Pen { ushort state; - ushort color; union { /* 256 color (legacy) */ struct { @@ -47,6 +212,7 @@ struct Pen }; }; +/* outputs */ struct Cell { rune r; Pen pen; @@ -104,8 +270,8 @@ struct Row { */ struct Buffer { - Row *lines; /* array of Row pointers of size 'rows' */ - Row *crow; /* row on which the cursor currently resides */ + Row *row; /* array of Row pointers of size 'rows' */ + Row *crow; /* row on which the cursor currently resides */ bool *tabs; /* a boolean flag for each column whether it is a tab */ struct { Row *buf; /* a ring buffer holding the scroll back content */ @@ -116,12 +282,161 @@ struct Buffer { int above; /* number of lines above current viewport */ int below; /* number of lines below current viewport */ } scroll; - int rows, cols; /* current dimension of buffer */ + Pen pen, spen; + int nrow, ncol; /* current dimension of buffer */ int maxcols; /* allocated cells (maximal cols over time) */ + int srow, scol; /* saved cursor row/column (zero based) */ +}; + +/* input */ +struct Key +{ + int type; + int mods; + uchar utf8[UTFmax+1]; + union { + rune pt; + int num; + int sym; + char mouse[4]; + } code; +}; + +struct KeyInfo +{ + int type; + int sym; + int modmask; + int modset; +}; + +/* make opaque? */ +struct Input +{ + int fd; + int flags; + int hflag; + int wait; /* in ms */ + + struct termios oldterm; + + /* buffer */ + struct { + long off; + uchar *b, *c, *e, bytes[256]; + } buf; + + /* modifiers */ + char closed : 1; + char started : 1; + char hasold : 1; + + /* key data */ + Node *keys; + struct KeyInfo c0[32]; + + char **keynm; + int nkeynm; + + int nsavedcsi; + char *savedcsi; +}; + +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 */ + Window *root; + Pen pen; + + /* 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 + + /* augmentations to terminfo */ + struct { + char *rgbf; // rgb foreground + char *rgbb; // rgb background + char *smxx; // strikethrough + char *smulx; // curly underline + } ext; + } esc; + + /* basic shapes */ + struct { + rune block; + rune board; + rune hline; + rune vline; + rune plus; + rune ltee; + rune rtee; + rune ttee; + rune btee; + rune ulcorner; + rune urcorner; + rune llcorner; + rune lrcorner; + } acs; }; /* exported functions */ +/* buffer.c */ void zero(Row *row, int start, int len); void roll(Row *start, Row *end, int count); @@ -130,8 +445,37 @@ void bfree(Buffer *b); void bscroll(Buffer *b, int s); void bresize(Buffer *b, int rows, int cols); bool binit(Buffer *b, int rows, int cols, int size); +void brender(Buffer *b, Term *t); void bboundary(Buffer *b, Row **bs, Row **be, Row **as, Row **ae) ; Row *browfirst(Buffer *b); Row *browlast(Buffer *b); Row *brownext(Buffer *b, Row *row); Row *bprevrow(Buffer *b, Row *row); + +/* input.c */ +Input *makeinput(int fd, int flags, unibi_term *info); +void freeinput(Input *in); +int startrecord(Input *in); +int stoprecord(Input *in); +char *keyname(Input *in, int sym); + +enum KeyEvent waitkey(Input *in, Key *key); /* block until next keypress */ +enum KeyEvent getkey(Input *in, Key *key); /* grab key if we can */ +enum KeyEvent demandkey(Input *in, Key *key); /* grab now and interpret as best we can */ +enum KeyEvent isreadablekey(Input *in); /* reads from input and reports the event w/o advance */ + +/* unpack key event into useful data */ +enum KeyEvent decodemouse(Input *in, Key *key, enum MouseEvent *ev, int *button, int *row, int *col); +enum KeyEvent decodepos(Input *in, Key *key, int *row, int *col); +enum KeyEvent decodemode(Input *in, Key *key, int *init, int *mode, int *val); + +/* term.c */ +void tinit(Term *t); +void tfini(Term *t); +void tflush(Term *t); +void twrite(Term *t, long len, char *s); +int tgoto(Term *t, int row, int col); +void tjump(Term *t, int down, int right); +void tdel(Term *t, int num); +void tsetpen(Term *t, Pen pen); +void tclear(Term *t); |