From 3633af5e418876932ab086b910ca5a43df425cbe Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 26 Nov 2017 18:54:59 -0800 Subject: [PATCH] GUACAMOLE-313: Use binary search to find human-readable names for known keys. --- src/guaclog/key-name.c | 99 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/src/guaclog/key-name.c b/src/guaclog/key-name.c index ffb622d1..f3485a22 100644 --- a/src/guaclog/key-name.c +++ b/src/guaclog/key-name.c @@ -22,12 +22,107 @@ #include "log.h" #include +#include + +/** + * A mapping of X11 keysym to its corresponding human-readable name. + */ +typedef struct guaclog_known_key { + + /** + * The X11 keysym of the key. + */ + const int keysym; + + /** + * A human-readable name for the key. + */ + const char* name; + +} guaclog_known_key; + +/** + * All known keys. + */ +const guaclog_known_key known_keys[] = { + { 0xFFE1, "Shift" } +}; + +/** + * Comparator for the standard bsearch() function which compares an integer + * keysym against the keysym associated with a guaclog_known_key. + * + * @param key + * The key value being compared against the member. This MUST be the + * keysym value, passed through typecasting to an intptr_t (NOT a pointer + * to the int itself). + * + * @param member + * The member within the known_keys array being compared against the given + * key. + * + * @return + * Zero if the given keysym is equal to that of the given member, a + * positive value if the given keysym is greater than that of the given + * member, or a negative value if the given keysym is less than that of the + * given member. + */ +static int guaclog_known_key_bsearch_compare(const void* key, + const void* member) { + + int keysym = (int) ((intptr_t) key); + guaclog_known_key* current = (guaclog_known_key*) member; + + /* Compare given keysym to keysym of current member */ + return keysym - current->keysym; + +} + +/** + * Searches through the known_keys array of known keys for the name of the key + * having the given keysym. If found, the name of the keysym is copied into the + * given buffer, which must be at least GUACLOG_MAX_KEY_NAME_LENGTH bytes long. + * + * @param key_name + * The buffer to copy the key name into, which must be at least + * GUACLOG_MAX_KEY_NAME_LENGTH. + * + * @param keysym + * The X11 keysym of the key whose name should be stored in + * key_name. + * + * @return + * The length of the name, in bytes, excluding null terminator, or zero if + * the key could not be found. + */ +static int guaclog_locate_key_name(char* key_name, int keysym) { + + /* Search through known keys for given keysym */ + guaclog_known_key* found = bsearch((void*) ((intptr_t) keysym), + known_keys, sizeof(known_keys) / sizeof(known_keys[0]), + sizeof(known_keys[0]), guaclog_known_key_bsearch_compare); + + /* If found, format name and return length of result */ + if (found != NULL) + return snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH, + "[ %s ]", found->name); + + /* Key not found */ + return 0; + +} int guaclog_key_name(char* key_name, int keysym) { + int name_length; + + /* Search for name within list of known keys */ + name_length = guaclog_locate_key_name(key_name, keysym); + /* Fallback to using hex keysym as name */ - int name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH, - "0x%X", keysym); + if (name_length == 0) + name_length = snprintf(key_name, GUACLOG_MAX_KEY_NAME_LENGTH, + "0x%X", keysym); /* Truncate name if necessary */ if (name_length >= GUACLOG_MAX_KEY_NAME_LENGTH) {