Edit

kc3-lang/libxkbcommon/src/keysym.c

Branch :

  • Show log

    Commit

  • Author : Ran Benita
    Date : 2012-09-16 14:45:32
    Hash : b2110705
    Message : Organize src/ and test/ headers - Add context.h and move context-related functions from xkb-priv.h to it. - Move xkb_context definition back to context.c. - Add keysym.h and move keysym upper/lower/keypad from xkb-priv.h to it. - Rename xkb-priv.h to map.h since it only contains keymap-related definitions and declarations now. - Remove unnecessary includes and some and some other small cleanups. Signed-off-by: Ran Benita <ran234@gmail.com>

  • src/keysym.c
  • /*
     * Copyright 1985, 1987, 1990, 1998  The Open Group
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the names of the authors or their
     * institutions shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization from the authors.
     */
    
    /*
     * Copyright © 2009 Dan Nicholson
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     * DEALINGS IN THE SOFTWARE.
     */
    
    #include "xkbcommon/xkbcommon.h"
    #include "utils.h"
    #include "ks_tables.h"
    #include "keysym.h"
    
    XKB_EXPORT void
    xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
    {
        int i, n, h, idx;
        const unsigned char *entry;
        unsigned char val1, val2, val3, val4;
    
        if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
            snprintf(buffer, size, "Invalid");
            return;
        }
    
        /* Try to find it in our hash table. */
        if (ks <= 0x1fffffff) {
            val1 = ks >> 24;
            val2 = (ks >> 16) & 0xff;
            val3 = (ks >> 8) & 0xff;
            val4 = ks & 0xff;
            i = ks % VTABLESIZE;
            h = i + 1;
            n = VMAXHASH;
    
            while ((idx = hashKeysym[i])) {
                entry = &_XkeyTable[idx];
    
                if ((entry[0] == val1) && (entry[1] == val2) &&
                    (entry[2] == val3) && (entry[3] == val4)) {
                    snprintf(buffer, size, "%s", entry + 4);
                    return;
                }
    
                if (!--n)
                    break;
    
                i += h;
                if (i >= VTABLESIZE)
                    i -= VTABLESIZE;
            }
        }
    
        if (ks >= 0x01000100 && ks <= 0x0110ffff)
            /* Unnamed Unicode codepoint. */
            snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
        else
            /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
            snprintf(buffer, size, "0x%08x", ks);
    }
    
    XKB_EXPORT xkb_keysym_t
    xkb_keysym_from_name(const char *s)
    {
        int i, n, h, c, idx;
        uint32_t sig = 0;
        const char *p = s;
        char *tmp;
        const unsigned char *entry;
        unsigned char sig1, sig2;
        xkb_keysym_t val;
    
        while ((c = *p++))
            sig = (sig << 1) + c;
    
        i = sig % KTABLESIZE;
        h = i + 1;
        sig1 = (sig >> 8) & 0xff;
        sig2 = sig & 0xff;
        n = KMAXHASH;
    
        while ((idx = hashString[i])) {
            entry = &_XkeyTable[idx];
    
            if ((entry[0] == sig1) && (entry[1] == sig2) &&
                streq(s, (const char *) entry + 6)) {
                val = (entry[2] << 24) | (entry[3] << 16) |
                      (entry[4] << 8) | entry[5];
                if (!val)
                    val = XKB_KEY_VoidSymbol;
                return val;
            }
    
            if (!--n)
                break;
    
            i += h;
            if (i >= KTABLESIZE)
                i -= KTABLESIZE;
        }
    
        if (*s == 'U') {
            val = strtoul(&s[1], &tmp, 16);
            if (tmp && *tmp != '\0')
                return XKB_KEY_NoSymbol;
    
            if (val < 0x20 || (val > 0x7e && val < 0xa0))
                return XKB_KEY_NoSymbol;
            if (val < 0x100)
                return val;
            if (val > 0x10ffff)
                return XKB_KEY_NoSymbol;
            return val | 0x01000000;
        }
        else if (s[0] == '0' && s[1] == 'x') {
            val = strtoul(&s[2], &tmp, 16);
            if (tmp && *tmp != '\0')
                return XKB_KEY_NoSymbol;
    
            return val;
        }
    
        /* Stupid inconsistency between the headers and XKeysymDB: the former has
         * no separating underscore, while some XF86* syms in the latter did.
         * As a last ditch effort, try without. */
        if (strncmp(s, "XF86_", 5) == 0) {
            xkb_keysym_t ret;
            tmp = strdup(s);
            if (!tmp)
                return XKB_KEY_NoSymbol;
            memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
            ret = xkb_keysym_from_name(tmp);
            free(tmp);
            return ret;
        }
    
        return XKB_KEY_NoSymbol;
    }
    
    enum keysym_case {
        NONE,
        LOWERCASE,
        UPPERCASE,
    };
    
    static enum keysym_case
    keysym_get_case(xkb_keysym_t ks)
    {
        unsigned set = (ks & (~0xff)) >> 8;
    
        switch (set) {
        case 0: /* latin 1 */
            if ((ks >= XKB_KEY_A && ks <= XKB_KEY_Z) ||
                (ks >= XKB_KEY_Agrave && ks <= XKB_KEY_THORN && ks !=
                 XKB_KEY_multiply))
                return UPPERCASE;
            if ((ks >= XKB_KEY_a && ks <= XKB_KEY_z) ||
                (ks >= XKB_KEY_agrave && ks <= XKB_KEY_ydiaeresis))
                return LOWERCASE;
            break;
    
        case 1: /* latin 2 */
            if ((ks >= XKB_KEY_Aogonek && ks <= XKB_KEY_Zabovedot && ks !=
                 XKB_KEY_breve) ||
                (ks >= XKB_KEY_Racute && ks <= XKB_KEY_Tcedilla))
                return UPPERCASE;
            if ((ks >= XKB_KEY_aogonek && ks <= XKB_KEY_zabovedot && ks !=
                 XKB_KEY_caron) ||
                (ks >= XKB_KEY_racute && ks <= XKB_KEY_tcedilla))
                return LOWERCASE;
            break;
    
        case 2: /* latin 3 */
            if ((ks >= XKB_KEY_Hstroke && ks <= XKB_KEY_Jcircumflex) ||
                (ks >= XKB_KEY_Cabovedot && ks <= XKB_KEY_Scircumflex))
                return UPPERCASE;
            if ((ks >= XKB_KEY_hstroke && ks <= XKB_KEY_jcircumflex) ||
                (ks >= XKB_KEY_cabovedot && ks <= XKB_KEY_scircumflex))
                return LOWERCASE;
            break;
    
        case 3: /* latin 4 */
            if ((ks >= XKB_KEY_Rcedilla && ks <= XKB_KEY_Tslash) ||
                (ks == XKB_KEY_ENG) ||
                (ks >= XKB_KEY_Amacron && ks <= XKB_KEY_Umacron))
                return UPPERCASE;
            if ((ks >= XKB_KEY_rcedilla && ks <= XKB_KEY_tslash) ||
                (ks == XKB_KEY_eng) ||
                (ks >= XKB_KEY_amacron && ks <= XKB_KEY_umacron))
                return LOWERCASE;
            break;
    
        case 6: /* Cyrillic */
            if ((ks >= XKB_KEY_Serbian_DJE && ks <= XKB_KEY_Serbian_DZE) ||
                (ks >= XKB_KEY_Cyrillic_YU && ks <= XKB_KEY_Cyrillic_HARDSIGN))
                return UPPERCASE;
            if ((ks >= XKB_KEY_Serbian_dje && ks <= XKB_KEY_Serbian_dze) ||
                (ks >= XKB_KEY_Cyrillic_yu && ks <= XKB_KEY_Cyrillic_hardsign))
                return LOWERCASE;
            break;
    
        case 7: /* Greek */
            if ((ks >= XKB_KEY_Greek_ALPHAaccent &&
                 ks <= XKB_KEY_Greek_OMEGAaccent) ||
                (ks >= XKB_KEY_Greek_ALPHA && ks <= XKB_KEY_Greek_OMEGA))
                return UPPERCASE;
            if ((ks >= XKB_KEY_Greek_alphaaccent &&
                 ks <= XKB_KEY_Greek_omegaaccent) ||
                (ks >= XKB_KEY_Greek_alpha && ks <= XKB_KEY_Greek_OMEGA))
                return LOWERCASE;
            break;
    
        case 18: /* latin 8 */
            if ((ks == XKB_KEY_Wcircumflex) ||
                (ks == XKB_KEY_Ycircumflex) ||
                (ks == XKB_KEY_Babovedot) ||
                (ks == XKB_KEY_Dabovedot) ||
                (ks == XKB_KEY_Fabovedot) ||
                (ks == XKB_KEY_Mabovedot) ||
                (ks == XKB_KEY_Pabovedot) ||
                (ks == XKB_KEY_Sabovedot) ||
                (ks == XKB_KEY_Tabovedot) ||
                (ks == XKB_KEY_Wdiaeresis) ||
                (ks == XKB_KEY_Ygrave))
                return UPPERCASE;
            if ((ks == XKB_KEY_wcircumflex) ||
                (ks == XKB_KEY_ycircumflex) ||
                (ks == XKB_KEY_babovedot) ||
                (ks == XKB_KEY_dabovedot) ||
                (ks == XKB_KEY_fabovedot) ||
                (ks == XKB_KEY_mabovedot) ||
                (ks == XKB_KEY_pabovedot) ||
                (ks == XKB_KEY_sabovedot) ||
                (ks == XKB_KEY_tabovedot) ||
                (ks == XKB_KEY_wdiaeresis) ||
                (ks == XKB_KEY_ygrave))
                return LOWERCASE;
            break;
    
        case 19: /* latin 9 */
            if (ks == XKB_KEY_OE || ks == XKB_KEY_Ydiaeresis)
                return UPPERCASE;
            if (ks == XKB_KEY_oe)
                return LOWERCASE;
            break;
        }
    
        return NONE;
    }
    
    bool
    xkb_keysym_is_lower(xkb_keysym_t keysym)
    {
        return keysym_get_case(keysym) == LOWERCASE;
    }
    
    bool
    xkb_keysym_is_upper(xkb_keysym_t keysym)
    {
        return keysym_get_case(keysym) == UPPERCASE;
    }
    
    bool
    xkb_keysym_is_keypad(xkb_keysym_t keysym)
    {
        return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
    }