keysym: inline find_sym function

It's easier when everything is in one place.

Signed-off-by: Ran Benita <ran@unusedvar.com>
master
Ran Benita 2021-03-28 15:21:47 +03:00
parent 2d87ab08f3
commit 3b506497bf
1 changed files with 46 additions and 56 deletions

View File

@ -91,59 +91,6 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
return snprintf(buffer, size, "0x%08x", ks);
}
/*
* Find the correct keysym if one case-insensitive match is given.
*
* The name_to_keysym table is sorted by istrcmp(). So the binary search may return
* _any_ of all possible case-insensitive duplicates. This function searches the
* returned entry @entry, all previous and all next entries that match by
* case-insensitive comparison and returns the exact match to @name. If @icase
* is true, then this returns the best case-insensitive match instead of a
* correct match.
* The "best" case-insensitive match is the lower-case keysym which we find with
* the help of xkb_keysym_is_lower().
* The only keysyms that only differ by letter-case are keysyms that are
* available as lower-case and upper-case variant (like KEY_a and KEY_A). So
* returning the first lower-case match is enough in this case.
*/
static const struct name_keysym *
find_sym(const struct name_keysym *entry, const char *name, bool icase)
{
const struct name_keysym *iter, *last;
size_t len = ARRAY_SIZE(name_to_keysym);
if (!entry)
return NULL;
if (!icase && strcmp(get_name(entry), name) == 0)
return entry;
if (icase && xkb_keysym_is_lower(entry->keysym))
return entry;
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
}
last = name_to_keysym + len;
for (iter = entry + 1; iter < last; ++iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
}
if (icase)
return entry;
return NULL;
}
XKB_EXPORT xkb_keysym_t
xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
{
@ -168,9 +115,52 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
break;
}
}
entry = find_sym(entry, name, icase);
if (entry)
return entry->keysym;
if (entry) {
/*
* Find the correct keysym if one case-insensitive match is given.
*
* The name_to_keysym table is sorted by istrcmp(). So the binary search
* may return _any_ of all possible case-insensitive duplicates. This
* code searches the entry, all previous and all next entries that match
* by case-insensitive comparison and returns the exact match to name.
* If icase is true, then this returns the best case-insensitive match
* instead of a correct match.
* The "best" case-insensitive match is the lower-case keysym which we
* find with the help of xkb_keysym_is_lower().
* The only keysyms that only differ by letter-case are keysyms that are
* available as lower-case and upper-case variant (like KEY_a and
* KEY_A). So returning the first lower-case match is enough in this
* case.
*/
const struct name_keysym *iter, *last;
if (!icase && strcmp(get_name(entry), name) == 0)
return entry->keysym;
if (icase && xkb_keysym_is_lower(entry->keysym))
return entry->keysym;
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter->keysym;
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter->keysym;
}
last = name_to_keysym + ARRAY_SIZE(name_to_keysym);
for (iter = entry + 1; iter < last; ++iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter->keysym;
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter->keysym;
}
if (icase)
return entry->keysym;
}
if (*name == 'U' || (icase && *name == 'u')) {
val = strtoul(&name[1], &tmp, 16);