Remove the XKB_NUM_VIRTUAL_MODIFIERS limit
[platform/upstream/libxkbcommon.git] / src / text.c
index 5286ba9..118820b 100644 (file)
  *
  ********************************************************/
 
+#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 *
@@ -47,59 +231,43 @@ GetBuffer(size_t size)
     return rtrn;
 }
 
+/* Get a vmod name's text, where the vmod index is zero based. */
 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 >= XkbNumVirtualMods)
-         tmp = "illegal";
-    else
-         tmp = 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;
+    if (ndx >= darray_size(keymap->vmods))
+        return "illegal";
+    return xkb_atom_text(keymap->ctx,
+                         darray_item(keymap->vmods, ndx).name);
 }
 
+/* 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 modMask,
-             xkb_mod_mask_t mask)
+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];
 
-    if (modMask == 0 && mask == 0)
+    rmask = cmask & 0xff;
+    vmask = cmask >> XKB_NUM_CORE_MODS;
+
+    if (rmask == 0 && vmask == 0)
         return "none";
 
-    if (modMask != 0)
-        mm = ModMaskText(modMask, false);
+    if (rmask != 0)
+        mm = ModMaskText(rmask);
 
     str = buf;
     buf[0] = '\0';
     rem = BUFFER_SIZE;
 
-    if (mask) {
-        for (i = 0, bit = 1; i < XkbNumVirtualMods && rem > 1; i++, bit <<=
-                 1) {
-            if (!(mask & bit))
+    if (vmask != 0) {
+        for (i = 0; i < darray_size(keymap->vmods) && rem > 1; i++) {
+            if (!(vmask & (1 << i)))
                 continue;
 
             len = snprintf(str, rem, "%s%s",
@@ -128,15 +296,22 @@ VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t modMask,
     return rtrn;
 }
 
-static const char *modNames[XkbNumModifiers] = {
-    [ShiftMapIndex]   = "Shift",
-    [LockMapIndex]    = "Lock",
-    [ControlMapIndex] = "Control",
-    [Mod1MapIndex]    = "Mod1",
-    [Mod2MapIndex]    = "Mod2",
-    [Mod3MapIndex]    = "Mod3",
-    [Mod4MapIndex]    = "Mod4",
-    [Mod5MapIndex]    = "Mod5",
+/*
+ * 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
@@ -144,7 +319,7 @@ ModNameToIndex(const char *name)
 {
     xkb_mod_index_t i;
 
-    for (i = 0; i < XkbNumModifiers; i++)
+    for (i = 0; i < XKB_NUM_CORE_MODS; i++)
         if (istreq(name, modNames[i]))
             return i;
 
@@ -154,7 +329,7 @@ ModNameToIndex(const char *name)
 const char *
 ModIndexToName(xkb_mod_index_t ndx)
 {
-    if (ndx < XkbNumModifiers)
+    if (ndx < XKB_NUM_CORE_MODS)
         return modNames[ndx];
     return NULL;
 }
@@ -169,7 +344,7 @@ ModIndexText(xkb_mod_index_t ndx)
     if (name)
         return name;
 
-    if (ndx == XkbNoModifier)
+    if (ndx == XKB_MOD_INVALID)
         return "none";
 
     buf = GetBuffer(32);
@@ -178,33 +353,32 @@ ModIndexText(xkb_mod_index_t ndx)
     return buf;
 }
 
+/* Gets the text for the real modifiers only. */
 const char *
-ModMaskText(xkb_mod_mask_t mask, bool cFormat)
+ModMaskText(xkb_mod_mask_t mask)
 {
     int i, rem;
     xkb_mod_index_t bit;
     char *str, *buf;
 
     if ((mask & 0xff) == 0xff)
-        return (cFormat ? "0xff" : "all");
+        return "all";
 
     if ((mask & 0xff) == 0)
-        return (cFormat ? "0" : "none");
+        return "none";
 
     rem = 64;
     buf = GetBuffer(rem);
     str = buf;
     buf[0] = '\0';
-    for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
+    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%s",
-                       (str != buf) ? (cFormat ? "|" : "+") : "",
-                       modNames[i],
-                       cFormat ? "Mask" : "");
+        len = snprintf(str, rem, "%s%s",
+                       (str != buf ?  "+" : ""), modNames[i]);
         rem -= len;
         str += len;
     }
