From 2f9532d28c1526c0dd96cb8544a4f9ea836c77e4 Mon Sep 17 00:00:00 2001 From: Boris Faure Date: Sat, 23 Aug 2014 17:01:20 +0200 Subject: [PATCH] store keybindings in a hash map --- src/bin/keyin.c | 140 ++++++++++++++++++++++++++++++++++++++++++++--- src/bin/keyin.h | 24 +++++++- src/bin/main.c | 8 +++ src/bin/termio.c | 4 +- 4 files changed, 165 insertions(+), 11 deletions(-) diff --git a/src/bin/keyin.c b/src/bin/keyin.c index 230c6e17..aa823b91 100644 --- a/src/bin/keyin.c +++ b/src/bin/keyin.c @@ -18,6 +18,8 @@ struct _Keyout int outlen; }; +static Eina_Hash *_key_bindings = NULL; + #define KEY(in, out) {in, out, sizeof(in) - 1, sizeof(out) - 1} @@ -622,19 +624,43 @@ _handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev, } } +static Key_Binding * +key_binding_lookup(const Evas_Event_Key_Down *ev, + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift) +{ + Key_Binding *kb; + size_t len = strlen(ev->keyname); + + if (len > UINT16_MAX) return NULL; + + kb = alloca(sizeof(Key_Binding) + len + 1); + if (!kb) return NULL; + kb->ctrl = ctrl; + kb->alt = alt; + kb->shift = shift; + kb->len = len; + strncpy(kb->keyname, ev->keyname, kb->len + 1); + + return eina_hash_find(_key_bindings, kb); +} + Eina_Bool keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, - int alt, int shift, int ctrl) + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift) { + Key_Binding *kb; + + kb = key_binding_lookup(ev, ctrl, alt, shift); + if (kb) + { + if (kb->cb(ty->obj)) + goto end; + } + + if ((!alt) && (ctrl) && (!shift)) { - if (!strcmp(ev->key, "Prior")) - { - keyin_compose_seq_reset(khdl); - evas_object_smart_callback_call(ty->obj, "prev", NULL); - return EINA_TRUE; - } - else if (!strcmp(ev->key, "Next")) + if (!strcmp(ev->key, "Next")) { keyin_compose_seq_reset(khdl); evas_object_smart_callback_call(ty->obj, "next", NULL); @@ -877,3 +903,101 @@ keyin_handle_up(Keys_Handler *khdl, Evas_Event_Key_Up *ev) return; } } + +static Eina_Bool +cb_term_prev(Evas_Object *term) +{ + evas_object_smart_callback_call(term, "prev", NULL); + return EINA_TRUE; +} + +static unsigned int +key_binding_key_length(EINA_UNUSED const void *key) +{ + return 0; +} + +static int +key_binding_key_cmp(const void *key1, int key1_length, + const void *key2, int key2_length) +{ + const Key_Binding *kb1 = key1, + *kb2 = key2; + + if (key1_length < key2_length) + return -1; + else if (key1_length > key2_length) + return 1; + else + { + unsigned int m1 = (kb1->ctrl << 2) | (kb1->alt << 1) | kb1->shift, + m2 = (kb2->ctrl << 2) | (kb2->alt << 1) | kb2->shift; + if (m1 < m2) + return -1; + else if (m1 > m2) + return 1; + else + return strncmp(kb1->keyname, kb2->keyname, kb1->len); + } +} + +static int +key_binding_key_hash(const void *key, int key_length) +{ + const Key_Binding *kb = key; + int hash; + + hash = eina_hash_djb2(key, key_length); + hash &= 0x1fffffff; + hash |= (kb->ctrl << 31) | (kb->alt << 30) | (kb->shift << 29); + return hash; +} + + +Key_Binding * +key_binding_new(const char *keyname, + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, + Key_Binding_Cb cb) +{ + Key_Binding *kb; + size_t len = strlen(keyname); + + if (len > UINT16_MAX) return NULL; + + kb = malloc(sizeof(Key_Binding) + len + 1); + if (!kb) return NULL; + kb->ctrl = ctrl; + kb->alt = alt; + kb->shift = shift; + kb->len = len; + strncpy(kb->keyname, keyname, kb->len + 1); + kb->cb = cb; + + return kb; +} + +int key_bindings_init(void) +{ + Key_Binding *kb; + + _key_bindings = eina_hash_new(key_binding_key_length, + key_binding_key_cmp, + key_binding_key_hash, + free, + 5); + if (!_key_bindings) return -1; + + kb = key_binding_new("Prior", 1, 0, 0, cb_term_prev); + if (!kb) return -1; + if (!eina_hash_direct_add(_key_bindings, kb, kb)) return -1; + + + return 0; +} + +void key_bindings_shutdown(void) +{ + if (_key_bindings) + eina_hash_free(_key_bindings); + _key_bindings = NULL; +} diff --git a/src/bin/keyin.h b/src/bin/keyin.h index a959bbbb..8cb4aa3d 100644 --- a/src/bin/keyin.h +++ b/src/bin/keyin.h @@ -14,9 +14,31 @@ struct _Keys_Handler void keyin_compose_seq_reset(Keys_Handler *khdl); Eina_Bool key_is_modifier(const char *key); Eina_Bool keyin_handle(Keys_Handler *khdl, Termpty *ty, const Evas_Event_Key_Down *ev, - int alt, int shift, int ctrl); + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift); void keyin_handle_up(Keys_Handler *khdl, Evas_Event_Key_Up *ev); +typedef struct _Key_Binding Key_Binding; + +typedef Eina_Bool (*Key_Binding_Cb)(Evas_Object *term); +struct _Key_Binding +{ + uint16_t ctrl : 1; + uint16_t alt : 1; + uint16_t shift : 1; + + uint16_t len; + + Key_Binding_Cb cb; + char keyname[]; +}; + +Key_Binding * +key_binding_new(const char *keyname, + Eina_Bool ctrl, Eina_Bool alt, Eina_Bool shift, + Key_Binding_Cb cb); +int key_bindings_init(void); +void key_bindings_shutdown(void); + #endif diff --git a/src/bin/main.c b/src/bin/main.c index 708c3200..3e250d2d 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -19,6 +19,7 @@ #include "dbus.h" #include "app_server.h" #include "miniview.h" +#include "keyin.h" #if (ELM_VERSION_MAJOR == 1) && (ELM_VERSION_MINOR < 8) #define PANES_TOP "left" @@ -2977,6 +2978,12 @@ elm_main(int argc, char **argv) elm_app_info_set(elm_main, "terminology", "themes/default.edj"); config_init(); + if (key_bindings_init() < 0) + { + ERR(_("Could not Initialize key bindings.")); + retval = EXIT_FAILURE; + goto end; + } main_config = config_load("config"); @@ -3373,6 +3380,7 @@ remote: config_del(main_config); + key_bindings_shutdown(); config_shutdown(); eina_log_domain_unregister(_log_domain); _log_domain = -1; diff --git a/src/bin/termio.c b/src/bin/termio.c index 42f7e4ee..f83ca7a8 100644 --- a/src/bin/termio.c +++ b/src/bin/termio.c @@ -1850,9 +1850,9 @@ _smart_cb_key_down(void *data, Evas *e EINA_UNUSED, { const Evas_Event_Key_Down *ev = event; Termio *sd = evas_object_smart_data_get(data); + int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); int alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); int shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); - int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); EINA_SAFETY_ON_NULL_RETURN(sd); EINA_SAFETY_ON_NULL_RETURN(ev->key); @@ -1861,7 +1861,7 @@ _smart_cb_key_down(void *data, Evas *e EINA_UNUSED, return; - if (keyin_handle(&sd->khdl, sd->pty, ev, alt, shift, ctrl)) + if (keyin_handle(&sd->khdl, sd->pty, ev, ctrl, alt, shift)) goto end; if (sd->jump_on_keypress)