Edit

kc3-lang/libxkbcommon/src/text.c

Branch :

  • Show log

    Commit

  • Author : Ran Benita
    Date : 2012-09-21 14:58:31
    Hash : bbaa11c6
    Message : Rename map.{c,h} to keymap.{c,h} Seeing as we don't like "map" anymore. Signed-off-by: Ran Benita <ran234@gmail.com>

  • src/text.c
  • /************************************************************
     * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
     *
     * Permission to use, copy, modify, and distribute this
     * software and its documentation for any purpose and without
     * fee is hereby granted, provided that the above copyright
     * notice appear in all copies and that both that copyright
     * notice and this permission notice appear in supporting
     * documentation, and that the name of Silicon Graphics not be
     * used in advertising or publicity pertaining to distribution
     * of the software without specific prior written permission.
     * Silicon Graphics makes no representation about the suitability
     * of this software for any purpose. It is provided "as is"
     * without any express or implied warranty.
     *
     * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
     * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
     * THE USE OR PERFORMANCE OF THIS SOFTWARE.
     *
     ********************************************************/
    
    #include "keymap.h"
    #include "text.h"
    
    bool
    LookupString(const LookupEntry tab[], const char *string,
                  unsigned int *value_rtrn)
    {
        const LookupEntry *entry;
    
        if (!string)
            return false;
    
        for (entry = tab; entry->name; entry++) {
            if (istreq(entry->name, string)) {
                *value_rtrn = entry->value;
                return true;
            }
        }
    
        return false;
    }
    
    const char *
    LookupValue(const LookupEntry tab[], unsigned int value)
    {
        const LookupEntry *entry;
    
        for (entry = tab; entry->name; entry++)
            if (entry->value == value)
                return entry->name;
    
        return NULL;
    }
    
    const LookupEntry ctrlMaskNames[] = {
        { "RepeatKeys", CONTROL_REPEAT },
        { "Repeat", CONTROL_REPEAT },
        { "AutoRepeat", CONTROL_REPEAT },
        { "SlowKeys", CONTROL_SLOW },
        { "BounceKeys", CONTROL_DEBOUNCE },
        { "StickyKeys", CONTROL_STICKY },
        { "MouseKeys", CONTROL_MOUSEKEYS },
        { "MouseKeysAccel", CONTROL_MOUSEKEYS_ACCEL },
        { "AccessXKeys", CONTROL_AX },
        { "AccessXTimeout", CONTROL_AX_TIMEOUT },
        { "AccessXFeedback", CONTROL_AX_FEEDBACK },
        { "AudibleBell", CONTROL_BELL },
        { "IgnoreGroupLock", CONTROL_IGNORE_GROUP_LOCK },
        { "all", CONTROL_ALL },
        { "none", 0 },
        { "Overlay1", 0 },
        { "Overlay2", 0 },
        { NULL, 0 }
    };
    
    const LookupEntry modComponentMaskNames[] = {
        {"base", XKB_STATE_DEPRESSED},
        {"latched", XKB_STATE_LATCHED},
        {"locked", XKB_STATE_LOCKED},
        {"effective", XKB_STATE_EFFECTIVE},
        {"compat", XKB_STATE_EFFECTIVE},
        {"any", XKB_STATE_EFFECTIVE},
        {"none", 0},
        {NULL, 0}
    };
    
    const LookupEntry groupComponentMaskNames[] = {
        {"base", XKB_STATE_DEPRESSED},
        {"latched", XKB_STATE_LATCHED},
        {"locked", XKB_STATE_LOCKED},
        {"effective", XKB_STATE_EFFECTIVE},
        {"any", XKB_STATE_EFFECTIVE},
        {"none", 0},
        {NULL, 0}
    };
    
    const LookupEntry groupMaskNames[] = {
        {"group1", 0x01},
        {"group2", 0x02},
        {"group3", 0x04},
        {"group4", 0x08},
        {"group5", 0x10},
        {"group6", 0x20},
        {"group7", 0x40},
        {"group8", 0x80},
        {"none", 0x00},
        {"all", 0xff},
        {NULL, 0}
    };
    
    const LookupEntry groupNames[] = {
        {"group1", 1},
        {"group2", 2},
        {"group3", 3},
        {"group4", 4},
        {"group5", 5},
        {"group6", 6},
        {"group7", 7},
        {"group8", 8},
        {NULL, 0}
    };
    
    const LookupEntry levelNames[] = {
        { "level1", 1 },
        { "level2", 2 },
        { "level3", 3 },
        { "level4", 4 },
        { "level5", 5 },
        { "level6", 6 },
        { "level7", 7 },
        { "level8", 8 },
        { NULL, 0 }
    };
    
    const LookupEntry buttonNames[] = {
        { "button1", 1 },
        { "button2", 2 },
        { "button3", 3 },
        { "button4", 4 },
        { "button5", 5 },
        { "default", 0 },
        { NULL, 0 }
    };
    
    const LookupEntry useModMapValueNames[] = {
        { "levelone", 1 },
        { "level1", 1 },
        { "anylevel", 0 },
        { "any", 0 },
        { NULL, 0 }
    };
    
    const LookupEntry actionTypeNames[] = {
        { "NoAction", ACTION_TYPE_NONE },
        { "SetMods", ACTION_TYPE_MOD_SET },
        { "LatchMods", ACTION_TYPE_MOD_LATCH },
        { "LockMods", ACTION_TYPE_MOD_LOCK },
        { "SetGroup", ACTION_TYPE_GROUP_SET },
        { "LatchGroup", ACTION_TYPE_GROUP_LATCH },
        { "LockGroup", ACTION_TYPE_GROUP_LOCK },
        { "MovePtr", ACTION_TYPE_PTR_MOVE },
        { "MovePointer", ACTION_TYPE_PTR_MOVE },
        { "PtrBtn", ACTION_TYPE_PTR_BUTTON },
        { "PointerButton", ACTION_TYPE_PTR_BUTTON },
        { "LockPtrBtn", ACTION_TYPE_PTR_LOCK },
        { "LockPtrButton", ACTION_TYPE_PTR_LOCK },
        { "LockPointerButton", ACTION_TYPE_PTR_LOCK },
        { "LockPointerBtn", ACTION_TYPE_PTR_LOCK },
        { "SetPtrDflt", ACTION_TYPE_PTR_DEFAULT },
        { "SetPointerDefault", ACTION_TYPE_PTR_DEFAULT },
        { "Terminate", ACTION_TYPE_TERMINATE },
        { "TerminateServer", ACTION_TYPE_TERMINATE },
        { "SwitchScreen", ACTION_TYPE_SWITCH_VT },
        { "SetControls", ACTION_TYPE_CTRL_SET },
        { "LockControls", ACTION_TYPE_CTRL_LOCK },
        { "RedirectKey", ACTION_TYPE_KEY_REDIRECT },
        { "Redirect", ACTION_TYPE_KEY_REDIRECT },
        { "Private", ACTION_TYPE_PRIVATE },
        /* deprecated actions below here - unused */
        { "ISOLock", ACTION_TYPE_NONE },
        { "ActionMessage", ACTION_TYPE_NONE },
        { "MessageAction", ACTION_TYPE_NONE },
        { "Message", ACTION_TYPE_NONE },
        { "DeviceBtn", ACTION_TYPE_NONE },
        { "DevBtn", ACTION_TYPE_NONE },
        { "DevButton", ACTION_TYPE_NONE },
        { "DeviceButton", ACTION_TYPE_NONE },
        { "LockDeviceBtn", ACTION_TYPE_NONE },
        { "LockDevBtn", ACTION_TYPE_NONE },
        { "LockDevButton", ACTION_TYPE_NONE },
        { "LockDeviceButton", ACTION_TYPE_NONE },
        { "DeviceValuator", ACTION_TYPE_NONE },
        { "DevVal", ACTION_TYPE_NONE },
        { "DeviceVal", ACTION_TYPE_NONE },
        { "DevValuator", ACTION_TYPE_NONE },
        { NULL, 0 },
    };
    
    const LookupEntry symInterpretMatchMaskNames[] = {
        { "NoneOf", MATCH_NONE },
        { "AnyOfOrNone", MATCH_ANY_OR_NONE },
        { "AnyOf", MATCH_ANY },
        { "AllOf", MATCH_ALL },
        { "Exactly", MATCH_EXACTLY },
    };
    
    #define BUFFER_SIZE 1024
    
    static char *
    GetBuffer(size_t size)
    {
        static char buffer[BUFFER_SIZE];
        static size_t next;
        char *rtrn;
    
        if (size >= BUFFER_SIZE)
            return NULL;
    
        if (BUFFER_SIZE - next <= size)
            next = 0;
    
        rtrn = &buffer[next];
        next += size;
    
        return rtrn;
    }
    
    /*
     * Get a vmod name's text, where the vmod index is zero based
     * (0..XKB_NUM_VIRTUAL_MODS-1).
     */
    static const char *
    VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
    {
        int len;
        char *rtrn;
        const char *tmp = NULL;
        char buf[20];
    
        if (ndx >= XKB_NUM_VIRTUAL_MODS)
             tmp = "illegal";
        else
             tmp = xkb_atom_text(keymap->ctx, keymap->vmod_names[ndx]);
    
        if (!tmp) {
            snprintf(buf, sizeof(buf) - 1, "%d", ndx);
            tmp = buf;
        }
    
        len = strlen(tmp) + 1;
        if (len >= BUFFER_SIZE)
            len = BUFFER_SIZE - 1;
    
        rtrn = GetBuffer(len);
        strncpy(rtrn, tmp, len);
    
        return rtrn;
    }
    
    /* Get a mod mask's text, where the mask is in rmods+vmods format. */
    const char *
    VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
    {
        xkb_mod_index_t i;
        xkb_mod_mask_t bit;
        xkb_mod_mask_t rmask, vmask;
        int len, rem;
        const char *mm = NULL;
        char *rtrn, *str;
        char buf[BUFFER_SIZE];
    
        rmask = cmask & 0xff;
        vmask = cmask >> XKB_NUM_CORE_MODS;
    
        if (rmask == 0 && vmask == 0)
            return "none";
    
        if (rmask != 0)
            mm = ModMaskText(rmask);
    
        str = buf;
        buf[0] = '\0';
        rem = BUFFER_SIZE;
    
        if (vmask != 0) {
            for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS && rem > 1; i++, bit <<=
                     1) {
                if (!(vmask & bit))
                    continue;
    
                len = snprintf(str, rem, "%s%s",
                               (str != buf) ? "+" : "",
                               VModIndexText(keymap, i));
                rem -= len;
                str += len;
            }
    
            str = buf;
        }
        else
            str = NULL;
    
        len = (str ? strlen(str) : 0) + (mm ? strlen(mm) : 0) +
              (str && mm ? 1 : 0);
        if (len >= BUFFER_SIZE)
            len = BUFFER_SIZE - 1;
    
        rtrn = GetBuffer(len + 1);
        rtrn[0] = '\0';
    
        snprintf(rtrn, len + 1, "%s%s%s", (mm ? mm : ""),
                 (mm && str ? "+" : ""), (str ? str : ""));
    
        return rtrn;
    }
    
    /*
     * IMPORTATNT
     * The indices used for the legacy core modifiers is derived from
     * the order of the names in this table. It matches the values
     * ShiftMapIndex, LockMapIndex, etc. from X11/X.h. Take note before
     * changing.
     */
    static const char *modNames[XKB_NUM_CORE_MODS] = {
        "Shift",
        "Lock",
        "Control",
        "Mod1",
        "Mod2",
        "Mod3",
        "Mod4",
        "Mod5",
    };
    
    xkb_mod_index_t
    ModNameToIndex(const char *name)
    {
        xkb_mod_index_t i;
    
        for (i = 0; i < XKB_NUM_CORE_MODS; i++)
            if (istreq(name, modNames[i]))
                return i;
    
        return XKB_MOD_INVALID;
    }
    
    const char *
    ModIndexToName(xkb_mod_index_t ndx)
    {
        if (ndx < XKB_NUM_CORE_MODS)
            return modNames[ndx];
        return NULL;
    }
    
    const char *
    ModIndexText(xkb_mod_index_t ndx)
    {
        const char *name;
        char *buf;
    
        name = ModIndexToName(ndx);
        if (name)
            return name;
    
        if (ndx == XKB_MOD_INVALID)
            return "none";
    
        buf = GetBuffer(32);
        snprintf(buf, 32, "ILLEGAL_%02x", ndx);
    
        return buf;
    }
    
    /* Gets the text for the real modifiers only. */
    const char *
    ModMaskText(xkb_mod_mask_t mask)
    {
        int i, rem;
        xkb_mod_index_t bit;
        char *str, *buf;
    
        if ((mask & 0xff) == 0xff)
            return "all";
    
        if ((mask & 0xff) == 0)
            return "none";
    
        rem = 64;
        buf = GetBuffer(rem);
        str = buf;
        buf[0] = '\0';
        for (i = 0, bit = 1; i < XKB_NUM_CORE_MODS && rem > 1; i++, bit <<= 1) {
            int len;
    
            if (!(mask & bit))
                continue;
    
            len = snprintf(str, rem, "%s%s",
                           (str != buf ?  "+" : ""), modNames[i]);
            rem -= len;
            str += len;
        }
    
        return buf;
    }
    
    const char *
    ActionTypeText(unsigned type)
    {
        const char *name = LookupValue(actionTypeNames, type);
        return name ? name : "Private";
    }
    
    const char *
    KeysymText(xkb_keysym_t sym)
    {
        static char buffer[64];
    
        xkb_keysym_get_name(sym, buffer, sizeof buffer);
    
        return buffer;
    }
    
    const char *
    KeyNameText(const char name[XKB_KEY_NAME_LENGTH])
    {
        char *buf;
        int len;
    
        buf = GetBuffer(7);
        buf[0] = '<';
        strncpy(&buf[1], name, 4);
        buf[5] = '\0';
        len = strlen(buf);
        buf[len++] = '>';
        buf[len] = '\0';
    
        return buf;
    }
    
    const char *
    SIMatchText(enum xkb_match_operation type)
    {
        const char *name;
        char *buf;
    
        type &= MATCH_OP_MASK;
    
        name = LookupValue(symInterpretMatchMaskNames, type);
        if (name)
            return name;
    
        buf = GetBuffer(40);
        snprintf(buf, 40, "0x%x", type);
        return buf;
    }