Pass around xkb_key's instead of keycodes
[platform/upstream/libxkbcommon.git] / src / xkbcomp / symbols.c
index b3fda43..d766cd0 100644 (file)
@@ -55,7 +55,6 @@ typedef darray (union xkb_action) darray_xkb_action;
 typedef struct _KeyInfo {
     CommonInfo defs;
     unsigned long name; /* the 4 chars of the key name, as long */
-    unsigned char groupInfo;
     unsigned char typesDefined;
     unsigned char symsDefined;
     unsigned char actsDefined;
@@ -83,6 +82,9 @@ typedef struct _KeyInfo {
     struct xkb_behavior behavior;
     unsigned short vmodmap;
     xkb_atom_t dfltType;
+
+    uint8_t out_of_range_group_action;
+    uint8_t out_of_range_group_number;
 } KeyInfo;
 
 /**
@@ -99,7 +101,6 @@ InitKeyInfo(KeyInfo *keyi, unsigned file_id)
     keyi->defs.merge = MERGE_OVERRIDE;
     keyi->defs.next = NULL;
     keyi->name = KeyNameToLong(dflt);
-    keyi->groupInfo = 0;
     keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 0;
 
     for (i = 0; i < XkbNumKbdGroups; i++) {
@@ -116,35 +117,21 @@ InitKeyInfo(KeyInfo *keyi, unsigned file_id)
     keyi->behavior.data = 0;
     keyi->vmodmap = 0;
     keyi->repeat = RepeatUndefined;
+    keyi->out_of_range_group_action = 0;
+    keyi->out_of_range_group_number = 0;
 }
 
-/**
- * Free memory associated with this key keyi and reset to sane values.
- */
 static void
 FreeKeyInfo(KeyInfo *keyi)
 {
     int i;
 
-    keyi->defs.defined = 0;
-    keyi->defs.file_id = 0;
-    keyi->defs.merge = MERGE_OVERRIDE;
-    keyi->defs.next = NULL;
-    keyi->groupkeyi = 0;
-    keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 0;
     for (i = 0; i < XkbNumKbdGroups; i++) {
-        keyi->numLevels[i] = 0;
-        keyi->types[i] = XKB_ATOM_NONE;
         darray_free(keyi->syms[i]);
         darray_free(keyi->symsMapIndex[i]);
         darray_free(keyi->symsMapNumEntries[i]);
         darray_free(keyi->acts[i]);
     }
-    keyi->dfltType = XKB_ATOM_NONE;
-    keyi->behavior.type = XkbKB_Default;
-    keyi->behavior.data = 0;
-    keyi->vmodmap = 0;
-    keyi->repeat = RepeatUndefined;
 }
 
 /**
@@ -237,8 +224,9 @@ FreeSymbolsInfo(SymbolsInfo * info)
     KeyInfo *keyi;
 
     free(info->name);
-    darray_foreach(keyi, info->keys)
+    darray_foreach(keyi, info->keys) {
         FreeKeyInfo(keyi);
+    }
     darray_free(info->keys);
     if (info->modMap)
         ClearCommonInfo(&info->modMap->defs);
@@ -583,7 +571,8 @@ MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
         into->defs.defined |= _Key_Type_Dflt;
     }
     if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide)) {
-        into->groupInfo = from->groupInfo;
+        into->out_of_range_group_action = from->out_of_range_group_action;
+        into->out_of_range_group_number = from->out_of_range_group_number;
         into->defs.defined |= _Key_GroupInfo;
     }
     if (collide) {
@@ -1114,9 +1103,9 @@ SetSymbolsField(KeyInfo *keyi, struct xkb_keymap *keymap, char *field,
             return false;
         }
         if (tmp.uval)
-            keyi->groupInfo = XkbWrapIntoRange;
+            keyi->out_of_range_group_action = XkbWrapIntoRange;
         else
-            keyi->groupInfo = XkbClampIntoRange;
+            keyi->out_of_range_group_action = XkbClampIntoRange;
         keyi->defs.defined |= _Key_GroupInfo;
     }
     else if ((strcasecmp(field, "groupsclamp") == 0) ||
@@ -1129,9 +1118,9 @@ SetSymbolsField(KeyInfo *keyi, struct xkb_keymap *keymap, char *field,
             return false;
         }
         if (tmp.uval)
-            keyi->groupInfo = XkbClampIntoRange;
+            keyi->out_of_range_group_action = XkbClampIntoRange;
         else
-            keyi->groupInfo = XkbWrapIntoRange;
+            keyi->out_of_range_group_action = XkbWrapIntoRange;
         keyi->defs.defined |= _Key_GroupInfo;
     }
     else if ((strcasecmp(field, "groupsredirect") == 0) ||
@@ -1142,8 +1131,8 @@ SetSymbolsField(KeyInfo *keyi, struct xkb_keymap *keymap, char *field,
             ACTION("Definition with non-integer group ignored\n");
             return false;
         }
-        keyi->groupInfo =
-            XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
+        keyi->out_of_range_group_action = XkbRedirectIntoRange;
+        keyi->out_of_range_group_number = tmp.uval - 1;
         keyi->defs.defined |= _Key_GroupInfo;
     }
     else {
@@ -1433,9 +1422,8 @@ HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
 }
 
 /**
- * Given a keysym @sym, find the keycode which generates it
- * (returned in @kc_rtrn). This is used for example in a modifier
- * map definition, such as:
+ * Given a keysym @sym, return a key which generates it, or NULL.
+ * This is used for example in a modifier map definition, such as:
  *      modifier_map Lock           { Caps_Lock };
  * where we want to add the Lock modifier to the modmap of the key
  * which matches the keysym Caps_Lock.
@@ -1443,19 +1431,18 @@ HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
  * is chosen first by lowest group in which the keysym appears, than
  * by lowest level and than by lowest key code.
  */
-static bool
-FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym,
-                 xkb_keycode_t *kc_rtrn)
+static struct xkb_key *
+FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
 {
-    xkb_keycode_t kc;
+    struct xkb_key *key, *ret = NULL;
     unsigned int group, level, min_group = UINT_MAX, min_level = UINT_MAX;
 
-    for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) {
-        for (group = 0; group < XkbKeyNumGroups(keymap, kc); group++) {
-            for (level = 0; level < XkbKeyGroupWidth(keymap, kc, group);
+    xkb_foreach_key(key, keymap) {
+        for (group = 0; group < key->num_groups; group++) {
+            for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
                  level++) {
-                if (XkbKeyNumSyms(keymap, kc, group, level) != 1 ||
-                    (XkbKeySymEntry(keymap, kc, group, level))[0] != sym)
+                if (XkbKeyNumSyms(key, group, level) != 1 ||
+                    (XkbKeySymEntry(key, group, level))[0] != sym)
                     continue;
 
                 /*
@@ -1465,9 +1452,9 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym,
                  */
                 if (group < min_group ||
                     (group == min_group && level < min_level)) {
-                    *kc_rtrn = kc;
+                    ret = key;
                     if (group == 0 && level == 0) {
-                        return true;
+                        return ret;
                     }
                     else {
                         min_group = group;
@@ -1478,7 +1465,7 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym,
         }
     }
 
-    return min_group != UINT_MAX;
+    return ret;
 }
 
 /**
@@ -1704,17 +1691,16 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
 
     useAlias = (start_from == 0);
 
-    /* get the keycode for the key. */
-    if (!FindNamedKey(keymap, keyi->name, &kc, useAlias,
-                      CreateKeyNames(keymap), start_from)) {
-        if ((start_from == 0) && (warningLevel >= 5)) {
+    key = FindNamedKey(keymap, keyi->name, useAlias,
+                       CreateKeyNames(keymap), start_from);
+    if (!key) {
+        if (start_from == 0 && warningLevel >= 5) {
             WARN("Key %s not found in keycodes\n", longText(keyi->name));
             ACTION("Symbols ignored\n");
         }
         return false;
     }
-
-    key = XkbKey(keymap, kc);
+    kc = XkbKeyGetKeycode(keymap, key);
 
     haveActions = false;
     for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) {
@@ -1776,7 +1762,7 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
     darray_resize0(key->syms, sizeSyms);
 
     if (haveActions) {
-        outActs = XkbcResizeKeyActions(keymap, kc, width * nGroups);
+        outActs = XkbcResizeKeyActions(keymap, key, width * nGroups);
         if (outActs == NULL) {
             WSGO("Could not enlarge actions for %s (key %d)\n",
                  longText(keyi->name), kc);
@@ -1787,15 +1773,14 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
     else
         outActs = NULL;
 
-    if (keyi->defs.defined & _Key_GroupInfo)
-        i = keyi->groupInfo;
-    else
-        i = key->group_info;
-
-    key->group_info = XkbSetNumGroups(i, nGroups);
+    key->num_groups = nGroups;
+    if (keyi->defs.defined & _Key_GroupInfo) {
+        key->out_of_range_group_number = keyi->out_of_range_group_number;
+        key->out_of_range_group_action = keyi->out_of_range_group_action;
+    }
     key->width = width;
-    key->sym_index = uTypedCalloc(nGroups * width, int);
-    key->num_syms = uTypedCalloc(nGroups * width, unsigned int);
+    key->sym_index = calloc(nGroups * width, sizeof(*key->sym_index));
+    key->num_syms = calloc(nGroups * width, sizeof(*key->num_syms));
 
     for (i = 0; i < nGroups; i++) {
         /* assign kt_index[i] to the index of the type in map->types.
@@ -1861,43 +1846,35 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
 static bool
 CopyModMapDef(struct xkb_keymap *keymap, ModMapEntry *entry)
 {
-    xkb_keycode_t kc;
+    struct xkb_key *key;
 
-    if (!entry->haveSymbol &&
-        !FindNamedKey(keymap, entry->u.keyName, &kc, true,
-                      CreateKeyNames(keymap), 0)) {
-        if (warningLevel >= 5) {
-            WARN("Key %s not found in keycodes\n",
-                 longText(entry->u.keyName));
-            ACTION("Modifier map entry for %s not updated\n",
-                   XkbcModIndexText(entry->modifier));
+    if (!entry->haveSymbol) {
+        key = FindNamedKey(keymap, entry->u.keyName, true,
+                           CreateKeyNames(keymap), 0);
+        if (!key) {
+            if (warningLevel >= 5) {
+                WARN("Key %s not found in keycodes\n",
+                     longText(entry->u.keyName));
+                ACTION("Modifier map entry for %s not updated\n",
+                       XkbcModIndexText(entry->modifier));
+            }
+            return false;
         }
-        return false;
     }
-    else if (entry->haveSymbol &&
-             !FindKeyForSymbol(keymap, entry->u.keySym, &kc)) {
-        if (warningLevel > 5) {
-            WARN("Key \"%s\" not found in symbol map\n",
-                 XkbcKeysymText(entry->u.keySym));
-            ACTION("Modifier map entry for %s not updated\n",
-                   XkbcModIndexText(entry->modifier));
+    else {
+        key = FindKeyForSymbol(keymap, entry->u.keySym);
+        if (!key) {
+            if (warningLevel > 5) {
+                WARN("Key \"%s\" not found in symbol map\n",
+                     XkbcKeysymText(entry->u.keySym));
+                ACTION("Modifier map entry for %s not updated\n",
+                       XkbcModIndexText(entry->modifier));
+            }
+            return false;
         }
-        return false;
     }
 
-    XkbKey(keymap, kc)->modmap |= (1 << entry->modifier);
-    return true;
-}
-
-static bool
-InitKeymapForSymbols(struct xkb_keymap *keymap)
-{
-    size_t nKeys = keymap->max_key_code + 1;
-
-    darray_resize0(keymap->keys, nKeys);
-
-    darray_resize0(keymap->acts, darray_size(keymap->acts) + 32 + 1);
-
+    key->modmap |= (1 << entry->modifier);
     return true;
 }
 
@@ -1913,8 +1890,6 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
                enum merge_mode merge)
 {
     int i;
-    bool ok;
-    xkb_keycode_t kc;
     struct xkb_key *key;
     SymbolsInfo info;
     KeyInfo *keyi;
@@ -1930,9 +1905,7 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
     if (info.errorCount != 0)
         goto err_info;
 
-    ok = InitKeymapForSymbols(keymap);
-    if (!ok)
-        goto err_info;
+    darray_resize0(keymap->acts, darray_size(keymap->acts) + 32 + 1);
 
     if (info.name)
         keymap->symbols_section_name = strdup(info.name);
@@ -1958,14 +1931,13 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
             info.errorCount++;
 
     if (warningLevel > 3) {
-        for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) {
-            key = XkbKey(keymap, kc);
+        xkb_foreach_key(key, keymap) {
             if (key->name[0] == '\0')
                 continue;
 
-            if (XkbKeyNumGroups(keymap, kc) < 1)
+            if (key->num_groups < 1)
                 WARN("No symbols defined for <%.4s> (keycode %d)\n",
-                     key->name, kc);
+                     key->name, XkbKeyGetKeycode(keymap, key));
         }
     }