keysym-utf: replace the Unicode characters for leftanglebracket and rightanglebracket
[platform/upstream/libxkbcommon.git] / src / keysym.c
index f80a1ed..6d06de0 100644 (file)
 #include "keysym.h"
 #include "ks_tables.h"
 
+static inline const char *
+get_name(const struct name_keysym *entry)
+{
+    return keysym_names + entry->offset;
+}
+
 static int
 compare_by_keysym(const void *a, const void *b)
 {
-    const struct name_keysym *key = a, *entry = b;
-    return key->keysym - (int32_t)entry->keysym;
+    const xkb_keysym_t *key = a;
+    const struct name_keysym *entry = b;
+    if (*key < entry->keysym)
+        return -1;
+    if (*key > entry->keysym)
+        return 1;
+    return 0;
 }
 
 static int
 compare_by_name(const void *a, const void *b)
 {
-    const struct name_keysym *key = a, *entry = b;
-    return strcasecmp(key->name, entry->name);
+    const char *key = a;
+    const struct name_keysym *entry = b;
+    return istrcmp(key, get_name(entry));
 }
 
 XKB_EXPORT int
 xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
 {
-    const struct name_keysym search = { .name = NULL, .keysym = ks };
     const struct name_keysym *entry;
 
     if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
@@ -78,16 +89,18 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
         return -1;
     }
 
-    entry = bsearch(&search, keysym_to_name,
+    entry = bsearch(&ks, keysym_to_name,
                     ARRAY_SIZE(keysym_to_name),
                     sizeof(*keysym_to_name),
                     compare_by_keysym);
     if (entry)
-        return snprintf(buffer, size, "%s", entry->name);
+        return snprintf(buffer, size, "%s", get_name(entry));
 
-    if (ks >= 0x01000100 && ks <= 0x0110ffff)
-        /* Unnamed Unicode codepoint. */
-        return snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
+    /* Unnamed Unicode codepoint. */
+    if (ks >= 0x01000100 && ks <= 0x0110ffff) {
+        const int width = (ks & 0xff0000UL) ? 8 : 4;
+        return snprintf(buffer, size, "U%0*lX", width, ks & 0xffffffUL);
+    }
 
     /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
     return snprintf(buffer, size, "0x%08x", ks);
@@ -96,7 +109,7 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
 /*
  * Find the correct keysym if one case-insensitive match is given.
  *
- * The name_to_keysym table is sorted by strcasecmp(). So bsearch() may return
+ * The name_to_keysym table is sorted by istrcmp(). So bsearch() 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
@@ -117,25 +130,25 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
     if (!entry)
         return NULL;
 
-    if (!icase && strcmp(entry->name, name) == 0)
+    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(iter->name, name) == 0)
+        if (!icase && strcmp(get_name(iter), name) == 0)
             return iter;
-        if (strcasecmp(iter->name, entry->name) != 0)
+        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(iter->name, name) == 0)
+    for (iter = entry + 1; iter < last; ++iter) {
+        if (!icase && strcmp(get_name(iter), name) == 0)
             return iter;
-        if (strcasecmp(iter->name, entry->name) != 0)
+        if (istrcmp(get_name(iter), get_name(entry)) != 0)
             break;
         if (icase && xkb_keysym_is_lower(iter->keysym))
             return iter;
@@ -149,16 +162,15 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
 XKB_EXPORT xkb_keysym_t
 xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
 {
-    const struct name_keysym search = { .name = s, .keysym = 0 };
     const struct name_keysym *entry;
     char *tmp;
     xkb_keysym_t val;
-    bool icase = !!(flags & XKB_KEYSYM_CASE_INSENSITIVE);
+    bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
 
     if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
         return XKB_KEY_NoSymbol;
 
-    entry = bsearch(&search, name_to_keysym,
+    entry = bsearch(s, name_to_keysym,
                     ARRAY_SIZE(name_to_keysym),
                     sizeof(*name_to_keysym),
                     compare_by_name);
@@ -211,6 +223,18 @@ xkb_keysym_is_keypad(xkb_keysym_t keysym)
     return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
 }
 
+
+bool
+xkb_keysym_is_modifier(xkb_keysym_t keysym)
+{
+    return
+        (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) ||
+        /* libX11 only goes upto XKB_KEY_ISO_Level5_Lock. */
+        (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Last_Group_Lock) ||
+        keysym == XKB_KEY_Mode_switch ||
+        keysym == XKB_KEY_Num_Lock;
+}
+
 static void
 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
 
@@ -240,6 +264,26 @@ xkb_keysym_is_upper(xkb_keysym_t ks)
     return (ks == upper ? true : false);
 }
 
+XKB_EXPORT xkb_keysym_t
+xkb_keysym_to_lower(xkb_keysym_t ks)
+{
+    xkb_keysym_t lower, upper;
+
+    XConvertCase(ks, &lower, &upper);
+
+    return lower;
+}
+
+XKB_EXPORT xkb_keysym_t
+xkb_keysym_to_upper(xkb_keysym_t ks)
+{
+    xkb_keysym_t lower, upper;
+
+    XConvertCase(ks, &lower, &upper);
+
+    return upper;
+}
+
 /*
  * The following is copied verbatim from libX11:src/KeyBind.c, commit
  * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes: