diff --git a/src/keybind.c b/src/keybind.c index c898e8c06..ef0d15f81 100644 --- a/src/keybind.c +++ b/src/keybind.c @@ -45,7 +45,7 @@ #include "keybind.h" -static const name_keymap_t command_names[] = { +static name_keymap_t command_names[] = { #ifdef USE_INTERNAL_EDIT { "EditNoCommand", CK_Ignore_Key }, { "EditIgnoreKey", CK_Ignore_Key }, @@ -401,6 +401,9 @@ static const name_keymap_t command_names[] = { { NULL, 0 } }; +static const size_t num_command_names = sizeof (command_names) / + sizeof (command_names[0]) - 1; + /*** global variables ****************************************************************************/ /* viewer/actions_cmd.c */ @@ -769,17 +772,39 @@ const global_keymap_t default_input_keymap[] = { { 0, 0, "" } }; +static int +name_keymap_comparator (const void *p1, const void *p2) +{ + const name_keymap_t *m1 = (const name_keymap_t *) p1; + const name_keymap_t *m2 = (const name_keymap_t *) p2; + + return str_casecmp (m1->name, m2->name); +} + +static void +sort_command_names (void) +{ + static gboolean has_been_sorted = FALSE; + + if (!has_been_sorted) { + qsort (command_names, num_command_names, + sizeof (command_names[0]), &name_keymap_comparator); + has_been_sorted = TRUE; + } +} int lookup_action (const char *keyname) { - int i; + const name_keymap_t key = { keyname, 0 }; + name_keymap_t *res; - for (i = 0; command_names [i].name; i++) - if (!str_casecmp (command_names [i].name, keyname)) - return command_names [i].val; + sort_command_names (); - return 0; + res = bsearch (&key, command_names, num_command_names, + sizeof (command_names[0]), name_keymap_comparator); + + return (res != NULL) ? res->val : 0; } static void diff --git a/src/tty/key.c b/src/tty/key.c index e42f17dfb..9d08c8b40 100644 --- a/src/tty/key.c +++ b/src/tty/key.c @@ -93,7 +93,7 @@ int use_8th_bit_as_meta = 0; * We use this to allow users to define alternate definitions for * certain keys that may be missing from the terminal database */ -key_code_name_t key_name_conv_tab[] = { +const key_code_name_t key_name_conv_tab[] = { /* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason to define f0 as well. Also, it makes Learn keys a bunch of problems :( */ { KEY_F (1), "f1", N_("Function key 1"), "F1" }, @@ -1231,22 +1231,61 @@ check_movement_keys (int key, int page_size, void *data, move_fn backfn, return MSG_HANDLED; } + +static const size_t key_name_conv_tab_size = sizeof (key_name_conv_tab) / + sizeof (key_name_conv_tab[0]) - 1; +static key_code_name_t key_name_conv_tab_sorted [sizeof (key_name_conv_tab) / + sizeof (key_name_conv_tab[0]) - 1]; + +static int +key_code_name_comparator (const void *p1, const void *p2) +{ + const key_code_name_t *n1 = (const key_code_name_t *) p1; + const key_code_name_t *n2 = (const key_code_name_t *) p2; + + return str_casecmp (n1->name, n2->name); +} + +static void +sort_key_name_conv_tab (void) +{ + static gboolean has_been_sorted = FALSE; + + if (!has_been_sorted) { + int i; + for (i = 0; key_name_conv_tab[i].code; i++) + key_name_conv_tab_sorted[i] = key_name_conv_tab[i]; + + qsort (key_name_conv_tab_sorted, key_name_conv_tab_size, + sizeof (key_name_conv_tab_sorted[0]), &key_code_name_comparator); + + has_been_sorted = TRUE; + } +} + static int lookup_keyname (const char *keyname, int *lc_index) { if (keyname[0] != '\0') { - int i; + const key_code_name_t key = { 0, keyname, NULL, NULL }; + key_code_name_t *res; if (keyname[1] == '\0') { *lc_index = -1; return (int) keyname[0]; } - for (i = 0; key_name_conv_tab[i].code; i++) - if (str_casecmp (key_name_conv_tab[i].name, keyname) == 0) { - *lc_index = i; - return key_name_conv_tab[i].code; - } + sort_key_name_conv_tab (); + + res = bsearch (&key, key_name_conv_tab_sorted, + key_name_conv_tab_size, + sizeof (key_name_conv_tab_sorted[0]), + key_code_name_comparator); + + if (res != NULL) { + *lc_index = (int) (res - key_name_conv_tab_sorted); + return res->code; + } } *lc_index = -1; diff --git a/src/tty/key.h b/src/tty/key.h index 812f342e4..84f911209 100644 --- a/src/tty/key.h +++ b/src/tty/key.h @@ -23,14 +23,14 @@ cb_ret_t check_movement_keys (int key, int page_size, void *data, move_fn backfn, move_fn forfn, move_fn topfn, move_fn bottomfn); int lookup_key (const char *keyname, char **label); -typedef const struct { +typedef struct { int code; const char *name; const char *longname; const char *shortcut; } key_code_name_t; -extern key_code_name_t key_name_conv_tab[]; +extern const key_code_name_t key_name_conv_tab[]; /* mouse support */ struct Gpm_Event;