From 057467f6b33b9f7c942bd2327561b74e738285b7 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Sun, 21 Jul 2013 22:27:58 -0300 Subject: getch2: Refactor/rewrite Still uses termcap, but uses terminfo for loading the termcap database if possible. Adds configure test to find terminfo; skips the termcap test if terminfo is found since terminfo provides termcap. Use termcap completely for special keys; if we can't get it from termcap and it isn't one of the known fallbacks, we ignore its specialness and treat as a sequence of UTF-8 codes. Further hardcoded fallbacks can be added by calling keys_push_once in load_termcap; there is no limit to the amount of keys pushed. Uses the "ke" and "ks" capabilities to start / exit application mode, which is necessary on vt100 emulators (including screen, xterm and all terminals that emulate either of those) to correctly receive arrow keys. It's now possible to compile getch2 even without termcap, though it won't be of much use since it'll be unable to detect special keys. Converted to 4 spaces per tab, prettified some statements. --- configure | 26 +++ osdep/getch2.c | 536 ++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 370 insertions(+), 192 deletions(-) diff --git a/configure b/configure index 723cc96fa9..67df30c033 100755 --- a/configure +++ b/configure @@ -293,6 +293,7 @@ Installation directories: Optional features: --disable-encoding disable encoding functionality [enable] --disable-libguess disable libguess [autodetect] + --enable-terminfo use terminfo database for key codes [autodetect] --enable-termcap use termcap database for key codes [autodetect] --enable-termios use termios database for key codes [autodetect] --disable-iconv disable iconv for encoding conversion [autodetect] @@ -464,6 +465,7 @@ _libguess=auto _joystick=no _lirc=auto _lircc=auto +_terminfo=auto _termcap=auto _termios=auto _shm=auto @@ -668,6 +670,8 @@ for ac_option do --disable-lirc) _lirc=no ;; --enable-lircc) _lircc=yes ;; --disable-lircc) _lircc=no ;; + --enable-terminfo) _terminfo=yes ;; + --disable-terminfo) _terminfo=no ;; --enable-termcap) _termcap=yes ;; --disable-termcap) _termcap=no ;; --enable-termios) _termios=yes ;; @@ -1409,6 +1413,27 @@ header_check sys/videoio.h && sys_videoio_h=yes && echores "$sys_videoio_h" +echocheck "terminfo" +if test "$_terminfo" = auto ; then + _terminfo=no + for _ld_tmp in "-lncurses" "-lncursesw"; do + statement_check term.h 'setupterm(NULL, 1, NULL)' $_ld_tmp && + libs_mplayer="$libs_mplayer $_ld_tmp" && _terminfo=yes && break + done +fi +if test "$_terminfo" = yes ; then + def_terminfo='#define HAVE_TERMINFO 1' + test $_ld_tmp && res_comment="using $_ld_tmp" + + if test "$_termcap" = auto ; then + _termcap = yes # terminfo provides termcap + fi +else + def_terminfo='#undef HAVE_TERMINFO' +fi +echores "$_terminfo" + + echocheck "termcap" if test "$_termcap" = auto ; then _termcap=no @@ -3098,6 +3123,7 @@ $def_posix_select $def_select $def_setmode $def_shm +$def_terminfo $def_termcap $def_termios diff --git a/osdep/getch2.c b/osdep/getch2.c index 0e58b53a4d..e5752ae235 100644 --- a/osdep/getch2.c +++ b/osdep/getch2.c @@ -23,20 +23,14 @@ #include "config.h" -//#define HAVE_TERMCAP #if !defined(__MORPHOS__) #define CONFIG_IOCTL #endif -#define MAX_KEYS 64 -#define BUF_LEN 256 - -#include #include +#include #include #include -#include -#include #ifdef CONFIG_IOCTL #include #endif @@ -51,8 +45,8 @@ #endif #include -#include +#include "core/mp_common.h" #include "core/bstr.h" #include "core/input/input.h" #include "core/input/keycodes.h" @@ -62,102 +56,303 @@ static volatile struct termios tio_orig; static volatile int tio_orig_set; #endif -static int getch2_len=0; -static unsigned char getch2_buf[BUF_LEN]; -int screen_width=80; -int screen_height=24; +int screen_width = 80; +int screen_height = 24; char * erase_to_end_of_line = NULL; typedef struct { - int len; - int code; - char chars[8]; + char *cap; + int len; + int code; + char chars[8]; } keycode_st; -static keycode_st getch2_keys[MAX_KEYS]; -static int getch2_key_db=0; + +typedef struct { + keycode_st *map; + int len; + int cap; +} keycode_map; + +static keycode_map getch2_keys; #ifdef HAVE_TERMCAP +static char *term_rmkx = NULL; +static char *term_smkx = NULL; + +#ifdef HAVE_TERMINFO +#include +#endif +#include + +#endif + +static keycode_st *keys_push(char *p, int code) { + if (getch2_keys.len == getch2_keys.cap) { + getch2_keys.cap *= 2; + if (getch2_keys.cap == 0) + getch2_keys.cap = 32; + + getch2_keys.map = realloc(getch2_keys.map, sizeof(keycode_st) * getch2_keys.cap); + } + + keycode_st *st = &getch2_keys.map[getch2_keys.len++]; + st->cap = NULL; + st->len = strlen(p); + st->code = code; + strncpy(st->chars, p, 8); + + return st; +} + +static int keys_count_matches(char *buf, int buflen) { + int count = 0; + if (buflen < 0) + buflen = strlen(buf); + + for (int i = 0; i < getch2_keys.len; i++) { + keycode_st *st = &getch2_keys.map[i]; + int len = MPMIN(buflen, st->len); + + if (memcmp(buf, st->chars, len) == 0) + count++; + } + return count; +} + +static keycode_st *keys_search(char *buf, int buflen) { + if (buflen < 0) + buflen = strlen(buf); + + for (int i = 0; i < getch2_keys.len; i++) { + keycode_st *st = &getch2_keys.map[i]; + + if (buflen >= st->len && memcmp(buf, st->chars, st->len) == 0) + return st; + } + return NULL; +} + +static keycode_st *keys_get_by_cap(char *cap) { + for (int i = 0; i < getch2_keys.len; i++) { + keycode_st *st = &getch2_keys.map[i]; + + if (strcmp(cap, st->cap) == 0) + return st; + } + return NULL; +} + +/* pushes only if there is no duplicate. + important as we only consider keys if the matches are unique. */ +static keycode_st* keys_push_once(char *p, int code) { + keycode_st *st = keys_search(p, -1); + if (!st) + return keys_push(p, code); + return st; +} + +#ifdef HAVE_TERMCAP + +typedef struct { + char *buf; + char *pos; + int cap; +} buf_st; +static buf_st termcap_buf; + +static void ensure_cap(buf_st *buf, int cap) { + if (buf->pos - buf->buf < cap) { + ptrdiff_t diff = buf->pos - buf->buf; + buf->cap += cap; + buf->buf = realloc(buf->buf, buf->cap); + buf->pos = buf->buf + diff; + } +} + +static char *termcap_get(char *id) { + ensure_cap(&termcap_buf, 1024); + return tgetstr(id, &termcap_buf.pos); +} + +typedef struct { + char *id; + int code; +} cap_key_pair; + #if 0 -#include -#else -int tgetent(char *BUFFER, char *TERMTYPE); -int tgetnum(char *NAME); -int tgetflag(char *NAME); -char *tgetstr(char *NAME, char **AREA); +#include +#include + +static void debug_keycode(keycode_st *st) { + if (!st) + return; + + char buf[128]; /* worst case should be 70 bytes */ + unsigned char *b = &buf[0]; + unsigned char *p = &st->chars[0]; + + if (st->cap) + b += sprintf(b, "%s: ", st->cap); + + for(; *p; p++) { + if (*p == 27) + b += sprintf(b, "\\e"); + else if (*p < 27) + b += sprintf(b, "^%c", '@' + *p); + else if (!isgraph(*p)) + b += sprintf(b, "\\x%02x", (unsigned int)*p); + else + b += sprintf(b, "%c", *p); + } + fprintf(stderr, "%s\n", buf); +} #endif -static char term_buffer[4096]; -static char term_buffer2[4096]; -static char *term_p=term_buffer2; - -static void termcap_add(char *id,int code){ -char *p=tgetstr(id,&term_p); - if(!p) return; - if(getch2_key_db>=MAX_KEYS) return; - getch2_keys[getch2_key_db].len=strlen(p); - strncpy(getch2_keys[getch2_key_db].chars,p,8); - getch2_keys[getch2_key_db].code=code; - ++getch2_key_db; -/* printf("%s=%s\n",id,p); */ +static void termcap_add(cap_key_pair pair) { + char *p = termcap_get(pair.id); + if (p) { + keycode_st *st = keys_push_once(p, pair.code); + if (st) + st->cap = pair.id; + /* debug_keycode(st); */ + } } -static int success=0; +static void termcap_add_extra_f_keys(void) { + char capbuf[3]; + for (int i = 11; i < 0x20; i++) { + unsigned char c; + if (i < 20) { /* 1-9 */ + c = '0' + (i - 10); + } else { /* A-Z */ + c = 'A' + (i - 20); + } -int load_termcap(char *termtype){ - if(!termtype) termtype=getenv("TERM"); - if(!termtype) termtype="unknown"; - success=tgetent(term_buffer, termtype); - if(success<0){ printf("Could not access the 'termcap' data base.\n"); return 0; } - if(success==0){ printf("Terminal type `%s' is not defined.\n", termtype);return 0;} - - screen_width=tgetnum("co"); - screen_height=tgetnum("li"); - if(screen_width<1 || screen_width>255) screen_width=80; - if(screen_height<1 || screen_height>255) screen_height=24; - erase_to_end_of_line= tgetstr("ce",&term_p); - - termcap_add("kP",MP_KEY_PGUP); - termcap_add("kN",MP_KEY_PGDWN); - termcap_add("kh",MP_KEY_HOME); - termcap_add("kH",MP_KEY_END); - termcap_add("kI",MP_KEY_INS); - termcap_add("kD",MP_KEY_DEL); - termcap_add("kb",MP_KEY_BS); - termcap_add("kl",MP_KEY_LEFT); - termcap_add("kd",MP_KEY_DOWN); - termcap_add("ku",MP_KEY_UP); - termcap_add("kr",MP_KEY_RIGHT); - termcap_add("k0",MP_KEY_F+0); - termcap_add("k1",MP_KEY_F+1); - termcap_add("k2",MP_KEY_F+2); - termcap_add("k3",MP_KEY_F+3); - termcap_add("k4",MP_KEY_F+4); - termcap_add("k5",MP_KEY_F+5); - termcap_add("k6",MP_KEY_F+6); - termcap_add("k7",MP_KEY_F+7); - termcap_add("k8",MP_KEY_F+8); - termcap_add("k9",MP_KEY_F+9); - termcap_add("k;",MP_KEY_F+10); - return getch2_key_db; + sprintf(&capbuf[0], "F%c", c); + + char *p = termcap_get(capbuf); + if (p) + keys_push_once(p, MP_KEY_F+i); + else + break; /* unlikely that the database has further keys */ + } } #endif -void get_screen_size(void){ +int load_termcap(char *termtype){ +#ifdef HAVE_TERMCAP + +#ifdef HAVE_TERMINFO + use_env(TRUE); + setupterm(termtype, 1, NULL); +#else + static char term_buffer[2048]; + if (!termtype) termtype = getenv("TERM"); + if (!termtype) termtype = "ansi"; + int success = tgetent(term_buffer, termtype); + if (success < 0) { + printf("Could not access the 'termcap' data base.\n"); + return 0; + } else if (success == 0) { + printf("Terminal type `%s' is not defined.\n", termtype); + return 0; + } +#endif + ensure_cap(&termcap_buf, 2048); + + erase_to_end_of_line = termcap_get("ce"); + + screen_width = tgetnum("co"); + screen_height = tgetnum("li"); + if (screen_width < 1 || screen_width > 255) + screen_width = 80; + if (screen_height < 1 || screen_height > 255) + screen_height = 24; + + term_smkx = termcap_get("ks"); + term_rmkx = termcap_get("ke"); + + cap_key_pair keys[] = { + {"kP", MP_KEY_PGUP}, {"kN", MP_KEY_PGDWN}, {"kh", MP_KEY_HOME}, {"kH", MP_KEY_END}, + {"kI", MP_KEY_INS}, {"kD", MP_KEY_DEL}, /* on PC keyboards */ {"@7", MP_KEY_END}, + + {"kl", MP_KEY_LEFT}, {"kd", MP_KEY_DOWN}, {"ku", MP_KEY_UP}, {"kr", MP_KEY_RIGHT}, + + {"do", MP_KEY_ENTER}, + {"kb", MP_KEY_BS}, + + {"k1", MP_KEY_F+1}, {"k2", MP_KEY_F+2}, {"k3", MP_KEY_F+3}, + {"k4", MP_KEY_F+4}, {"k5", MP_KEY_F+5}, {"k6", MP_KEY_F+6}, + {"k7", MP_KEY_F+7}, {"k8", MP_KEY_F+8}, {"k9", MP_KEY_F+9}, + {"k;", MP_KEY_F+10}, {"k0", MP_KEY_F+0}, + + /* K2 is the keypad center */ + {"K2", MP_KEY_KP5}, + + /* EOL */ + {NULL}, + }; + for (int i = 0; keys[i].id; i++) { + termcap_add(keys[i]); + } + termcap_add_extra_f_keys(); +#endif + + /* special cases (hardcoded, no need for HAVE_TERMCAP) */ + + /* it's important to use keys_push_once as we can't have duplicates */ + + /* many terminals, for emacs compatibility, use 0x7f instead of ^H + when typing backspace, even when the 'kb' cap says otherwise. */ + keys_push_once("\177", MP_KEY_BS); + + /* mintty always sends these when using the numpad arrows, + even in application mode, for telling them from regular arrows. */ + keys_push_once("\033[A", MP_KEY_UP); + keys_push_once("\033[B", MP_KEY_DOWN); + keys_push_once("\033[C", MP_KEY_RIGHT); + keys_push_once("\033[D", MP_KEY_LEFT); + + /* mintty uses this instead of the "K2" cap for keypad center */ + keys_push_once("\033OE", MP_KEY_KP5); + + return getch2_keys.len; +} + +void get_screen_size(void) { #ifdef CONFIG_IOCTL - struct winsize ws; - if (ioctl(0, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col) return; -/* printf("Using IOCTL\n"); */ - screen_width=ws.ws_col; - screen_height=ws.ws_row; + struct winsize ws; + if (ioctl(0, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col) + return; + + screen_width = ws.ws_col; + screen_height = ws.ws_row; #endif } +#define BUF_LEN 256 + +static unsigned char getch2_buf[BUF_LEN]; +static int getch2_len = 0; +static int getch2_pos = 0; + +static void walk_buf(unsigned int count) { + if (!(count < BUF_LEN && count <= getch2_len)) + abort(); + + memmove(&getch2_buf[0], &getch2_buf[count], getch2_len - count); + getch2_len -= count; + getch2_pos -= count; + if (getch2_pos < 0) + getch2_pos = 0; +} + bool getch2(struct input_ctx *input_ctx) { - int retval = read(0, &getch2_buf[getch2_len], BUF_LEN-getch2_len); + int retval = read(0, &getch2_buf[getch2_pos], BUF_LEN - getch2_len - getch2_pos); /* Return false on EOF to stop running select() on the FD, as it'd * trigger all the time. Note that it's possible to get temporary * EOF on terminal if the user presses ctrl-d, but that shouldn't @@ -168,149 +363,103 @@ bool getch2(struct input_ctx *input_ctx) return retval; getch2_len += retval; - while (getch2_len > 0 && (getch2_len > 1 || getch2_buf[0] != 27)) { - int i, len, code; + static enum { + STATE_INITIAL = 0, + STATE_UTF8, + } state = STATE_INITIAL; + static int utf8_len = 0; - /* First find in the TERMCAP database: */ - for (i = 0; i < getch2_key_db; i++) { - if ((len = getch2_keys[i].len) <= getch2_len) - if(memcmp(getch2_keys[i].chars, getch2_buf, len) == 0) { - code = getch2_keys[i].code; - goto found; - } - } - /* We always match some keypress here, with length 1 if nothing else. - * Since some of the cases explicitly test remaining buffer length - * having a keycode only partially read in the buffer could incorrectly - * use the first byte as an independent character. - * However the buffer is big enough that this shouldn't happen too - * easily, and it's been this way for years without many complaints. - * I see no simple fix as there's no easy test which would tell - * whether a string must be part of a longer keycode. */ - len = 1; - code = getch2_buf[0]; - /* Check the well-known codes... */ - if (code != 27) { - if (code == 'A'-64) code = MP_KEY_HOME; - else if (code == 'E'-64) code = MP_KEY_END; - else if (code == 'D'-64) code = MP_KEY_DEL; - else if (code == 'H'-64) code = MP_KEY_BS; - else if (code == 'U'-64) code = MP_KEY_PGUP; - else if (code == 'V'-64) code = MP_KEY_PGDWN; - else if (code == 8 || code==127) code = MP_KEY_BS; - else if (code == 10 || code==13) { - if (getch2_len > 1) { - int c = getch2_buf[1]; - if ((c == 10 || c == 13) && (c != code)) - len = 2; - } - code = MP_KEY_ENTER; - } else { - int utf8len = bstr_parse_utf8_code_length(code); - if (utf8len > 0 && utf8len <= getch2_len) { - struct bstr s = { getch2_buf, utf8len }; - int unicode = bstr_decode_utf8(s, NULL); - if (unicode > 0) { - len = utf8len; - code = unicode; - } - } - } - } - else if (getch2_len > 1) { - int c = getch2_buf[1]; - if (c == 27) { - code = MP_KEY_ESC; - len = 2; - goto found; - } - if (c >= '0' && c <= '9') { - code = c-'0'+MP_KEY_F; - len = 2; - goto found; - } - if (getch2_len >= 4 && c == '[' && getch2_buf[2] == '[') { - int c = getch2_buf[3]; - if (c >= 'A' && c < 'A'+12) { - code = MP_KEY_F+1 + c-'A'; - len = 4; - goto found; - } - } - if ((c == '[' || c == 'O') && getch2_len >= 3) { - int c = getch2_buf[2]; - const int ctable[] = { - MP_KEY_UP, MP_KEY_DOWN, MP_KEY_RIGHT, MP_KEY_LEFT, 0, - MP_KEY_END, MP_KEY_PGDWN, MP_KEY_HOME, MP_KEY_PGUP, 0, 0, MP_KEY_INS, 0, 0, 0, - MP_KEY_F+1, MP_KEY_F+2, MP_KEY_F+3, MP_KEY_F+4}; - if (c >= 'A' && c <= 'S') - if (ctable[c - 'A']) { - code = ctable[c - 'A']; - len = 3; - goto found; + while (getch2_pos < getch2_len) { + unsigned char c = getch2_buf[getch2_pos++]; + + switch (state) { + case STATE_INITIAL: { +#ifdef HAVE_TERMCAP + int match_count = keys_count_matches(&getch2_buf[0], getch2_len); + if (match_count == 1) { + keycode_st *st = keys_search(&getch2_buf[0], getch2_len); + + mp_input_put_key(input_ctx, st->code); + walk_buf(st->len); + } else if (match_count > 1) { + continue; /* need more bytes to disambiguate */ + } else { +#endif + utf8_len = bstr_parse_utf8_code_length(c); + + if (utf8_len > 1) { + state = STATE_UTF8; + } else { + if (utf8_len == 1) + mp_input_put_key(input_ctx, c); + walk_buf(getch2_pos); } - } - if (getch2_len >= 4 && c == '[' && getch2_buf[3] == '~') { - int c = getch2_buf[2]; - const int ctable[8] = {MP_KEY_HOME, MP_KEY_INS, MP_KEY_DEL, MP_KEY_END, MP_KEY_PGUP, MP_KEY_PGDWN, MP_KEY_HOME, MP_KEY_END}; - if (c >= '1' && c <= '8') { - code = ctable[c - '1']; - len = 4; - goto found; +#ifdef HAVE_TERMCAP } +#endif + break; } - if (getch2_len >= 5 && c == '[' && getch2_buf[4] == '~') { - int i = getch2_buf[2] - '0'; - int j = getch2_buf[3] - '0'; - if (i >= 0 && i <= 9 && j >= 0 && j <= 9) { - const short ftable[20] = { - 11,12,13,14,15, 17,18,19,20,21, - 23,24,25,26,28, 29,31,32,33,34 }; - int a = i*10 + j; - for (i = 0; i < 20; i++) - if (ftable[i] == a) { - code = MP_KEY_F+1 + i; - len = 5; - goto found; - } + case STATE_UTF8: { + if (getch2_pos < utf8_len) /* need more bytes */ + continue; + + struct bstr s = {getch2_buf, utf8_len}; + int unicode = bstr_decode_utf8(s, NULL); + + if (unicode > 0) { + mp_input_put_key(input_ctx, unicode); } + walk_buf(utf8_len); + state = STATE_INITIAL; + continue; } } - found: - getch2_len -= len; - for (i = 0; i < getch2_len; i++) - getch2_buf[i] = getch2_buf[len+i]; - mp_input_put_key(input_ctx, code); } + return true; } -static volatile int getch2_active=0; -static volatile int getch2_enabled=0; +static volatile int getch2_active = 0; +static volatile int getch2_enabled = 0; static void do_activate_getch2(void) { if (getch2_active) return; + +#ifdef HAVE_TERMCAP + if (term_smkx) + tputs(term_smkx, 1, putchar); +#endif + #ifdef HAVE_TERMIOS struct termios tio_new; tcgetattr(0,&tio_new); + if (!tio_orig_set) { tio_orig = tio_new; tio_orig_set = 1; } + tio_new.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ tio_new.c_cc[VMIN] = 1; tio_new.c_cc[VTIME] = 0; tcsetattr(0,TCSANOW,&tio_new); #endif - getch2_active=1; + + getch2_active = 1; } static void do_deactivate_getch2(void) { if (!getch2_active) return; + +#ifdef HAVE_TERMCAP + if (term_rmkx) + tputs(term_rmkx, 1, putchar); +#endif + #ifdef HAVE_TERMIOS if (tio_orig_set) { // once set, it will never be set again @@ -318,7 +467,8 @@ static void do_deactivate_getch2(void) tcsetattr(0, TCSANOW, (const struct termios *) &tio_orig); } #endif - getch2_active=0; + + getch2_active = 0; } // sigaction wrapper @@ -327,10 +477,12 @@ static int setsigaction(int signo, void (*handler) (int), { struct sigaction sa; sa.sa_handler = handler; + if(do_mask) sigfillset(&sa.sa_mask); else sigemptyset(&sa.sa_mask); + sa.sa_flags = flags; return sigaction(signo, &sa, NULL); } @@ -378,7 +530,7 @@ void getch2_enable(void){ // handlers to fix terminal settings setsigaction(SIGCONT, continue_sighandler, 0, true); setsigaction(SIGTSTP, stop_sighandler, SA_RESETHAND, false); - setsigaction(SIGINT, quit_request_sighandler, SA_RESETHAND, false); + setsigaction(SIGINT, quit_request_sighandler, SA_RESETHAND, false); setsigaction(SIGTTIN, SIG_IGN, 0, true); do_activate_getch2(); @@ -393,7 +545,7 @@ void getch2_disable(void){ // restore signals setsigaction(SIGCONT, SIG_DFL, 0, false); setsigaction(SIGTSTP, SIG_DFL, 0, false); - setsigaction(SIGINT, SIG_DFL, 0, false); + setsigaction(SIGINT, SIG_DFL, 0, false); setsigaction(SIGTTIN, SIG_DFL, 0, false); do_deactivate_getch2(); -- cgit v1.2.3 From 19b1279bb3322699c3669197aa96deeaa262ee5a Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Thu, 25 Jul 2013 12:21:22 -0300 Subject: getch2: Remove unused function, fix possible crash If we still haven't read the full key from the input but it's regardless a unique match in the database, we could receive a NULL keycode from keys_search (it's not a full match after all) and proceed to use it. Don't disable the keycode matching code if we don't have termcap as we can still match against the hardcoded sequences. --- osdep/getch2.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/osdep/getch2.c b/osdep/getch2.c index e5752ae235..c19a410252 100644 --- a/osdep/getch2.c +++ b/osdep/getch2.c @@ -134,16 +134,6 @@ static keycode_st *keys_search(char *buf, int buflen) { return NULL; } -static keycode_st *keys_get_by_cap(char *cap) { - for (int i = 0; i < getch2_keys.len; i++) { - keycode_st *st = &getch2_keys.map[i]; - - if (strcmp(cap, st->cap) == 0) - return st; - } - return NULL; -} - /* pushes only if there is no duplicate. important as we only consider keys if the matches are unique. */ static keycode_st* keys_push_once(char *p, int code) { @@ -374,29 +364,33 @@ bool getch2(struct input_ctx *input_ctx) switch (state) { case STATE_INITIAL: { -#ifdef HAVE_TERMCAP int match_count = keys_count_matches(&getch2_buf[0], getch2_len); if (match_count == 1) { keycode_st *st = keys_search(&getch2_buf[0], getch2_len); - mp_input_put_key(input_ctx, st->code); - walk_buf(st->len); + if (st) { + mp_input_put_key(input_ctx, st->code); + walk_buf(st->len); + } /* else this is still a partial (but unique) match */ + + continue; } else if (match_count > 1) { continue; /* need more bytes to disambiguate */ } else { -#endif - utf8_len = bstr_parse_utf8_code_length(c); - - if (utf8_len > 1) { - state = STATE_UTF8; - } else { - if (utf8_len == 1) - mp_input_put_key(input_ctx, c); - walk_buf(getch2_pos); - } -#ifdef HAVE_TERMCAP + /* backtrack, send as UTF-8 */ + getch2_pos = 0; + c = getch2_buf[0]; } -#endif + utf8_len = bstr_parse_utf8_code_length(c); + + if (utf8_len > 1) { + state = STATE_UTF8; + } else if (utf8_len == 1) { + mp_input_put_key(input_ctx, c); + walk_buf(1); + } else + walk_buf(getch2_pos); + break; } case STATE_UTF8: { -- cgit v1.2.3 From 5586b0293122da39d1d0cb813c7e6eec5d0ffd94 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Thu, 25 Jul 2013 12:23:40 -0300 Subject: getch2, mplayer: Always call load_termcap getch2 now deals with the cases where we don't have termcap. Add a dummy load_termcap to getch2-win so we don't get linking errors on mingw. --- core/mplayer.c | 2 -- osdep/getch2-win.c | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/mplayer.c b/core/mplayer.c index 4d1dc64de5..f1f1e81195 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -4586,9 +4586,7 @@ static void osdep_preinit(int *p_argc, char ***p_argv) SetErrorMode(0x8003); #endif -#ifdef HAVE_TERMCAP load_termcap(NULL); // load key-codes -#endif mp_time_init(); } diff --git a/osdep/getch2-win.c b/osdep/getch2-win.c index 0750f95c78..558876ff62 100644 --- a/osdep/getch2-win.c +++ b/osdep/getch2-win.c @@ -64,6 +64,11 @@ void get_screen_size(void) } } +int load_termcap(char *termtype) +{ + return 0; +} + static HANDLE in; static int getch2_status = 0; -- cgit v1.2.3 From 1df1eb0b613d952bcb23c8e035bfc730fb71bd56 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Thu, 25 Jul 2013 12:24:09 -0300 Subject: configure: Fix bad variable assignment Bourne shell hates having spaces before or after the = sign. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 67df30c033..2e6dc67723 100755 --- a/configure +++ b/configure @@ -1426,7 +1426,7 @@ if test "$_terminfo" = yes ; then test $_ld_tmp && res_comment="using $_ld_tmp" if test "$_termcap" = auto ; then - _termcap = yes # terminfo provides termcap + _termcap=yes # terminfo provides termcap fi else def_terminfo='#undef HAVE_TERMINFO' -- cgit v1.2.3