keysym-utf: also translate special keysyms like Tab and Return
authorRan Benita <ran234@gmail.com>
Mon, 5 Nov 2012 19:34:59 +0000 (21:34 +0200)
committerRan Benita <ran234@gmail.com>
Mon, 5 Nov 2012 19:34:59 +0000 (21:34 +0200)
The keysym2ucs.c file apparently leaves out some keysyms, which libX11
deals with separately (like in _XkbHandleSpecialSym()).
The problematic keysyms are the keypad ones (for which we already added
some support) and keysyms which use 0xff** instead of 0x00** < 0x20.
This code should fix them properly, as much as I could gather from
libX11 and http://www.cl.cam.ac.uk/~mgk25/ucs/keysym2ucs.c and other
sources (which are not aware of locale).

https://bugs.freedesktop.org/show_bug.cgi?id=56780

Reported-by: Gatis Paeglis <gatis.paeglis@digia.com>
Signed-off-by: Ran Benita <ran234@gmail.com>
src/keysym-utf.c
test/keysym.c

index 67dbb22..ae01f09 100644 (file)
@@ -834,20 +834,6 @@ const struct codepair keysymtab[] = {
     { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
 };
 
-const struct codepair keysymtab_kp[] = {
-    { 0xff80, 0x0020 }, /*                    KP_Space   SPACE */
-    { 0xffaa, 0x002a }, /*                 KP_Multiply * ASTERISK */
-    { 0xffab, 0x002b }, /*                     KP_Plus + PLUS SIGN */
-    /* XXX: It's debatable what KP_Separator and KP_Decimal should represent,
-     *      as well as locale-specific.  So just enforce English colonial
-     *      hegemony on the world for the time being. */
-    { 0xffac, 0x002e }, /*                KP_Separator . FULL STOP */
-    { 0xffad, 0x002d }, /*                 KP_Subtract - HYPHEN-MINUS */
-    { 0xffae, 0x002e }, /*                  KP_Decimal . FULL STOP */
-    { 0xffaf, 0x002f }, /*                   KP_Divide / SOLIDUS */
-    { 0xffbd, 0x003d }, /*                    KP_Equal = EQUAL SIGN */
-};
-
 /* binary search with range check */
 static uint32_t
 bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym)
@@ -877,28 +863,29 @@ bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym)
 XKB_EXPORT uint32_t
 xkb_keysym_to_utf32(xkb_keysym_t keysym)
 {
-    uint32_t retval = 0;
-
     /* first check for Latin-1 characters (1:1 mapping) */
     if ((keysym >= 0x0020 && keysym <= 0x007e) ||
         (keysym >= 0x00a0 && keysym <= 0x00ff))
         return keysym;
 
-    if (keysym >= 0xffb0 && keysym <= 0xffb9)
-        return keysym - (0xffb0 - 0x0030);
+    /* patch encoding botch */
+    if (keysym == XKB_KEY_KP_Space)
+        return XKB_KEY_space & 0x7f;
+
+    /* special keysyms */
+    if ((keysym >= XKB_KEY_BackSpace && keysym <= XKB_KEY_Clear) ||
+        (keysym >= XKB_KEY_KP_Multiply && keysym <= XKB_KEY_KP_9) ||
+        keysym == XKB_KEY_Return || keysym == XKB_KEY_Escape ||
+        keysym == XKB_KEY_Delete || keysym == XKB_KEY_KP_Tab ||
+        keysym == XKB_KEY_KP_Enter || keysym == XKB_KEY_KP_Equal)
+        return keysym & 0x7f;
 
     /* also check for directly encoded 24-bit UCS characters */
     if ((keysym & 0xff000000) == 0x01000000)
         return keysym & 0x00ffffff;
 
-    /* search smaller keypad table */
-    retval = bin_search(keysymtab_kp, ARRAY_SIZE(keysymtab_kp) - 1, keysym);
-
     /* search main table */
-    if (!retval)
-        retval = bin_search(keysymtab, ARRAY_SIZE(keysymtab) - 1, keysym);
-
-    return retval;
+    return bin_search(keysymtab, ARRAY_SIZE(keysymtab) - 1, keysym);
 }
 
 /*
index 595f829..fe6138d 100644 (file)
@@ -73,8 +73,10 @@ test_utf8(xkb_keysym_t keysym, const char *expected)
     if (ret <= 0)
         return ret;
 
-    fprintf(stderr, "Expected keysym %#x -> %s\n", keysym, expected);
-    fprintf(stderr, "Received keysym %#x -> %s\n\n", keysym, s);
+    fprintf(stderr, "Expected keysym %#x -> %s (%u bytes)\n", keysym, expected,
+            (unsigned) strlen(expected));
+    fprintf(stderr, "Received keysym %#x -> %s (%u bytes)\n\n", keysym, s,
+            (unsigned) strlen(s));
 
     return streq(s, expected);
 }
@@ -133,6 +135,17 @@ main(void)
 
     assert(test_utf8(XKB_KEY_space, " "));
     assert(test_utf8(XKB_KEY_KP_Space, " "));
+    assert(test_utf8(XKB_KEY_BackSpace, "\b"));
+    assert(test_utf8(XKB_KEY_Escape, "\e"));
+    assert(test_utf8(XKB_KEY_KP_Separator, ","));
+    assert(test_utf8(XKB_KEY_KP_Decimal, "."));
+    assert(test_utf8(XKB_KEY_Tab, "\t"));
+    assert(test_utf8(XKB_KEY_KP_Tab, "\t"));
+    assert(test_utf8(XKB_KEY_hyphen, "­"));
+    assert(test_utf8(XKB_KEY_Linefeed, "\n"));
+    assert(test_utf8(XKB_KEY_Return, "\r"));
+    assert(test_utf8(XKB_KEY_KP_Enter, "\r"));
+    assert(test_utf8(XKB_KEY_KP_Equal, "="));
     assert(test_utf8(XKB_KEY_9, "9"));
     assert(test_utf8(XKB_KEY_KP_9, "9"));
     assert(test_utf8(XKB_KEY_KP_Multiply, "*"));