Allow utf8 for keybinds.
authorDaniel Carl <danielcarl@gmx.de>
Sun, 6 Oct 2013 20:57:03 +0000 (22:57 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 6 Oct 2013 21:09:05 +0000 (23:09 +0200)
Used some key processing stuff from vim.

19 files changed:
doc/vimb.1
src/ascii.h [new file with mode: 0644]
src/default.h
src/ex.c
src/ex.h
src/hints.c
src/hints.h
src/input.c
src/input.h
src/main.h
src/map.c
src/map.h
src/mode.c
src/mode.h
src/normal.c
src/normal.h
src/pass.c
src/pass.h
src/util.c

index 6b1666c..46348ea 100644 (file)
@@ -117,10 +117,10 @@ Open the url out of the clipboard.
 .B P
 Open the url out of the clipboard into new window.
 .TP
-.BI [ N ]CTRL\-O
+.BI [ N ]UP
 Go back \fIN\fP steps in the browser history.
 .TP
-.BI [ N ]CTRL\-I
+.BI [ N ]DOWN
 Go forward \fIN\fP steps in the browser history.
 .TP
 .BI [ N ]g\-u
@@ -201,9 +201,9 @@ element has been selected, it is automatically clicked or used (depending on
 Following keys have special meanings in Hints mode:
 .IP \fB<CR>\fP
 Selects the first highlighted element, or the current focused.
-.IP "\fB<Tab>, CTRL\-I\fP"
+.IP "\fB<Tab>\fP"
 Moves the focus to the next hint element.
-.IP "\fB<S-Tab>, CTRL\-O\fP"
+.IP "\fB<S-Tab>\fP"
 Moves the focus to the previous hint element.
 .IP "\fB<Esc>, CTRL\-C, CTRL\-[\fP"
 Exits Hints mode without selecting an element
@@ -328,16 +328,16 @@ Moves the cursor after the char in inputbox.
 
 .SS Command Line History
 .TP
-.B <Tab>, CTRL\-I
+.B <Tab>
 Start completion of the content in inputbox in forward direction.
 .TP
-.B <S-Tab>, CTRL\-O
+.B <S-Tab>
 Start completion of the content in inputbox in backward direction.
 .TP
-.B <Up>, CTRL\-P
+.B <Up>
 Step backward in the command history.
 .TP
-.B <Down>, CTRL\-N
+.B <Down>
 Step forward in the command history.
 
 .SS Open
diff --git a/src/ascii.h b/src/ascii.h
new file mode 100644 (file)
index 0000000..8a13349
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * vimb - a webkit based vim like browser.
+ *
+ * Copyright (C) 2012-2013 Daniel Carl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef _ASCII_H
+#define _ASCII_H
+
+/* CSI (control sequence introducer) is the first byte of a control sequence
+ * and is always followed by two bytes. */
+#define CSI         0x9b
+#define CSI_STR     "\233"
+
+#define IS_SPECIAL(c)       (c < 0)
+
+#define TERMCAP2KEY(a, b)   (-((a) + ((int)(b) << 8)))
+#define KEY2TERMCAP0(x)     ((-(x)) & 0xff)
+#define KEY2TERMCAP1(x)     (((unsigned)(-(x)) >> 8) & 0xff)
+
+#define KEY_TAB         '\x09'
+#define KEY_NL          '\x15'
+#define KEY_CR          '\x0a'
+#define KEY_ESC         '\x1b'
+#define KEY_BS          '\x08'
+#define KEY_SHIFT_TAB   TERMCAP2KEY('k', 'B')
+#define KEY_UP          TERMCAP2KEY('k', 'u')
+#define KEY_DOWN        TERMCAP2KEY('k', 'd')
+#define KEY_LEFT        TERMCAP2KEY('k', 'l')
+#define KEY_RIGHT       TERMCAP2KEY('k', 'r')
+
+#define KEY_F1          TERMCAP2KEY('k', '1')
+#define KEY_F2          TERMCAP2KEY('k', '2')
+#define KEY_F3          TERMCAP2KEY('k', '3')
+#define KEY_F4          TERMCAP2KEY('k', '4')
+#define KEY_F5          TERMCAP2KEY('k', '5')
+#define KEY_F6          TERMCAP2KEY('k', '6')
+#define KEY_F7          TERMCAP2KEY('k', '7')
+#define KEY_F8          TERMCAP2KEY('k', '8')
+#define KEY_F9          TERMCAP2KEY('k', '9')
+#define KEY_F10         TERMCAP2KEY('k', ';')
+#define KEY_F11         TERMCAP2KEY('F', '1')
+#define KEY_F12         TERMCAP2KEY('F', '2')
+
+#endif /* end of include guard: _ASCII_H */
index 51d9305..3664fa6 100644 (file)
@@ -66,8 +66,6 @@ static char *default_config[] = {
     "set insecure-content-run=off",
 #endif
     "set timeoutlen=1000",
-    "cmap <Up> <C-P>",
-    "cmap <Down> <C-N>",
     NULL
 };
 
index 128f009..4ea5859 100644 (file)
--- a/src/ex.c
+++ b/src/ex.c
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "main.h"
 #include "ex.h"
+#include "ascii.h"
 #include "completion.h"
 #include "hints.h"
 #include "mode.h"
@@ -202,7 +203,7 @@ void ex_leave(void)
 /**
  * Handles the keypress events from webview and inputbox.
  */
-VbResult ex_keypress(unsigned int key)
+VbResult ex_keypress(int key)
 {
     /* TODO allow to get the right prompt like ':', '/', ';o', ... */
     char *prompt = ":";
@@ -216,11 +217,11 @@ VbResult ex_keypress(unsigned int key)
     }
 
     switch (key) {
-        case CTRL('I'): /* Tab */
+        case KEY_TAB:
             complete(1);
             break;
 
-        case CTRL('O'): /* S-Tab */
+        case KEY_SHIFT_TAB:
             complete(-1);
             break;
 
@@ -234,11 +235,11 @@ VbResult ex_keypress(unsigned int key)
             input_activate();
             break;
 
-        case CTRL('P'): /* up */
+        case KEY_UP:
             history(true);
             break;
 
-        case CTRL('N'): /* down */
+        case KEY_DOWN:
             history(false);
             break;
 
index acb71e6..50a7ccc 100644 (file)
--- a/src/ex.h
+++ b/src/ex.h
@@ -25,7 +25,7 @@
 
 void ex_enter(void);
 void ex_leave(void);
-VbResult ex_keypress(unsigned int key);
+VbResult ex_keypress(int key);
 void ex_input_changed(const char *text);
 gboolean ex_fill_completion(GtkListStore *store, const char *input);
 gboolean ex_run_string(const char *input);
index e62bf63..b2d659b 100644 (file)
@@ -22,6 +22,7 @@
 #include <gdk/gdkkeysyms.h>
 #include <gdk/gdkkeysyms-compat.h>
 #include "hints.h"
+#include "ascii.h"
 #include "dom.h"
 #include "command.h"
 #include "hints.js.h"
@@ -49,7 +50,7 @@ void hints_init(WebKitWebFrame *frame)
     g_free(value);
 }
 
-VbResult hints_keypress(unsigned int key)
+VbResult hints_keypress(int key)
 {
     /* if we are not already in hint mode we expect to get a ; to start
      * hinting */
@@ -57,11 +58,12 @@ VbResult hints_keypress(unsigned int key)
         return RESULT_ERROR;
     }
 
-    if (key == '\n') {
+    if (key == KEY_CR) {
         hints_fire();
 
         return RESULT_COMPLETE;
     }
+
     /* if there is an active filter by hint num backspace will remove the
      * number filter first */
     if (hints.num && key == CTRL('H')) {
@@ -80,12 +82,12 @@ VbResult hints_keypress(unsigned int key)
             return RESULT_COMPLETE;
         }
     }
-    if (key == CTRL('I')) {
+    if (key == KEY_TAB) {
         hints_focus_next(false);
 
         return RESULT_COMPLETE;
     }
-    if (key == CTRL('O')) {
+    if (key == KEY_SHIFT_TAB) {
         hints_focus_next(true);
 
         return RESULT_COMPLETE;
index 640401b..f721883 100644 (file)
@@ -23,7 +23,7 @@
 #include "main.h"
 
 void hints_init(WebKitWebFrame *frame);
-VbResult hints_keypress(unsigned int key);
+VbResult hints_keypress(int key);
 void hints_create(const char *input);
 void hints_update(int num);
 void hints_fire(void);
index ac4a7f3..5f46947 100644 (file)
@@ -55,7 +55,7 @@ void input_leave(void)
 /**
  * Handles the keypress events from webview and inputbox.
  */
-VbResult input_keypress(unsigned int key)
+VbResult input_keypress(int key)
 {
     switch (key) {
         case CTRL('['): /* esc */
index fa8c908..4b9b3ef 100644 (file)
@@ -25,7 +25,7 @@
 
 void input_enter(void);
 void input_leave(void);
-VbResult input_keypress(unsigned int key);
+VbResult input_keypress(int key);
 VbResult input_open_editor(void);
 
 #endif /* end of include guard: _INPUT_H */
index 89edfd0..5ad8805 100644 (file)
@@ -41,9 +41,7 @@
 
 #define CTRL(x)      ((x) ^ 0x40)
 /* check if the char x is a char with CTRL like ^C */
-#define IS_CTRL(x)   (((unsigned char)x) <= 0x1f)
-#define CSI          0x9b   /* Control Sequence Introducer */
-#define CSI_STR      "\233"
+#define IS_CTRL(x)   (((guchar)x) <= 0x1f)
 
 #ifdef DEBUG
 #define PRINT_DEBUG(...) { \
@@ -224,7 +222,7 @@ typedef struct {
 } Arg;
 
 typedef void (*ModeTransitionFunc) (void);
-typedef VbResult (*ModeKeyFunc) (unsigned int);
+typedef VbResult (*ModeKeyFunc) (int);
 typedef void (*ModeInputChangedFunc) (const char*);
 typedef struct {
     char                 id;
index 1bc423d..f49ba5e 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "main.h"
 #include "map.h"
+#include "ascii.h"
 #include "mode.h"
 
 extern VbCore vb;
@@ -42,6 +43,8 @@ static struct {
     char   showbuf[10];             /* buffer to shw ambiguous key sequence */
 } map;
 
+static int keyval_to_string(guint keyval, guint state, guchar *string);
+static int utf_char2bytes(guint c, guchar *buf);
 static char *convert_keys(char *in, int inlen, int *len);
 static char *convert_keylabel(char *in, int inlen, int *len);
 static gboolean do_timeout(gpointer data);
@@ -49,6 +52,31 @@ static void showcmd(char *keys, int keylen);
 static char* transchar(char c);
 static void free_map(Map *map);
 
+static struct {
+    guint state; 
+    guint keyval;
+    char one;
+    char two;
+} special_keys[] = {
+    {GDK_SHIFT_MASK,    GDK_Tab,       'k', 'B'},
+    {0,                 GDK_Up,        'k', 'u'},
+    {0,                 GDK_Down,      'k', 'd'},
+    {0,                 GDK_Left,      'k', 'l'},
+    {0,                 GDK_Right,     'k', 'r'},
+    {0,                 GDK_F1,        'k', '1'},
+    {0,                 GDK_F2,        'k', '2'},
+    {0,                 GDK_F3,        'k', '3'},
+    {0,                 GDK_F4,        'k', '4'},
+    {0,                 GDK_F5,        'k', '5'},
+    {0,                 GDK_F6,        'k', '6'},
+    {0,                 GDK_F7,        'k', '7'},
+    {0,                 GDK_F8,        'k', '8'},
+    {0,                 GDK_F9,        'k', '9'},
+    {0,                 GDK_F10,       'k', ';'},
+    {0,                 GDK_F11,       'F', '1'},
+    {0,                 GDK_F12,       'F', '2'},
+};
+
 
 void map_cleanup(void)
 {
@@ -63,90 +91,140 @@ void map_cleanup(void)
  */
 gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data)
 {
-    unsigned int key = 0;
-    static struct {
-        guint keyval;
-        int   ctrl;    /* -1 = indifferent, 1 = ctrl, 0 = no ctrl */
-        char  *ch;
-        int   chlen;
-    } keys[] = {
-        {GDK_Escape,       -1, "\x1b",         1}, /* ^[ */
-        {GDK_Tab,          -1, "\x09",         1}, /* ^I */
-        {GDK_ISO_Left_Tab, -1, "\x0f",         1}, /* ^O */
-        {GDK_Return,       -1, "\x0a",         1},
-        {GDK_KP_Enter,     -1, "\x0a",         1},
-        {GDK_BackSpace,    -1, "\x08",         1}, /* ^H */
-        {GDK_Up,           -1, CSI_STR "ku",   3},
-        {GDK_Down,         -1, CSI_STR "kd",   3},
-        {GDK_Left,         -1, CSI_STR "kl",   3},
-        {GDK_Right,        -1, CSI_STR "kr",   3},
-        /* function keys are prefixed by gEsc like in vim the CSI Control
-         * Sequence Introducer \233 */
-        /* TODO calculate this automatic */
-        {GDK_KEY_F1,        1, CSI_STR "\x01", 2},
-        {GDK_KEY_F2,        1, CSI_STR "\x02", 2},
-        {GDK_KEY_F3,        1, CSI_STR "\x03", 2},
-        {GDK_KEY_F4,        1, CSI_STR "\x04", 2},
-        {GDK_KEY_F5,        1, CSI_STR "\x05", 2},
-        {GDK_KEY_F6,        1, CSI_STR "\x06", 2},
-        {GDK_KEY_F7,        1, CSI_STR "\x07", 2},
-        {GDK_KEY_F8,        1, CSI_STR "\x08", 2},
-        {GDK_KEY_F9,        1, CSI_STR "\x09", 2},
-        {GDK_KEY_F10,       1, CSI_STR "\x0a", 2},
-        {GDK_KEY_F11,       1, CSI_STR "\x0b", 2},
-        {GDK_KEY_F12,       1, CSI_STR "\x0c", 2},
-        {GDK_KEY_F1,        0, CSI_STR "\x0d", 2},
-        {GDK_KEY_F2,        0, CSI_STR "\x0e", 2},
-        {GDK_KEY_F3,        0, CSI_STR "\x0f", 2},
-        {GDK_KEY_F4,        0, CSI_STR "\x10", 2},
-        {GDK_KEY_F5,        0, CSI_STR "\x11", 2},
-        {GDK_KEY_F6,        0, CSI_STR "\x12", 2},
-        {GDK_KEY_F7,        0, CSI_STR "\x13", 2},
-        {GDK_KEY_F8,        0, CSI_STR "\x14", 2},
-        {GDK_KEY_F9,        0, CSI_STR "\x15", 2},
-        {GDK_KEY_F10,       0, CSI_STR "\x16", 2},
-        {GDK_KEY_F11,       0, CSI_STR "\x17", 2},
-        {GDK_KEY_F12,       0, CSI_STR "\x18", 2},
-    };
-
-    int ctrl = (event->state & GDK_CONTROL_MASK) != 0;
+    guint state  = event->state;
+    guint keyval = event->keyval;
+    guchar string[32];
+    int len;
 
-    /* set initial value for the flag that should be changed in the modes key
-     * handler functions */
-    vb.state.processed_key = true;
-    if (!ctrl && event->keyval > 0 && event->keyval < 0xff) {
-        map_handle_keys((char*)(&event->keyval), 1);
+    len = keyval_to_string(keyval, state, string);
 
-        return vb.state.processed_key;
+    /* translate iso left tab to shift tab */
+    if (keyval == GDK_ISO_Left_Tab) {
+        keyval = GDK_Tab;
+        state |= GDK_SHIFT_MASK;
     }
 
-    /* convert chars A-]a-z with ctrl flag <ctrl-a> or <ctrl-A> -> \001
-     * and <ctrl-z> -> \032 like vi */
-    if (event->keyval >= 0x41 && event->keyval <= 0x5d) {/* chars A-] */
-        key = event->keyval - 0x40;
-        map_handle_keys((char*)(&key), 1);
-
-        return vb.state.processed_key;
-    } else if (event->keyval >= 0x61 && event->keyval <= 0x7a) {/* chars a-z */
-        key = event->keyval - 0x60;
-        map_handle_keys((char*)(&key), 1);
+    if (len == 0 || len == 1) {
+        for (int i = 0; i < LENGTH(special_keys); i++) {
+            if (special_keys[i].keyval == keyval
+                && (special_keys[i].state == 0 || state & special_keys[i].state)
+            ) {
+                state &= ~special_keys[i].state;
+                string[0] = CSI;
+                string[1] = special_keys[i].one;
+                string[2] = special_keys[i].two;
+                len = 3;
+                break;
+            }
+        }
+    }
 
-        return vb.state.processed_key;
+    if (len == 0) {
+        /* mark all unknown key events as unhandled to not break some gtk features
+         * like <S-Einf> to copy clipboard content into inputbox */
+        return false;
     }
 
-    for (int i = 0; i < LENGTH(keys); i++) {
-        if (keys[i].keyval == event->keyval
-            && (keys[i].ctrl == ctrl ||keys[i].ctrl == -1)
-        ) {
-            map_handle_keys(keys[i].ch, keys[i].chlen);
+    vb.state.processed_key = true;
+    map_handle_keys(string, len);
+
+    return vb.state.processed_key;
+}
 
-            return vb.state.processed_key;
+/**
+ * Translate a keyvalue to utf-8 encoded and null terminated string.
+ * Given string must have room for 6 bytes.
+ */
+static int keyval_to_string(guint keyval, guint state, guchar *string)
+{
+    int len;
+    guint32 uc;
+
+    if ((uc = gdk_keyval_to_unicode(keyval))) {
+        if ((state & GDK_CONTROL_MASK) && uc >= 0x20 && uc < 0x80) {
+            len = 1;
+            if (uc >= '@') {
+                string[0] = uc & 0x1f;
+            } else if (uc == '8') {
+                string[0] = KEY_BS;
+            } else {
+                string[0] = uc;
+            }
+        } else {
+            /* translate a normal key to utf-8 */
+            len = utf_char2bytes((guint)uc, string);
+        }
+    } else {
+        /* translate keys which are represented by ascii control codes */
+        len = 1;
+        switch (keyval) {
+            case GDK_Tab:
+            case GDK_KP_Tab:
+            case GDK_ISO_Left_Tab:
+                string[0] = KEY_TAB;
+                break;
+            case GDK_Linefeed:
+                string[0] = KEY_NL;
+                break;
+            case GDK_Return:
+            case GDK_ISO_Enter:
+            case GDK_3270_Enter:
+                string[0] = KEY_CR;
+                break;
+            case GDK_Escape:
+                string[0] = KEY_ESC;
+                break;
+            case GDK_BackSpace:
+                string[0] = KEY_BS;
+                break;
+            default:
+                len = 0;
+                break;
         }
     }
 
-    /* mark all unknown key events as unhandled to not break some gtk features
-     * like <S-Einf> to copy clipboard content into inputbox */
-    return false;
+    return len;
+}
+
+static int utf_char2bytes(guint c, guchar *buf)
+{
+    if (c < 0x80) {
+        buf[0] = c;
+        return 1;
+    }
+    if (c < 0x800) {
+        buf[0] = 0xc0 + (c >> 6);
+        buf[1] = 0x80 + (c & 0x3f);
+        return 2;
+    }
+    if (c < 0x10000) {
+        buf[0] = 0xe0 + (c >> 12);
+        buf[1] = 0x80 + ((c >> 6) & 0x3f);
+        buf[2] = 0x80 + (c & 0x3f);
+        return 3;
+    }
+    if (c < 0x200000) {
+        buf[0] = 0xf0 + (c >> 18);
+        buf[1] = 0x80 + ((c >> 12) & 0x3f);
+        buf[2] = 0x80 + ((c >> 6) & 0x3f);
+        buf[3] = 0x80 + (c & 0x3f);
+        return 4;
+    }
+    if (c < 0x4000000) {
+        buf[0] = 0xf8 + (c >> 24);
+        buf[1] = 0x80 + ((c >> 18) & 0x3f);
+        buf[2] = 0x80 + ((c >> 12) & 0x3f);
+        buf[3] = 0x80 + ((c >> 6) & 0x3f);
+        buf[4] = 0x80 + (c & 0x3f);
+        return 5;
+    }
+    buf[0] = 0xfc + (c >> 30);
+    buf[1] = 0x80 + ((c >> 24) & 0x3f);
+    buf[2] = 0x80 + ((c >> 18) & 0x3f);
+    buf[3] = 0x80 + ((c >> 12) & 0x3f);
+    buf[4] = 0x80 + ((c >> 6) & 0x3f);
+    buf[5] = 0x80 + (c & 0x3f);
+    return 6;
 }
 
 /**
@@ -154,7 +232,7 @@ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data)
  * chars. The key sequence do not need to be NUL terminated.
  * Keylen of 0 signalized a key timeout.
  */
-MapState map_handle_keys(const char *keys, int keylen)
+MapState map_handle_keys(const guchar *keys, int keylen)
 {
     int ambiguous;
     Map *match = NULL;
@@ -180,13 +258,14 @@ MapState map_handle_keys(const char *keys, int keylen)
     while (true) {
         /* send any resolved key to the parser */
         static int csi = 0;
+        static int c;
         while (map.resolved > 0) {
             /* pop the next char from queue */
             map.resolved--;
             map.qlen--;
 
             /* get first char of queue */
-            char qk = map.queue[0];
+            int qk = map.queue[0];
             /* move all other queue entries one step to the left */
             for (int i = 0; i < map.qlen; i++) {
                 map.queue[i] = map.queue[i + 1];
@@ -199,21 +278,21 @@ MapState map_handle_keys(const char *keys, int keylen)
             /* TODO make it simplier to skip the special keys here */
             if ((qk & 0xff) == CSI) {
                 csi = 2;
-                vb.state.processed_key = false;
                 continue;
-            }
-            if (csi > 0) {
+            } else if (csi == 2) {
                 csi--;
-                vb.state.processed_key = false;
-                showcmd(NULL, 0);
+                c = qk;
                 continue;
+            } else if (csi == 1) {
+                csi--;
+                qk = TERMCAP2KEY(c, qk);
             }
 
             /* remove the nomap flag */
             vb.mode->flags &= ~FLAG_NOMAP;
 
             /* send the key to the parser */
-            if (RESULT_MORE != mode_handle_key((unsigned int)qk)) {
+            if (RESULT_MORE != mode_handle_key((int)qk)) {
                 showcmd(NULL, 0);
             }
         }
@@ -423,40 +502,26 @@ static char *convert_keylabel(char *in, int inlen, int *len)
         char *ch;
         int  chlen;
     } keys[] = {
-        {"<CR>",    4, "\n",           1},
-        {"<Tab>",   5, "\t",           1},
-        {"<Esc>",   5, "\x1b",         1},
-        {"<Up>",    4, CSI_STR "ku",   3},
-        {"<Down>",  6, CSI_STR "kd",   3},
-        {"<Left>",  6, CSI_STR "kl",   3},
-        {"<Right>", 7, CSI_STR "kr",   3},
-        /* convert function keys to gEsc+num */
-        /* TODO allow to calculate the ch programmatic instead of mapping the
-         * function keys here */
-        {"<C-F1>",  6, CSI_STR "\x01", 2},
-        {"<C-F2>",  6, CSI_STR "\x02", 2},
-        {"<C-F3>",  6, CSI_STR "\x03", 2},
-        {"<C-F4>",  6, CSI_STR "\x04", 2},
-        {"<C-F5>",  6, CSI_STR "\x05", 2},
-        {"<C-F6>",  6, CSI_STR "\x06", 2},
-        {"<C-F7>",  6, CSI_STR "\x07", 2},
-        {"<C-F8>",  6, CSI_STR "\x08", 2},
-        {"<C-F9>",  6, CSI_STR "\x09", 2},
-        {"<C-F10>", 7, CSI_STR "\x0a", 2},
-        {"<C-F11>", 7, CSI_STR "\x0b", 2},
-        {"<C-F12>", 7, CSI_STR "\x0c", 2},
-        {"<F1>",    4, CSI_STR "\x0d", 2},
-        {"<F2>",    4, CSI_STR "\x0e", 2},
-        {"<F3>",    4, CSI_STR "\x0f", 2},
-        {"<F4>",    4, CSI_STR "\x10", 2},
-        {"<F5>",    4, CSI_STR "\x11", 2},
-        {"<F6>",    4, CSI_STR "\x12", 2},
-        {"<F7>",    4, CSI_STR "\x13", 2},
-        {"<F8>",    4, CSI_STR "\x14", 2},
-        {"<F9>",    4, CSI_STR "\x15", 2},
-        {"<F10>",   5, CSI_STR "\x16", 2},
-        {"<F11>",   5, CSI_STR "\x17", 2},
-        {"<F12>",   5, CSI_STR "\x18", 2},
+        {"<CR>",    4, "\n",         1},
+        {"<Tab>",   5, "\t",         1},
+        {"<S-Tab>", 7, CSI_STR "kB", 3},
+        {"<Esc>",   5, "\x1b",       1},
+        {"<Up>",    4, CSI_STR "ku", 3},
+        {"<Down>",  6, CSI_STR "kd", 3},
+        {"<Left>",  6, CSI_STR "kl", 3},
+        {"<Right>", 7, CSI_STR "kr", 3},
+        {"<F1>",    4, CSI_STR "k1", 3},
+        {"<F2>",    4, CSI_STR "k2", 3},
+        {"<F3>",    4, CSI_STR "k3", 3},
+        {"<F4>",    4, CSI_STR "k4", 3},
+        {"<F5>",    4, CSI_STR "k5", 3},
+        {"<F6>",    4, CSI_STR "k6", 3},
+        {"<F7>",    4, CSI_STR "k7", 3},
+        {"<F8>",    4, CSI_STR "k8", 3},
+        {"<F9>",    4, CSI_STR "k9", 3},
+        {"<F10>",   5, CSI_STR "k;", 3},
+        {"<F11>",   5, CSI_STR "F1", 3},
+        {"<F12>",   5, CSI_STR "F2", 3},
     };
 
     for (int i = 0; i < LENGTH(keys); i++) {
@@ -476,7 +541,7 @@ static char *convert_keylabel(char *in, int inlen, int *len)
 static gboolean do_timeout(gpointer data)
 {
     /* signalize the timeout to the key handler */
-    map_handle_keys("", 0);
+    map_handle_keys((guchar*)"", 0);
 
     /* call only once */
     return false;
index 26d66df..3e79610 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -34,7 +34,7 @@ typedef enum {
 
 void map_cleanup(void);
 gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data);
-MapState map_handle_keys(const char *keys, int keylen);
+MapState map_handle_keys(const guchar *keys, int keylen);
 void map_insert(char *in, char *mapped, char mode);
 gboolean map_delete(char *in, char mode);
 
index 15a926b..4d9ef08 100644 (file)
@@ -92,11 +92,10 @@ void mode_enter(char id)
     vb_update_statusbar();
 }
 
-VbResult mode_handle_key(unsigned int key)
+VbResult mode_handle_key(int key)
 {
     VbResult res;
     if (vb.mode && vb.mode->keypress) {
-        key &= 0xff;
 #ifdef DEBUG
         int flags = vb.mode->flags;
         int id    = vb.mode->id;
index cd50159..4040f42 100644 (file)
@@ -28,7 +28,7 @@ void mode_cleanup(void);
 void mode_add(char id, ModeTransitionFunc enter, ModeTransitionFunc leave,
     ModeKeyFunc keypress, ModeInputChangedFunc input_changed);
 void mode_enter(char id);
-VbResult mode_handle_key(unsigned int key);
+VbResult mode_handle_key(int key);
 gboolean mode_input_focusin(GtkWidget *widget, GdkEventFocus *event, gpointer data);
 gboolean mode_input_focusout(GtkWidget *widget, GdkEventFocus *event, gpointer data);
 void mode_input_changed(GtkTextBuffer* buffer, gpointer data);
index 44396ca..6d08ec6 100644 (file)
@@ -23,6 +23,7 @@
 #include "mode.h"
 #include "main.h"
 #include "normal.h"
+#include "ascii.h"
 #include "command.h"
 #include "hints.h"
 #include "dom.h"
@@ -36,10 +37,10 @@ typedef enum {
 } Phase;
 
 struct NormalCmdInfo_s {
-    int count;          /* count used for the command */
-    unsigned char cmd;  /* command key */
-    unsigned char ncmd; /* second command key (optional) */
-    Phase phase;        /* current parsing phase */
+    int count;   /* count used for the command */
+    char cmd;    /* command key */
+    char ncmd;   /* second command key (optional) */
+    Phase phase; /* current parsing phase */
 } info = {0, '\0', '\0', PHASE_START};
 
 typedef VbResult (*NormalCommand)(const NormalCmdInfo *info);
@@ -223,7 +224,7 @@ void normal_leave(void)
 /**
  * Handles the keypress events from webview and inputbox.
  */
-VbResult normal_keypress(unsigned int key)
+VbResult normal_keypress(int key)
 {
     State *s = &vb.state;
     VbResult res;
@@ -242,13 +243,15 @@ VbResult normal_keypress(unsigned int key)
         info.cmd   = key;
         vb.mode->flags |= FLAG_NOMAP;
     } else {
-        info.cmd   = key & 0xff;
+        info.cmd   = key;
         info.phase = PHASE_COMPLETE;
     }
 
     if (info.phase == PHASE_COMPLETE) {
-        if (commands[info.cmd].func) {
-            res = commands[info.cmd].func(&info);
+        /* TODO allow more commands - some that are looked up via command key
+         * direct and those that are searched via binary search */
+        if ((guchar)info.cmd <= LENGTH(commands) && commands[(guchar)info.cmd].func) {
+            res = commands[(guchar)info.cmd].func(&info);
         } else {
             /* let gtk handle the keyevent if we have no command attached to
              * it */
index 02a887f..8060d2c 100644 (file)
@@ -27,6 +27,6 @@ typedef struct NormalCmdInfo_s NormalCmdInfo;
 
 void normal_enter(void);
 void normal_leave(void);
-VbResult normal_keypress(unsigned int key);
+VbResult normal_keypress(int key);
 
 #endif /* end of include guard: _NORMAL_H */
index b835d96..3aac3f7 100644 (file)
@@ -45,7 +45,7 @@ void pass_leave(void)
     vb_set_input_text("");
 }
 
-VbResult pass_keypress(unsigned int key)
+VbResult pass_keypress(int key)
 {
     if (key == CTRL('[')) { /* esc */
         mode_enter('n');
index 1e34eb0..0553a95 100644 (file)
@@ -25,6 +25,6 @@
 
 void pass_enter(void);
 void pass_leave(void);
-VbResult pass_keypress(unsigned int key);
+VbResult pass_keypress(int key);
 
 #endif /* end of include guard: _PASS_H */
index f468da7..82d1437 100644 (file)
@@ -217,7 +217,7 @@ gboolean util_file_prepend(const char *file, const char *format, ...)
 
 char *util_strcasestr(const char *haystack, const char *needle)
 {
-    unsigned char c1, c2;
+    guchar c1, c2;
     int i, j;
     int nlen = strlen(needle);
     int hlen = strlen(haystack) - nlen + 1;