From a76057df97157dc76959bcd40649f5953aebc9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Sun, 13 Sep 2015 17:49:38 +0200 Subject: vis: rework input handling using libtermkey Key bindings are now specified as symbolic key strings, this will eventually allow run time configurable key mappings. This introduces a bulid time dependency on libtermkey which can be found at: http://www.leonerd.org.uk/code/libtermkey/ --- ui-curses.c | 84 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 43 deletions(-) (limited to 'ui-curses.c') diff --git a/ui-curses.c b/ui-curses.c index 4705d08..b2fd099 100644 --- a/ui-curses.c +++ b/ui-curses.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "ui.h" @@ -62,6 +63,8 @@ typedef struct { char info[255]; /* info message displayed at the bottom of the screen */ int width, height; /* terminal dimensions available for all windows */ enum UiLayout layout; /* whether windows are displayed horizontally or vertically */ + TermKey *termkey; /* libtermkey instance to handle keyboard input */ + char key[64]; /* string representation of last pressed key */ } UiCurses; struct UiCursesWin { @@ -518,6 +521,11 @@ static bool ui_init(Ui *ui, Editor *ed) { return true; } +static TermKey *ui_termkey_get(Ui *ui) { + UiCurses *uic = (UiCurses*)ui; + return uic->termkey; +} + static void ui_suspend(Ui *ui) { endwin(); raise(SIGSTOP); @@ -532,59 +540,51 @@ static bool ui_haskey(Ui *ui) { return c != ERR; } -static Key ui_getkey(Ui *ui) { - Key key = { .str = "", .code = 0 }; - int keycode = getch(), cur = 0; - if (keycode == ERR) - return key; - - if (keycode >= KEY_MIN) { - key.code = keycode; - } else { - key.str[cur++] = keycode; - int len = 1; - unsigned char keychar = keycode; - if (ISASCII(keychar)) len = 1; - else if (keychar == 0x1B || keychar >= 0xFC) len = 6; - else if (keychar >= 0xF8) len = 5; - else if (keychar >= 0xF0) len = 4; - else if (keychar >= 0xE0) len = 3; - else if (keychar >= 0xC0) len = 2; - len = MIN(len, LENGTH(key.str)); - - if (cur < len) { - nodelay(stdscr, TRUE); - for (int t; cur < len && (t = getch()) != ERR; cur++) - key.str[cur] = t; - nodelay(stdscr, FALSE); - } - - if (len == 1) { - switch (key.str[0]) { - case 127: - case CONTROL('H'): - key.code = KEY_BACKSPACE; - key.str[0] = '\0'; - break; - } - } +static const char *ui_getkey(Ui *ui) { + UiCurses *uic = (UiCurses*)ui; + TermKeyKey key; + TermKeyResult ret = termkey_getkey(uic->termkey, &key); + + if (ret == TERMKEY_RES_AGAIN) { + struct pollfd fd; + fd.fd = STDIN_FILENO; + fd.events = POLLIN; + if (poll(&fd, 1, termkey_get_waittime(uic->termkey)) == 0) + ret = termkey_getkey_force(uic->termkey, &key); } - - return key; + + if (ret != TERMKEY_RES_KEY) + return NULL; + termkey_strfkey(uic->termkey, uic->key, sizeof(uic->key), &key, TERMKEY_FORMAT_VIM); + return uic->key; } static void ui_terminal_save(Ui *ui) { + UiCurses *uic = (UiCurses*)ui; + termkey_stop(uic->termkey); curs_set(1); reset_shell_mode(); } static void ui_terminal_restore(Ui *ui) { + UiCurses *uic = (UiCurses*)ui; reset_prog_mode(); wclear(stdscr); curs_set(0); + termkey_start(uic->termkey); } Ui *ui_curses_new(Color *colors) { + + UiCurses *uic = calloc(1, sizeof(UiCurses)); + Ui *ui = (Ui*)uic; + if (!uic) + return NULL; + if (!(uic->termkey = termkey_new(STDIN_FILENO, TERMKEY_FLAG_UTF8))) { + ui_curses_free(ui); + return NULL; + } + setlocale(LC_CTYPE, ""); if (!getenv("ESCDELAY")) set_escdelay(50); @@ -605,14 +605,10 @@ Ui *ui_curses_new(Color *colors) { would clear the screen (overwrite it with an empty / unused stdscr */ refresh(); - UiCurses *uic = calloc(1, sizeof(UiCurses)); - Ui *ui = (Ui*)uic; - if (!uic) - return NULL; - *ui = (Ui) { .init = ui_init, .free = ui_curses_free, + .termkey_get = ui_termkey_get, .suspend = ui_suspend, .resume = ui_resize, .resize = ui_resize, @@ -660,6 +656,8 @@ void ui_curses_free(Ui *ui) { while (uic->windows) ui_window_free((UiWin*)uic->windows); endwin(); + if (uic->termkey) + termkey_destroy(uic->termkey); free(uic); } -- cgit v1.2.3