From 95986f5aee1c2ee7d12c4b1e4bc47874856c5831 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Tue, 20 May 2008 12:40:19 +0200 Subject: [PATCH 1/1] Update to latest madtty. Signed-off-by: Pierre Habouzit --- lib-ui/curs_lib.c | 1 + lib-ui/madtty.c | 181 ++++++++++++++++++++++++++++++++++++++-------- lib-ui/madtty.h | 32 +++++++- 3 files changed, 181 insertions(+), 33 deletions(-) diff --git a/lib-ui/curs_lib.c b/lib-ui/curs_lib.c index b283e42..8a78ac8 100644 --- a/lib-ui/curs_lib.c +++ b/lib-ui/curs_lib.c @@ -343,6 +343,7 @@ void curses_initialize(void) if (start_color() == ERR || !has_colors() || COLORS < 8) mutt_exit(-1); madtty_init_colors(); + madtty_init_vt100_graphics(); ci_start_color(); noecho(); raw(); diff --git a/lib-ui/madtty.c b/lib-ui/madtty.c index 3e2ca5b..03089ef 100644 --- a/lib-ui/madtty.c +++ b/lib-ui/madtty.c @@ -25,12 +25,13 @@ #include #include #include +#include #include "madtty.h" #define IS_CONTROL(ch) !((ch) & 0xffffff60UL) -static int has_default = 0; +static int has_default, is_utf8; enum { C0_NUL = 0x00, @@ -70,6 +71,7 @@ struct madtty_t { unsigned escaped : 1; unsigned graphmode : 1; unsigned curshid : 1; + unsigned curskeymode: 1; /* geometry */ int rows, cols; @@ -88,6 +90,10 @@ struct madtty_t { char rbuf[BUFSIZ]; char ebuf[BUFSIZ]; int rlen, elen; + + /* custom escape sequence handler */ + madtty_handler_t handler; + void *data; }; typedef struct t_row_t { @@ -98,10 +104,13 @@ typedef struct t_row_t { static char const * const keytable[KEY_MAX+1] = { ['\n'] = "\r", - [KEY_UP] = "\e[A", - [KEY_DOWN] = "\e[B", - [KEY_RIGHT] = "\e[C", - [KEY_LEFT] = "\e[D", + /* 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", [KEY_BACKSPACE] = "\177", [KEY_HOME] = "\e[1~", [KEY_IC] = "\e[2~", @@ -519,11 +528,15 @@ static void es_interpret_csi(madtty_t *t) case 'l': if (csiparam[0] == 25) t->curshid = true; + if (csiparam[0] == 1) /* DECCKM: reset ANSI cursor (normal) key mode */ + t->curskeymode = 0; break; case 'h': if (csiparam[0] == 25) t->curshid = false; + if (csiparam[0] == 1) /* DECCKM: set ANSI cursor (application) key mode */ + t->curskeymode = 1; break; } } @@ -579,11 +592,17 @@ static void es_interpret_csi(madtty_t *t) static void try_interpret_escape_seq(madtty_t *t) { char lastchar = t->ebuf[t->elen-1]; - - switch (*t->ebuf) { - case '\0': + if(!*t->ebuf) return; - + if(t->handler){ + switch((*(t->handler))(t, t->ebuf)){ + case MADTTY_HANDLER_OK: + goto cancel; + case MADTTY_HANDLER_NOTYET: + return; + } + } + switch (*t->ebuf) { case 'M': interpret_csi_SR(t); cancel_escape_sequence(t); @@ -659,10 +678,16 @@ static void madtty_process_nonprinting(madtty_t *t, wchar_t wc) } } +static void is_utf8_locale(void) +{ + const char *cset = nl_langinfo(CODESET) ?: "ANSI_X3.4-1968"; + is_utf8 = !strcmp(cset, "UTF-8"); +} + // vt100 special graphics and line drawing // 5f-7e standard vt100 // 40-5e rxvt extension for extra curses acs chars -static uint16_t const vt100_0[62] = { // 41 .. 7e +static uint16_t const vt100_utf8[62] = { // 41 .. 7e 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // 41-47 hi mr. snowman! 0, 0, 0, 0, 0, 0, 0, 0, // 48-4f 0, 0, 0, 0, 0, 0, 0, 0, // 50-57 @@ -673,6 +698,48 @@ static uint16_t const vt100_0[62] = { // 41 .. 7e 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, // 78-7e }; +static uint32_t vt100[62]; + +void madtty_init_vt100_graphics(void) +{ + vt100['l' - 0x41] = ACS_ULCORNER; + vt100['m' - 0x41] = ACS_LLCORNER; + vt100['k' - 0x41] = ACS_URCORNER; + vt100['j' - 0x41] = ACS_LRCORNER; + vt100['u' - 0x41] = ACS_RTEE; + vt100['t' - 0x41] = ACS_LTEE; + vt100['v' - 0x41] = ACS_TTEE; + vt100['w' - 0x41] = ACS_BTEE; + vt100['q' - 0x41] = ACS_HLINE; + vt100['x' - 0x41] = ACS_VLINE; + vt100['n' - 0x41] = ACS_PLUS; + vt100['o' - 0x41] = ACS_S1; + vt100['s' - 0x41] = ACS_S9; + vt100['`' - 0x41] = ACS_DIAMOND; + vt100['a' - 0x41] = ACS_CKBOARD; + vt100['f' - 0x41] = ACS_DEGREE; + vt100['g' - 0x41] = ACS_PLMINUS; + vt100['~' - 0x41] = ACS_BULLET; +#if 0 /* out of bounds */ + vt100[',' - 0x41] = ACS_LARROW; + vt100['+' - 0x41] = ACS_RARROW; + vt100['.' - 0x41] = ACS_DARROW; + vt100['-' - 0x41] = ACS_UARROW; + vt100['0' - 0x41] = ACS_BLOCK; +#endif + vt100['h' - 0x41] = ACS_BOARD; + vt100['i' - 0x41] = ACS_LANTERN; + /* these defaults were invented for ncurses */ + vt100['p' - 0x41] = ACS_S3; + vt100['r' - 0x41] = ACS_S7; + vt100['y' - 0x41] = ACS_LEQUAL; + vt100['z' - 0x41] = ACS_GEQUAL; + vt100['{' - 0x41] = ACS_PI; + vt100['|' - 0x41] = ACS_NEQUAL; + vt100['}' - 0x41] = ACS_STERLING; + is_utf8_locale(); +} + static void madtty_putc(madtty_t *t, wchar_t wc) { int width = 0; @@ -693,8 +760,10 @@ static void madtty_putc(madtty_t *t, wchar_t wc) t_row_t *tmp; if (t->graphmode) { - if (wc >= 0x41 && wc <= 0x7e && vt100_0[wc - 0x41]) { - wc = vt100_0[wc - 0x41]; + if (wc >= 0x41 && wc <= 0x7e) { + wchar_t gc = is_utf8 ? vt100_utf8[wc - 0x41] : vt100[wc - 0x41]; + if (gc) + wc = gc; } width = 1; } else { @@ -838,6 +907,8 @@ void madtty_resize(madtty_t *t, int rows, int cols) lines[row].attr = realloc(lines[row].attr, sizeof(uint16_t) * cols); if (t->cols < cols) t_row_set(lines + row, t->cols, cols - t->cols, 0); + else + lines[row].dirty = true; } t->cols = cols; } @@ -845,14 +916,13 @@ void madtty_resize(madtty_t *t, int rows, int cols) while (t->rows < rows) { lines[t->rows].text = (wchar_t *)calloc(sizeof(wchar_t), cols); lines[t->rows].attr = (uint16_t *)calloc(sizeof(uint16_t), cols); + t_row_set(lines + t->rows, 0, t->cols, 0); t->rows++; } t->curs_row += lines - t->lines; - t->scroll_top += lines - t->lines; - t->scroll_bot += lines - t->lines; - if (t->scroll_bot > lines + t->rows) - t->scroll_bot = lines + t->rows; + t->scroll_top = lines; + t->scroll_bot = lines + rows; t->lines = lines; clamp_cursor_to_bounds(t); ioctl(t->pty, TIOCSWINSZ, &ws); @@ -873,6 +943,12 @@ void madtty_destroy(madtty_t *t) free(t); } +void madtty_dirty(madtty_t *t) +{ + for (int i = 0; i < t->rows; i++) + t->lines[i].dirty = true; +} + void madtty_draw(madtty_t *t, WINDOW *win, int srow, int scol) { curs_set(0); @@ -887,7 +963,7 @@ void madtty_draw(madtty_t *t, WINDOW *win, int srow, int scol) for (int j = 0; j < t->cols; j++) { if (!j || row->attr[j] != row->attr[j - 1]) wattrset(win, (attr_t)row->attr[j] << NCURSES_ATTR_SHIFT); - if (row->text[j] >= 128) { + if (is_utf8 && row->text[j] >= 128) { char buf[MB_CUR_MAX + 1]; int len; @@ -939,20 +1015,8 @@ int madtty_getpty(madtty_t *t) return t->pty; } -void madtty_keypress(madtty_t *t, int keycode) +static void term_write(madtty_t *t, const char *buf, int len) { - char c = (char)keycode; - const char *buf; - int len; - - if (keycode >= 0 && keycode < KEY_MAX && keytable[keycode]) { - buf = keytable[keycode]; - len = strlen(keytable[keycode]); - } else { - buf = &c; - len = 1; - } - while (len > 0) { int res = write(t->pty, buf, len); if (res < 0 && errno != EAGAIN && errno != EINTR) @@ -963,6 +1027,43 @@ void madtty_keypress(madtty_t *t, int keycode) } } +void madtty_keypress(madtty_t *t, int keycode) +{ + char c = (char)keycode; + + if (keycode >= 0 && keycode < KEY_MAX && keytable[keycode]) { + switch(keycode) { + case KEY_UP: + case KEY_DOWN: + case KEY_RIGHT: + case KEY_LEFT: { + char keyseq[3] = { '\e', (t->curskeymode ? 'O' : '['), keytable[keycode][0] }; + term_write(t, keyseq, 3); + break; + } + default: + term_write(t, keytable[keycode], strlen(keytable[keycode])); + } + } else + term_write(t, &c, 1); +} + +void madtty_keypress_sequence(madtty_t *t, const char *seq) +{ + int key, len = strlen(seq); + /* check for function keys from putty, this makes the + * keypad work but it's probably not the right way to + * do it. the sequence we look for is \eO + a character + * representing the number. + */ + if(len == 3 && seq[0] == '\e' && seq[1] == 'O') { + key = seq[2] - 64; + if(key >= '0' && key <= '9') + madtty_keypress(t, key); + } else + term_write(t, seq, len); +} + void madtty_init_colors(void) { if (COLOR_PAIRS > 64) { @@ -1005,3 +1106,23 @@ int madtty_color_pair(int fg, int bg) bg = COLOR_BLACK; return COLOR_PAIR((7 - fg) * 8 + bg); } + +void madtty_set_handler(madtty_t *t, madtty_handler_t handler) +{ + t->handler = handler; +} + +void madtty_set_data(madtty_t *t, void *data) +{ + t->data = data; +} + +void *madtty_get_data(madtty_t *t) +{ + return t->data; +} + +unsigned madtty_cursor(madtty_t *t) +{ + return !t->curshid; +} diff --git a/lib-ui/madtty.h b/lib-ui/madtty.h index 38c2651..0c780f4 100644 --- a/lib-ui/madtty.h +++ b/lib-ui/madtty.h @@ -24,20 +24,46 @@ #include -void madtty_init_colors(void); -int madtty_color_pair(int fg, int bg); +enum { + /* means escape sequence was handled */ + MADTTY_HANDLER_OK, + /* means the escape sequence was not recognized yet, but + * there is hope that it still will once more characters + * arrive (i.e. it is not yet complete). + * + * The library will thus continue collecting characters + * and calling the handler as each character arrives until + * either OK or NOWAY is returned. + */ + MADTTY_HANDLER_NOTYET, + /* means the escape sequence was not recognized, and there + * is no chance that it will even if more characters are + * added to it. + */ + MADTTY_HANDLER_NOWAY +}; typedef struct madtty_t madtty_t; +typedef int (*madtty_handler_t)(madtty_t *, char *es); + +void madtty_init_colors(void); +void madtty_init_vt100_graphics(void); +void madtty_set_handler(madtty_t *, madtty_handler_t); +void madtty_set_data(madtty_t *, void *); +void *madtty_get_data(madtty_t *); +int madtty_color_pair(int fg, int bg); madtty_t *madtty_create(int rows, int cols); void madtty_resize(madtty_t *, int rows, int cols); void madtty_destroy(madtty_t *); pid_t madtty_forkpty(madtty_t *, const char *, const char *argv[], int *pty); int madtty_getpty(madtty_t *); +unsigned madtty_cursor(madtty_t *t); int madtty_process(madtty_t *); void madtty_keypress(madtty_t *, int keycode); +void madtty_keypress_sequence(madtty_t *, const char *seq); +void madtty_dirty(madtty_t *t); void madtty_draw(madtty_t *, WINDOW *win, int startrow, int startcol); - #endif /* MADTTY_MADTTY_H */ -- 2.20.1