@@ -213,56 +387,10 @@ ModMaskText(xkb_mod_mask_t mask, bool cFormat)
 }
 
 const char *
-FileTypeText(enum xkb_file_type type)
-{
-    switch (type) {
-    case FILE_TYPE_KEYMAP:
-        return "Keymap";
-    case FILE_TYPE_TYPES:
-        return "Types";
-    case FILE_TYPE_COMPAT:
-        return "CompatMap";
-    case FILE_TYPE_SYMBOLS:
-        return "Symbols";
-    case FILE_TYPE_KEYCODES:
-        return "KeyNames";
-    case FILE_TYPE_RULES:
-        return "Rules";
-    default:
-        return "unknown";
-    }
-}
-
-static const char *actionTypeNames[XkbSA_NumActions] = {
-    [XkbSA_NoAction]       = "NoAction",
-    [XkbSA_SetMods]        = "SetMods",
-    [XkbSA_LatchMods]      = "LatchMods",
-    [XkbSA_LockMods]       = "LockMods",
-    [XkbSA_SetGroup]       = "SetGroup",
-    [XkbSA_LatchGroup]     = "LatchGroup",
-    [XkbSA_LockGroup]      = "LockGroup",
-    [XkbSA_MovePtr]        = "MovePtr",
-    [XkbSA_PtrBtn]         = "PtrBtn",
-    [XkbSA_LockPtrBtn]     = "LockPtrBtn",
-    [XkbSA_SetPtrDflt]     = "SetPtrDflt",
-    [XkbSA_ISOLock]        = "ISOLock",
-    [XkbSA_Terminate]      = "Terminate",
-    [XkbSA_SwitchScreen]   = "SwitchScreen",
-    [XkbSA_SetControls]    = "SetControls",
-    [XkbSA_LockControls]   = "LockControls",
-    [XkbSA_ActionMessage]  = "ActionMessage",
-    [XkbSA_RedirectKey]    = "RedirectKey",
-    [XkbSA_DeviceBtn]      = "DeviceBtn",
-    [XkbSA_LockDeviceBtn]  = "LockDeviceBtn",
-    [XkbSA_DeviceValuator] = "DeviceValuator"
-};
-
-const char *
 ActionTypeText(unsigned type)
 {
-    if (type <= XkbSA_LastAction)
-        return actionTypeNames[type];
-    return "Private";
+    const char *name = LookupValue(actionTypeNames, type);
+    return name ? name : "Private";
 }
 
 const char *
@@ -276,49 +404,28 @@ KeysymText(xkb_keysym_t sym)
 }
 
 const char *
-KeyNameText(char *name)
+KeyNameText(struct xkb_context *ctx, xkb_atom_t name)
 {
-    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';
-
+    const char *sname = xkb_atom_text(ctx, name);
+    size_t len = strlen(sname) + 3;
+    char *buf = GetBuffer(len);
+    snprintf(buf, len, "<%s>", sname);
     return buf;
 }
 
-static const char *siMatchText[5] = {
-    "NoneOf",       /* XkbSI_NoneOf */
-    "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
-    "AnyOf",        /* XkbSI_AnyOf */
-    "AllOf",        /* XkbSI_AllOf */
-    "Exactly"       /* XkbSI_Exactly */
-};
-
 const char *
-SIMatchText(unsigned type)
+SIMatchText(enum xkb_match_operation type)
 {
+    const char *name;
     char *buf;
 
-    switch (type & XkbSI_OpMask) {
-    case XkbSI_NoneOf:
-        return siMatchText[0];
-    case XkbSI_AnyOfOrNone:
-        return siMatchText[1];
-    case XkbSI_AnyOf:
-        return siMatchText[2];
-    case XkbSI_AllOf:
-        return siMatchText[3];
-    case XkbSI_Exactly:
-        return siMatchText[4];
-    default:
-        buf = GetBuffer(40);
-        snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
-        return buf;
-    }
+    type &= MATCH_OP_MASK;
+
+    name = LookupValue(symInterpretMatchMaskNames, type);
+    if (name)
+        return name;
+
+    buf = GetBuffer(40);
+    snprintf(buf, 40, "0x%x", type);
+    return buf;
 }