From 9fd3263bfd4ea794dd9eb81b763b5e94dc93ddda Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Sun, 6 Oct 2013 22:57:03 +0200 Subject: [PATCH] Allow utf8 for keybinds. Used some key processing stuff from vim. --- doc/vimb.1 | 16 +-- src/ascii.h | 58 ++++++++++ src/default.h | 2 - src/ex.c | 11 +- src/ex.h | 2 +- src/hints.c | 10 +- src/hints.h | 2 +- src/input.c | 2 +- src/input.h | 2 +- src/main.h | 6 +- src/map.c | 297 ++++++++++++++++++++++++++++++-------------------- src/map.h | 2 +- src/mode.c | 3 +- src/mode.h | 2 +- src/normal.c | 19 ++-- src/normal.h | 2 +- src/pass.c | 2 +- src/pass.h | 2 +- src/util.c | 2 +- 19 files changed, 283 insertions(+), 159 deletions(-) create mode 100644 src/ascii.h diff --git a/doc/vimb.1 b/doc/vimb.1 index 6b1666c..46348ea 100644 --- a/doc/vimb.1 +++ b/doc/vimb.1 @@ -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\fP Selects the first highlighted element, or the current focused. -.IP "\fB, CTRL\-I\fP" +.IP "\fB\fP" Moves the focus to the next hint element. -.IP "\fB, CTRL\-O\fP" +.IP "\fB\fP" Moves the focus to the previous hint element. .IP "\fB, 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 , CTRL\-I +.B Start completion of the content in inputbox in forward direction. .TP -.B , CTRL\-O +.B Start completion of the content in inputbox in backward direction. .TP -.B , CTRL\-P +.B Step backward in the command history. .TP -.B , CTRL\-N +.B Step forward in the command history. .SS Open diff --git a/src/ascii.h b/src/ascii.h new file mode 100644 index 0000000..8a13349 --- /dev/null +++ b/src/ascii.h @@ -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 */ diff --git a/src/default.h b/src/default.h index 51d9305..3664fa6 100644 --- a/src/default.h +++ b/src/default.h @@ -66,8 +66,6 @@ static char *default_config[] = { "set insecure-content-run=off", #endif "set timeoutlen=1000", - "cmap ", - "cmap ", NULL }; diff --git a/src/ex.c b/src/ex.c index 128f009..4ea5859 100644 --- 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; diff --git a/src/ex.h b/src/ex.h index acb71e6..50a7ccc 100644 --- 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); diff --git a/src/hints.c b/src/hints.c index e62bf63..b2d659b 100644 --- a/src/hints.c +++ b/src/hints.c @@ -22,6 +22,7 @@ #include #include #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; diff --git a/src/hints.h b/src/hints.h index 640401b..f721883 100644 --- a/src/hints.h +++ b/src/hints.h @@ -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); diff --git a/src/input.c b/src/input.c index ac4a7f3..5f46947 100644 --- a/src/input.c +++ b/src/input.c @@ -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 */ diff --git a/src/input.h b/src/input.h index fa8c908..4b9b3ef 100644 --- a/src/input.h +++ b/src/input.h @@ -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 */ diff --git a/src/main.h b/src/main.h index 89edfd0..5ad8805 100644 --- a/src/main.h +++ b/src/main.h @@ -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; diff --git a/src/map.c b/src/map.c index 1bc423d..f49ba5e 100644 --- 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 or -> \001 - * and -> \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 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 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[] = { - {"", 4, "\n", 1}, - {"", 5, "\t", 1}, - {"", 5, "\x1b", 1}, - {"", 4, CSI_STR "ku", 3}, - {"", 6, CSI_STR "kd", 3}, - {"", 6, CSI_STR "kl", 3}, - {"", 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 */ - {"", 6, CSI_STR "\x01", 2}, - {"", 6, CSI_STR "\x02", 2}, - {"", 6, CSI_STR "\x03", 2}, - {"", 6, CSI_STR "\x04", 2}, - {"", 6, CSI_STR "\x05", 2}, - {"", 6, CSI_STR "\x06", 2}, - {"", 6, CSI_STR "\x07", 2}, - {"", 6, CSI_STR "\x08", 2}, - {"", 6, CSI_STR "\x09", 2}, - {"", 7, CSI_STR "\x0a", 2}, - {"", 7, CSI_STR "\x0b", 2}, - {"", 7, CSI_STR "\x0c", 2}, - {"", 4, CSI_STR "\x0d", 2}, - {"", 4, CSI_STR "\x0e", 2}, - {"", 4, CSI_STR "\x0f", 2}, - {"", 4, CSI_STR "\x10", 2}, - {"", 4, CSI_STR "\x11", 2}, - {"", 4, CSI_STR "\x12", 2}, - {"", 4, CSI_STR "\x13", 2}, - {"", 4, CSI_STR "\x14", 2}, - {"", 4, CSI_STR "\x15", 2}, - {"", 5, CSI_STR "\x16", 2}, - {"", 5, CSI_STR "\x17", 2}, - {"", 5, CSI_STR "\x18", 2}, + {"", 4, "\n", 1}, + {"", 5, "\t", 1}, + {"", 7, CSI_STR "kB", 3}, + {"", 5, "\x1b", 1}, + {"", 4, CSI_STR "ku", 3}, + {"", 6, CSI_STR "kd", 3}, + {"", 6, CSI_STR "kl", 3}, + {"", 7, CSI_STR "kr", 3}, + {"", 4, CSI_STR "k1", 3}, + {"", 4, CSI_STR "k2", 3}, + {"", 4, CSI_STR "k3", 3}, + {"", 4, CSI_STR "k4", 3}, + {"", 4, CSI_STR "k5", 3}, + {"", 4, CSI_STR "k6", 3}, + {"", 4, CSI_STR "k7", 3}, + {"", 4, CSI_STR "k8", 3}, + {"", 4, CSI_STR "k9", 3}, + {"", 5, CSI_STR "k;", 3}, + {"", 5, CSI_STR "F1", 3}, + {"", 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; diff --git a/src/map.h b/src/map.h index 26d66df..3e79610 100644 --- 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); diff --git a/src/mode.c b/src/mode.c index 15a926b..4d9ef08 100644 --- a/src/mode.c +++ b/src/mode.c @@ -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; diff --git a/src/mode.h b/src/mode.h index cd50159..4040f42 100644 --- a/src/mode.h +++ b/src/mode.h @@ -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); diff --git a/src/normal.c b/src/normal.c index 44396ca..6d08ec6 100644 --- a/src/normal.c +++ b/src/normal.c @@ -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 */ diff --git a/src/normal.h b/src/normal.h index 02a887f..8060d2c 100644 --- a/src/normal.h +++ b/src/normal.h @@ -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 */ diff --git a/src/pass.c b/src/pass.c index b835d96..3aac3f7 100644 --- a/src/pass.c +++ b/src/pass.c @@ -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'); diff --git a/src/pass.h b/src/pass.h index 1e34eb0..0553a95 100644 --- a/src/pass.h +++ b/src/pass.h @@ -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 */ diff --git a/src/util.c b/src/util.c index f468da7..82d1437 100644 --- a/src/util.c +++ b/src/util.c @@ -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; -- 2.20.1