Update to latest madtty.
authorPierre Habouzit <madcoder@debian.org>
Tue, 20 May 2008 10:40:19 +0000 (12:40 +0200)
committerPierre Habouzit <madcoder@debian.org>
Tue, 20 May 2008 10:40:19 +0000 (12:40 +0200)
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
lib-ui/curs_lib.c
lib-ui/madtty.c
lib-ui/madtty.h

index b283e42..8a78ac8 100644 (file)
@@ -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();
index 3e2ca5b..03089ef 100644 (file)
 #include <pty.h>
 #include <sys/ioctl.h>
 #include <termios.h>
+#include <langinfo.h>
 
 #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;
+}
index 38c2651..0c780f4 100644 (file)
 
 #include <sys/types.h>
 
-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 */