Pass around xkb_key's instead of keycodes
[platform/upstream/libxkbcommon.git] / src / xkbcomp / symbols.c
index ab7f224..d766cd0 100644 (file)
@@ -1,27 +1,27 @@
 /************************************************************
- 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.
-
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 <limits.h>
 /***====================================================================***/
 
 /* Needed to work with the typechecker. */
-typedef darray(xkb_keysym_t) darray_xkb_keysym_t;
-typedef darray(union xkb_action) darray_xkb_action;
-
-#define        RepeatYes       1
-#define        RepeatNo        0
-#define        RepeatUndefined ~((unsigned)0)
-
-#define        _Key_Syms       (1<<0)
-#define        _Key_Acts       (1<<1)
-#define        _Key_Repeat     (1<<2)
-#define        _Key_Behavior   (1<<3)
-#define        _Key_Type_Dflt  (1<<4)
-#define        _Key_Types      (1<<5)
-#define        _Key_GroupInfo  (1<<6)
-#define        _Key_VModMap    (1<<7)
-
-typedef struct _KeyInfo
-{
+typedef darray (xkb_keysym_t) darray_xkb_keysym_t;
+typedef darray (union xkb_action) darray_xkb_action;
+
+#define RepeatYes       1
+#define RepeatNo        0
+#define RepeatUndefined ~((unsigned) 0)
+
+#define _Key_Syms       (1 << 0)
+#define _Key_Acts       (1 << 1)
+#define _Key_Repeat     (1 << 2)
+#define _Key_Behavior   (1 << 3)
+#define _Key_Type_Dflt  (1 << 4)
+#define _Key_Types      (1 << 5)
+#define _Key_GroupInfo  (1 << 6)
+#define _Key_VModMap    (1 << 7)
+
+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;
@@ -84,68 +82,56 @@ 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;
 
 /**
  * Init the given key info to sane values.
  */
 static void
-InitKeyInfo(KeyInfo * info, unsigned file_id)
+InitKeyInfo(KeyInfo *keyi, unsigned file_id)
 {
     int i;
     static const char dflt[4] = "*";
 
-    info->defs.defined = 0;
-    info->defs.file_id = file_id;
-    info->defs.merge = MERGE_OVERRIDE;
-    info->defs.next = NULL;
-    info->name = KeyNameToLong(dflt);
-    info->groupInfo = 0;
-    info->typesDefined = info->symsDefined = info->actsDefined = 0;
-    for (i = 0; i < XkbNumKbdGroups; i++)
-    {
-        info->numLevels[i] = 0;
-        info->types[i] = XKB_ATOM_NONE;
-        darray_init(info->syms[i]);
-        darray_init(info->symsMapIndex[i]);
-        darray_init(info->symsMapNumEntries[i]);
-        darray_init(info->acts[i]);
-    }
-    info->dfltType = XKB_ATOM_NONE;
-    info->behavior.type = XkbKB_Default;
-    info->behavior.data = 0;
-    info->vmodmap = 0;
-    info->repeat = RepeatUndefined;
+    keyi->defs.defined = 0;
+    keyi->defs.file_id = file_id;
+    keyi->defs.merge = MERGE_OVERRIDE;
+    keyi->defs.next = NULL;
+    keyi->name = KeyNameToLong(dflt);
+    keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 0;
+
+    for (i = 0; i < XkbNumKbdGroups; i++) {
+        keyi->numLevels[i] = 0;
+        keyi->types[i] = XKB_ATOM_NONE;
+        darray_init(keyi->syms[i]);
+        darray_init(keyi->symsMapIndex[i]);
+        darray_init(keyi->symsMapNumEntries[i]);
+        darray_init(keyi->acts[i]);
+    }
+
+    keyi->dfltType = XKB_ATOM_NONE;
+    keyi->behavior.type = XkbKB_Default;
+    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 info and reset to sane values.
- */
 static void
-FreeKeyInfo(KeyInfo * info)
+FreeKeyInfo(KeyInfo *keyi)
 {
     int i;
 
-    info->defs.defined = 0;
-    info->defs.file_id = 0;
-    info->defs.merge = MERGE_OVERRIDE;
-    info->defs.next = NULL;
-    info->groupInfo = 0;
-    info->typesDefined = info->symsDefined = info->actsDefined = 0;
-    for (i = 0; i < XkbNumKbdGroups; i++)
-    {
-        info->numLevels[i] = 0;
-        info->types[i] = XKB_ATOM_NONE;
-        darray_free(info->syms[i]);
-        darray_free(info->symsMapIndex[i]);
-        darray_free(info->symsMapNumEntries[i]);
-        darray_free(info->acts[i]);
-    }
-    info->dfltType = XKB_ATOM_NONE;
-    info->behavior.type = XkbKB_Default;
-    info->behavior.data = 0;
-    info->vmodmap = 0;
-    info->repeat = RepeatUndefined;
+    for (i = 0; i < XkbNumKbdGroups; i++) {
+        darray_free(keyi->syms[i]);
+        darray_free(keyi->symsMapIndex[i]);
+        darray_free(keyi->symsMapNumEntries[i]);
+        darray_free(keyi->acts[i]);
+    }
 }
 
 /**
@@ -184,20 +170,17 @@ CopyKeyInfo(KeyInfo * old, KeyInfo * new, bool clearOld)
 
 /***====================================================================***/
 
-typedef struct _ModMapEntry
-{
+typedef struct _ModMapEntry {
     CommonInfo defs;
     bool haveSymbol;
     int modifier;
-    union
-    {
+    union {
         unsigned long keyName;
         xkb_keysym_t keySym;
     } u;
 } ModMapEntry;
 
-typedef struct _SymbolsInfo
-{
+typedef struct _SymbolsInfo {
     char *name;         /* e.g. pc+us+inet(evdev) */
     int errorCount;
     unsigned file_id;
@@ -238,11 +221,12 @@ InitSymbolsInfo(SymbolsInfo * info, struct xkb_keymap *keymap,
 static void
 FreeSymbolsInfo(SymbolsInfo * info)
 {
-    KeyInfo *key;
+    KeyInfo *keyi;
 
     free(info->name);
-    darray_foreach(key, info->keys)
-        FreeKeyInfo(key);
+    darray_foreach(keyi, info->keys) {
+        FreeKeyInfo(keyi);
+    }
     darray_free(info->keys);
     if (info->modMap)
         ClearCommonInfo(&info->modMap->defs);
@@ -252,32 +236,32 @@ FreeSymbolsInfo(SymbolsInfo * info)
 }
 
 static bool
-ResizeKeyGroup(KeyInfo * key, unsigned int group, unsigned int numLevels,
+ResizeKeyGroup(KeyInfo *keyi, unsigned int group, unsigned int numLevels,
                unsigned sizeSyms, bool forceActions)
 {
     int i;
 
-    if (darray_size(key->syms[group]) < sizeSyms)
-        darray_resize0(key->syms[group], sizeSyms);
+    if (darray_size(keyi->syms[group]) < sizeSyms)
+        darray_resize0(keyi->syms[group], sizeSyms);
 
-    if (darray_empty(key->symsMapIndex[group]) ||
-        key->numLevels[group] < numLevels) {
-        darray_resize(key->symsMapIndex[group], numLevels);
-        for (i = key->numLevels[group]; i < numLevels; i++)
-            darray_item(key->symsMapIndex[group], i) = -1;
+    if (darray_empty(keyi->symsMapIndex[group]) ||
+        keyi->numLevels[group] < numLevels) {
+        darray_resize(keyi->symsMapIndex[group], numLevels);
+        for (i = keyi->numLevels[group]; i < numLevels; i++)
+            darray_item(keyi->symsMapIndex[group], i) = -1;
     }
 
-    if (darray_empty(key->symsMapNumEntries[group]) ||
-        key->numLevels[group] < numLevels)
-        darray_resize0(key->symsMapNumEntries[group], numLevels);
+    if (darray_empty(keyi->symsMapNumEntries[group]) ||
+        keyi->numLevels[group] < numLevels)
+        darray_resize0(keyi->symsMapNumEntries[group], numLevels);
 
-    if ((forceActions && (key->numLevels[group] < numLevels ||
-                          darray_empty(key->acts[group]))) ||
-        (key->numLevels[group] < numLevels && !darray_empty(key->acts[group])))
-        darray_resize0(key->acts[group], numLevels);
+    if ((forceActions && (keyi->numLevels[group] < numLevels ||
+                          darray_empty(keyi->acts[group]))) ||
+        (keyi->numLevels[group] < numLevels && !darray_empty(keyi->acts[group])))
+        darray_resize0(keyi->acts[group], numLevels);
 
-    if (key->numLevels[group] < numLevels)
-        key->numLevels[group] = numLevels;
+    if (keyi->numLevels[group] < numLevels)
+        keyi->numLevels[group] = numLevels;
 
     return true;
 }
@@ -304,17 +288,15 @@ MergeKeyGroups(SymbolsInfo * info,
     clobber = (from->defs.merge != MERGE_AUGMENT);
 
     report = (warningLevel > 9) ||
-        ((into->defs.file_id == from->defs.file_id) && (warningLevel > 0));
+             ((into->defs.file_id == from->defs.file_id) && (warningLevel > 0));
 
     darray_init(resultSyms);
 
-    if (into->numLevels[group] >= from->numLevels[group])
-    {
+    if (into->numLevels[group] >= from->numLevels[group]) {
         resultActs = into->acts[group];
         resultWidth = into->numLevels[group];
     }
-    else
-    {
+    else {
         resultActs = from->acts[group];
         resultWidth = from->numLevels[group];
         darray_resize(into->symsMapIndex[group],
@@ -327,11 +309,9 @@ MergeKeyGroups(SymbolsInfo * info,
     }
 
     if (darray_empty(resultActs) && (!darray_empty(into->acts[group]) ||
-                                     !darray_empty(from->acts[group])))
-    {
+                                     !darray_empty(from->acts[group]))) {
         darray_resize0(resultActs, resultWidth);
-        for (i = 0; i < resultWidth; i++)
-        {
+        for (i = 0; i < resultWidth; i++) {
             union xkb_action *fromAct = NULL, *toAct = NULL;
 
             if (!darray_empty(from->acts[group]))
@@ -341,36 +321,30 @@ MergeKeyGroups(SymbolsInfo * info,
                 toAct = &darray_item(into->acts[group], i);
 
             if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction))
-                && (toAct != NULL))
-            {
+                && (toAct != NULL)) {
                 darray_item(resultActs, i) = *toAct;
             }
             else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction))
-                     && (fromAct != NULL))
-            {
+                     && (fromAct != NULL)) {
                 darray_item(resultActs, i) = *fromAct;
             }
-            else
-            {
+            else {
                 union xkb_action *use, *ignore;
-                if (clobber)
-                {
+                if (clobber) {
                     use = fromAct;
                     ignore = toAct;
                 }
-                else
-                {
+                else {
                     use = toAct;
                     ignore = fromAct;
                 }
-                if (report)
-                {
+                if (report) {
                     WARN
                         ("Multiple actions for level %d/group %d on key %s\n",
-                         i + 1, group + 1, longText(into->name));
+                        i + 1, group + 1, longText(into->name));
                     ACTION("Using %s, ignoring %s\n",
-                            XkbcActionTypeText(use->type),
-                            XkbcActionTypeText(ignore->type));
+                           XkbcActionTypeText(use->type),
+                           XkbcActionTypeText(ignore->type));
                 }
                 if (use)
                     darray_item(resultActs, i) = *use;
@@ -378,8 +352,7 @@ MergeKeyGroups(SymbolsInfo * info,
         }
     }
 
-    for (i = 0; i < resultWidth; i++)
-    {
+    for (i = 0; i < resultWidth; i++) {
         unsigned int fromSize = 0;
         unsigned toSize = 0;
 
@@ -391,18 +364,15 @@ MergeKeyGroups(SymbolsInfo * info,
             i < into->numLevels[group])
             toSize = darray_item(into->symsMapNumEntries[group], i);
 
-        if (fromSize == 0)
-        {
+        if (fromSize == 0) {
             resultSize += toSize;
             using |= TO;
         }
-        else if (toSize == 0 || clobber)
-        {
+        else if (toSize == 0 || clobber) {
             resultSize += fromSize;
             using |= FROM;
         }
-        else
-        {
+        else {
             resultSize += toSize;
             using |= TO;
         }
@@ -411,8 +381,7 @@ MergeKeyGroups(SymbolsInfo * info,
     if (resultSize == 0)
         goto out;
 
-    if (using == FROM)
-    {
+    if (using == FROM) {
         resultSyms = from->syms[group];
         darray_free(into->symsMapNumEntries[group]);
         darray_free(into->symsMapIndex[group]);
@@ -422,16 +391,14 @@ MergeKeyGroups(SymbolsInfo * info,
         darray_init(from->symsMapIndex[group]);
         goto out;
     }
-    else if (using == TO)
-    {
+    else if (using == TO) {
         resultSyms = into->syms[group];
         goto out;
     }
 
     darray_resize0(resultSyms, resultSize);
 
-    for (i = 0; i < resultWidth; i++)
-    {
+    for (i = 0; i < resultWidth; i++) {
         enum key_group_selector use = NONE;
         unsigned int fromSize = 0;
         unsigned int toSize = 0;
@@ -442,8 +409,7 @@ MergeKeyGroups(SymbolsInfo * info,
         if (i < into->numLevels[group])
             toSize = darray_item(into->symsMapNumEntries[group], i);
 
-        if (fromSize == 0 && toSize == 0)
-        {
+        if (fromSize == 0 && toSize == 0) {
             darray_item(into->symsMapIndex[group], i) = -1;
             darray_item(into->symsMapNumEntries[group], i) = 0;
             continue;
@@ -456,8 +422,7 @@ MergeKeyGroups(SymbolsInfo * info,
         else
             use = TO;
 
-        if (toSize && fromSize && report)
-        {
+        if (toSize && fromSize && report) {
             INFO("Multiple symbols for group %d, level %d on key %s\n",
                  group + 1, i + 1, longText(into->name));
             ACTION("Using %s, ignoring %s\n",
@@ -465,22 +430,22 @@ MergeKeyGroups(SymbolsInfo * info,
                    (use == FROM ? "to" : "from"));
         }
 
-        if (use == FROM)
-        {
+        if (use == FROM) {
             memcpy(darray_mem(resultSyms, cur_idx),
                    darray_mem(from->syms[group],
                               darray_item(from->symsMapIndex[group], i)),
-                   darray_item(from->symsMapNumEntries[group], i) * sizeof(xkb_keysym_t));
+                   darray_item(from->symsMapNumEntries[group],
+                               i) * sizeof(xkb_keysym_t));
             darray_item(into->symsMapIndex[group], i) = cur_idx;
             darray_item(into->symsMapNumEntries[group], i) =
                 darray_item(from->symsMapNumEntries[group], i);
         }
-        else
-        {
+        else {
             memcpy(darray_mem(resultSyms, cur_idx),
                    darray_mem(into->syms[group],
                               darray_item(into->symsMapIndex[group], i)),
-                   darray_item(into->symsMapNumEntries[group], i) * sizeof(xkb_keysym_t));
+                   darray_item(into->symsMapNumEntries[group],
+                               i) * sizeof(xkb_keysym_t));
             darray_item(into->symsMapIndex[group], i) = cur_idx;
         }
         cur_idx += darray_item(into->symsMapNumEntries[group], i);
@@ -519,12 +484,9 @@ MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
     unsigned collide = 0;
     bool report;
 
-    if (from->defs.merge == MERGE_REPLACE)
-    {
-        for (i = 0; i < XkbNumKbdGroups; i++)
-        {
-            if (into->numLevels[i] != 0)
-            {
+    if (from->defs.merge == MERGE_REPLACE) {
+        for (i = 0; i < XkbNumKbdGroups; i++) {
+            if (into->numLevels[i] != 0) {
                 darray_free(into->syms[i]);
                 darray_free(into->acts[i]);
             }
@@ -536,12 +498,9 @@ MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
     report = ((warningLevel > 9) ||
               ((into->defs.file_id == from->defs.file_id)
                && (warningLevel > 0)));
-    for (i = 0; i < XkbNumKbdGroups; i++)
-    {
-        if (from->numLevels[i] > 0)
-        {
-            if (into->numLevels[i] == 0)
-            {
+    for (i = 0; i < XkbNumKbdGroups; i++) {
+        if (from->numLevels[i] > 0) {
+            if (into->numLevels[i] == 0) {
                 into->numLevels[i] = from->numLevels[i];
                 into->syms[i] = from->syms[i];
                 into->symsMapIndex[i] = from->symsMapIndex[i];
@@ -559,10 +518,8 @@ MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
                 if (!darray_empty(into->acts[i]))
                     into->defs.defined |= _Key_Acts;
             }
-            else
-            {
-                if (report)
-                {
+            else {
+                if (report) {
                     if (!darray_empty(into->syms[i]))
                         collide |= _Key_Syms;
                     if (!darray_empty(into->acts[i]))
@@ -571,90 +528,80 @@ MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
                 MergeKeyGroups(info, into, from, (unsigned) i);
             }
         }
-        if (from->types[i] != XKB_ATOM_NONE)
-        {
+        if (from->types[i] != XKB_ATOM_NONE) {
             if ((into->types[i] != XKB_ATOM_NONE) && report &&
-                (into->types[i] != from->types[i]))
-            {
+                (into->types[i] != from->types[i])) {
                 xkb_atom_t use, ignore;
                 collide |= _Key_Types;
-                if (from->defs.merge != MERGE_AUGMENT)
-                {
+                if (from->defs.merge != MERGE_AUGMENT) {
                     use = from->types[i];
                     ignore = into->types[i];
                 }
-                else
-                {
+                else {
                     use = into->types[i];
                     ignore = from->types[i];
                 }
                 WARN
                     ("Multiple definitions for group %d type of key %s\n",
-                     i, longText(into->name));
+                    i, longText(into->name));
                 ACTION("Using %s, ignoring %s\n",
-                        xkb_atom_text(keymap->ctx, use),
-                        xkb_atom_text(keymap->ctx, ignore));
+                       xkb_atom_text(keymap->ctx, use),
+                       xkb_atom_text(keymap->ctx, ignore));
             }
             if ((from->defs.merge != MERGE_AUGMENT)
-                || (into->types[i] == XKB_ATOM_NONE))
-            {
+                || (into->types[i] == XKB_ATOM_NONE)) {
                 into->types[i] = from->types[i];
             }
         }
     }
-    if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide))
-    {
+    if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide)) {
         into->behavior = from->behavior;
         into->defs.defined |= _Key_Behavior;
     }
-    if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide))
-    {
+    if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide)) {
         into->vmodmap = from->vmodmap;
         into->defs.defined |= _Key_VModMap;
     }
-    if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide))
-    {
+    if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide)) {
         into->repeat = from->repeat;
         into->defs.defined |= _Key_Repeat;
     }
-    if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide))
-    {
+    if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide)) {
         into->dfltType = from->dfltType;
         into->defs.defined |= _Key_Type_Dflt;
     }
-    if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide))
-    {
-        into->groupInfo = from->groupInfo;
+    if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide)) {
+        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)
-    {
+    if (collide) {
         WARN("Symbol map for key %s redefined\n",
-              longText(into->name));
+             longText(into->name));
         ACTION("Using %s definition for conflicting fields\n",
-                (from->defs.merge == MERGE_AUGMENT ? "first" : "last"));
+               (from->defs.merge == MERGE_AUGMENT ? "first" : "last"));
     }
     return true;
 }
 
 static bool
-AddKeySymbols(SymbolsInfo *info, KeyInfo *key, struct xkb_keymap *keymap)
+AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, struct xkb_keymap *keymap)
 {
     unsigned long real_name;
     KeyInfo *iter, *new;
 
     darray_foreach(iter, info->keys)
-        if (iter->name == key->name)
-            return MergeKeys(info, keymap, iter, key);
+        if (iter->name == keyi->name)
+            return MergeKeys(info, keymap, iter, keyi);
 
-    if (FindKeyNameForAlias(keymap, key->name, &real_name))
+    if (FindKeyNameForAlias(keymap, keyi->name, &real_name))
         darray_foreach(iter, info->keys)
             if (iter->name == real_name)
-                return MergeKeys(info, keymap, iter, key);
+                return MergeKeys(info, keymap, iter, keyi);
 
     darray_resize0(info->keys, darray_size(info->keys) + 1);
     new = &darray_item(info->keys, darray_size(info->keys) - 1);
-    return CopyKeyInfo(key, new, true);
+    return CopyKeyInfo(keyi, new, true);
 }
 
 static bool
@@ -664,66 +611,56 @@ AddModMapEntry(SymbolsInfo * info, ModMapEntry * new)
     bool clobber;
 
     clobber = (new->defs.merge != MERGE_AUGMENT);
-    for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next)
-    {
+    for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next) {
         if (new->haveSymbol && mm->haveSymbol
-            && (new->u.keySym == mm->u.keySym))
-        {
+            && (new->u.keySym == mm->u.keySym)) {
             unsigned use, ignore;
-            if (mm->modifier != new->modifier)
-            {
-                if (clobber)
-                {
+            if (mm->modifier != new->modifier) {
+                if (clobber) {
                     use = new->modifier;
                     ignore = mm->modifier;
                 }
-                else
-                {
+                else {
                     use = mm->modifier;
                     ignore = new->modifier;
                 }
                 ERROR
                     ("%s added to symbol map for multiple modifiers\n",
-                     XkbcKeysymText(new->u.keySym));
+                    XkbcKeysymText(new->u.keySym));
                 ACTION("Using %s, ignoring %s.\n",
-                        XkbcModIndexText(use),
-                        XkbcModIndexText(ignore));
+                       XkbcModIndexText(use),
+                       XkbcModIndexText(ignore));
                 mm->modifier = use;
             }
             return true;
         }
         if ((!new->haveSymbol) && (!mm->haveSymbol) &&
-            (new->u.keyName == mm->u.keyName))
-        {
+            (new->u.keyName == mm->u.keyName)) {
             unsigned use, ignore;
-            if (mm->modifier != new->modifier)
-            {
-                if (clobber)
-                {
+            if (mm->modifier != new->modifier) {
+                if (clobber) {
                     use = new->modifier;
                     ignore = mm->modifier;
                 }
-                else
-                {
+                else {
                     use = mm->modifier;
                     ignore = new->modifier;
                 }
                 ERROR("Key %s added to map for multiple modifiers\n",
-                       longText(new->u.keyName));
+                      longText(new->u.keyName));
                 ACTION("Using %s, ignoring %s.\n",
-                        XkbcModIndexText(use),
-                        XkbcModIndexText(ignore));
+                       XkbcModIndexText(use),
+                       XkbcModIndexText(ignore));
                 mm->modifier = use;
             }
             return true;
         }
     }
     mm = uTypedAlloc(ModMapEntry);
-    if (mm == NULL)
-    {
+    if (mm == NULL) {
         WSGO("Could not allocate modifier map entry\n");
         ACTION("Modifier map for %s will be incomplete\n",
-                XkbcModIndexText(new->modifier));
+               XkbcModIndexText(new->modifier));
         return false;
     }
     *mm = *new;
@@ -739,41 +676,35 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
                      enum merge_mode merge, struct xkb_keymap *keymap)
 {
     unsigned int i;
-    KeyInfo *key;
+    KeyInfo *keyi;
 
-    if (from->errorCount > 0)
-    {
+    if (from->errorCount > 0) {
         into->errorCount += from->errorCount;
         return;
     }
-    if (into->name == NULL)
-    {
+    if (into->name == NULL) {
         into->name = from->name;
         from->name = NULL;
     }
-    for (i = 0; i < XkbNumKbdGroups; i++)
-    {
-        if (from->groupNames[i] != XKB_ATOM_NONE)
-        {
+    for (i = 0; i < XkbNumKbdGroups; i++) {
+        if (from->groupNames[i] != XKB_ATOM_NONE) {
             if ((merge != MERGE_AUGMENT) ||
                 (into->groupNames[i] == XKB_ATOM_NONE))
                 into->groupNames[i] = from->groupNames[i];
         }
     }
 
-    darray_foreach(key, from->keys) {
+    darray_foreach(keyi, from->keys) {
         if (merge != MERGE_DEFAULT)
-            key->defs.merge = merge;
+            keyi->defs.merge = merge;
 
-        if (!AddKeySymbols(into, key, keymap))
+        if (!AddKeySymbols(into, keyi, keymap))
             into->errorCount++;
     }
 
-    if (from->modMap != NULL)
-    {
+    if (from->modMap != NULL) {
         ModMapEntry *mm, *next;
-        for (mm = from->modMap; mm != NULL; mm = next)
-        {
+        for (mm = from->modMap; mm != NULL; mm = next) {
             if (merge != MERGE_DEFAULT)
                 mm->defs.merge = merge;
             if (!AddModMapEntry(into, mm))
@@ -789,76 +720,65 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
 
 static void
 HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
-                  enum merge_mode merge, SymbolsInfo *info);
+                  enum merge_mode merge,
+                  SymbolsInfo *info);
 
 static bool
 HandleIncludeSymbols(IncludeStmt *stmt, struct xkb_keymap *keymap,
                      SymbolsInfo *info)
 {
-    unsigned newMerge;
+    enum merge_mode newMerge;
     XkbFile *rtrn;
     SymbolsInfo included;
     bool haveSelf;
 
     haveSelf = false;
-    if ((stmt->file == NULL) && (stmt->map == NULL))
-    {
+    if ((stmt->file == NULL) && (stmt->map == NULL)) {
         haveSelf = true;
         included = *info;
         memset(info, 0, sizeof(SymbolsInfo));
     }
     else if (ProcessIncludeFile(keymap->ctx, stmt, FILE_TYPE_SYMBOLS, &rtrn,
-                                &newMerge))
-    {
+                                &newMerge)) {
         InitSymbolsInfo(&included, keymap, rtrn->id);
         included.merge = included.dflt.defs.merge = MERGE_OVERRIDE;
-        if (stmt->modifier)
-        {
+        if (stmt->modifier) {
             included.explicit_group = atoi(stmt->modifier) - 1;
         }
-        else
-        {
+        else {
             included.explicit_group = info->explicit_group;
         }
         HandleSymbolsFile(rtrn, keymap, MERGE_OVERRIDE, &included);
-        if (stmt->stmt != NULL)
-        {
+        if (stmt->stmt != NULL) {
             free(included.name);
             included.name = stmt->stmt;
             stmt->stmt = NULL;
         }
         FreeXKBFile(rtrn);
     }
-    else
-    {
+    else {
         info->errorCount += 10;
         return false;
     }
-    if ((stmt->next != NULL) && (included.errorCount < 1))
-    {
+    if ((stmt->next != NULL) && (included.errorCount < 1)) {
         IncludeStmt *next;
         unsigned op;
         SymbolsInfo next_incl;
 
-        for (next = stmt->next; next != NULL; next = next->next)
-        {
-            if ((next->file == NULL) && (next->map == NULL))
-            {
+        for (next = stmt->next; next != NULL; next = next->next) {
+            if ((next->file == NULL) && (next->map == NULL)) {
                 haveSelf = true;
                 MergeIncludedSymbols(&included, info, next->merge, keymap);
                 FreeSymbolsInfo(info);
             }
             else if (ProcessIncludeFile(keymap->ctx, next, FILE_TYPE_SYMBOLS,
-                                        &rtrn, &op))
-            {
+                                        &rtrn, &op)) {
                 InitSymbolsInfo(&next_incl, keymap, rtrn->id);
                 next_incl.merge = next_incl.dflt.defs.merge = MERGE_OVERRIDE;
-                if (next->modifier)
-                {
+                if (next->modifier) {
                     next_incl.explicit_group = atoi(next->modifier) - 1;
                 }
-                else
-                {
+                else {
                     next_incl.explicit_group = info->explicit_group;
                 }
                 HandleSymbolsFile(rtrn, keymap, MERGE_OVERRIDE, &next_incl);
@@ -866,33 +786,30 @@ HandleIncludeSymbols(IncludeStmt *stmt, struct xkb_keymap *keymap,
                 FreeSymbolsInfo(&next_incl);
                 FreeXKBFile(rtrn);
             }
-            else
-            {
+            else {
                 info->errorCount += 10;
                 FreeSymbolsInfo(&included);
                 return false;
             }
         }
     }
-    else if (stmt->next)
-    {
+    else if (stmt->next) {
         info->errorCount += included.errorCount;
     }
     if (haveSelf)
         *info = included;
-    else
-    {
+    else {
         MergeIncludedSymbols(info, &included, newMerge, keymap);
         FreeSymbolsInfo(&included);
     }
     return (info->errorCount == 0);
 }
 
-#define        SYMBOLS 1
-#define        ACTIONS 2
+#define SYMBOLS 1
+#define ACTIONS 2
 
 static bool
-GetGroupIndex(KeyInfo *key, struct xkb_keymap *keymap,
+GetGroupIndex(KeyInfo *keyi, struct xkb_keymap *keymap,
               ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn)
 {
     const char *name;
@@ -903,32 +820,28 @@ GetGroupIndex(KeyInfo *key, struct xkb_keymap *keymap,
     else
         name = "actions";
 
-    if (arrayNdx == NULL)
-    {
+    if (arrayNdx == NULL) {
         int i;
         unsigned defined;
         if (what == SYMBOLS)
-            defined = key->symsDefined;
+            defined = keyi->symsDefined;
         else
-            defined = key->actsDefined;
+            defined = keyi->actsDefined;
 
-        for (i = 0; i < XkbNumKbdGroups; i++)
-        {
-            if ((defined & (1 << i)) == 0)
-            {
+        for (i = 0; i < XkbNumKbdGroups; i++) {
+            if ((defined & (1 << i)) == 0) {
                 *ndx_rtrn = i;
                 return true;
             }
         }
         ERROR("Too many groups of %s for key %s (max %d)\n", name,
-               longText(key->name), XkbNumKbdGroups + 1);
+              longText(keyi->name), XkbNumKbdGroups + 1);
         ACTION("Ignoring %s defined for extra groups\n", name);
         return false;
     }
-    if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp))
-    {
+    if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp)) {
         ERROR("Illegal group index for %s of key %s\n", name,
-               longText(key->name));
+              longText(keyi->name));
         ACTION("Definition with non-integer array index ignored\n");
         return false;
     }
@@ -937,87 +850,88 @@ GetGroupIndex(KeyInfo *key, struct xkb_keymap *keymap,
 }
 
 static bool
-AddSymbolsToKey(KeyInfo *key, struct xkb_keymap *keymap,
+AddSymbolsToKey(KeyInfo *keyi, struct xkb_keymap *keymap,
                 ExprDef *arrayNdx, ExprDef *value, SymbolsInfo *info)
 {
     unsigned ndx, nSyms, nLevels;
     unsigned int i;
     long j;
 
-    if (!GetGroupIndex(key, keymap, arrayNdx, SYMBOLS, &ndx))
+    if (!GetGroupIndex(keyi, keymap, arrayNdx, SYMBOLS, &ndx))
         return false;
-    if (value == NULL)
-    {
-        key->symsDefined |= (1 << ndx);
+    if (value == NULL) {
+        keyi->symsDefined |= (1 << ndx);
         return true;
     }
-    if (value->op != ExprKeysymList)
-    {
+    if (value->op != ExprKeysymList) {
         ERROR("Expected a list of symbols, found %s\n", exprOpText(value->op));
         ACTION("Ignoring symbols for group %d of %s\n", ndx + 1,
-                longText(key->name));
+               longText(keyi->name));
         return false;
     }
-    if (!darray_empty(key->syms[ndx]))
-    {
+    if (!darray_empty(keyi->syms[ndx])) {
         ERROR("Symbols for key %s, group %d already defined\n",
-               longText(key->name), ndx + 1);
+               longText(keyi->name), ndx + 1);
         ACTION("Ignoring duplicate definition\n");
         return false;
     }
     nSyms = darray_size(value->value.list.syms);
     nLevels = darray_size(value->value.list.symsMapIndex);
-    if ((key->numLevels[ndx] < nSyms || darray_empty(key->syms[ndx])) &&
-        (!ResizeKeyGroup(key, ndx, nLevels, nSyms, false)))
-    {
+    if ((keyi->numLevels[ndx] < nSyms || darray_empty(keyi->syms[ndx])) &&
+        (!ResizeKeyGroup(keyi, ndx, nLevels, nSyms, false))) {
         WSGO("Could not resize group %d of key %s to contain %d levels\n",
-             ndx + 1, longText(key->name), nSyms);
+             ndx + 1, longText(keyi->name), nSyms);
         ACTION("Symbols lost\n");
         return false;
     }
-    key->symsDefined |= (1 << ndx);
+    keyi->symsDefined |= (1 << ndx);
     for (i = 0; i < nLevels; i++) {
-        darray_item(key->symsMapIndex[ndx], i) =
+        darray_item(keyi->symsMapIndex[ndx], i) =
             darray_item(value->value.list.symsMapIndex, i);
-        darray_item(key->symsMapNumEntries[ndx], i) =
+        darray_item(keyi->symsMapNumEntries[ndx], i) =
             darray_item(value->value.list.symsNumEntries, i);
 
-        for (j = 0; j < darray_item(key->symsMapNumEntries[ndx], i); j++) {
+        for (j = 0; j < darray_item(keyi->symsMapNumEntries[ndx], i); j++) {
             /* FIXME: What's abort() doing here? */
-            if (darray_item(key->symsMapIndex[ndx], i) + j >= nSyms)
+            if (darray_item(keyi->symsMapIndex[ndx], i) + j >= nSyms)
                 abort();
             if (!LookupKeysym(darray_item(value->value.list.syms,
-                                          darray_item(value->value.list.symsMapIndex, i) + j),
-                              &darray_item(key->syms[ndx],
-                                           darray_item(key->symsMapIndex[ndx], i) + j))) {
-                WARN("Could not resolve keysym %s for key %s, group %d (%s), level %d\n",
-                     darray_item(value->value.list.syms, i),
-                     longText(key->name),
-                     ndx + 1,
-                     xkb_atom_text(keymap->ctx, info->groupNames[ndx]), nSyms);
+                                          darray_item(value->value.list.symsMapIndex,
+                                                      i) + j),
+                              &darray_item(keyi->syms[ndx],
+                                           darray_item(keyi->symsMapIndex[ndx],
+                                                       i) + j))) {
+                WARN(
+                    "Could not resolve keysym %s for key %s, group %d (%s), level %d\n",
+                    darray_item(value->value.list.syms, i),
+                    longText(keyi->name),
+                    ndx + 1,
+                    xkb_atom_text(keymap->ctx, info->groupNames[ndx]), nSyms);
                 while (--j >= 0)
-                    darray_item(key->syms[ndx],
-                                darray_item(key->symsMapIndex[ndx], i) + j) = XKB_KEY_NoSymbol;
-                darray_item(key->symsMapIndex[ndx], i) = -1;
-                darray_item(key->symsMapNumEntries[ndx], i) = 0;
+                    darray_item(keyi->syms[ndx],
+                                darray_item(keyi->symsMapIndex[ndx],
+                                            i) + j) = XKB_KEY_NoSymbol;
+                darray_item(keyi->symsMapIndex[ndx], i) = -1;
+                darray_item(keyi->symsMapNumEntries[ndx], i) = 0;
                 break;
             }
-            if (darray_item(key->symsMapNumEntries[ndx], i) == 1 &&
-                darray_item(key->syms[ndx],
-                            darray_item(key->symsMapIndex[ndx], i) + j) == XKB_KEY_NoSymbol) {
-                darray_item(key->symsMapIndex[ndx], i) = -1;
-                darray_item(key->symsMapNumEntries[ndx], i) = 0;
+            if (darray_item(keyi->symsMapNumEntries[ndx], i) == 1 &&
+                darray_item(keyi->syms[ndx],
+                            darray_item(keyi->symsMapIndex[ndx],
+                                        i) + j) == XKB_KEY_NoSymbol) {
+                darray_item(keyi->symsMapIndex[ndx], i) = -1;
+                darray_item(keyi->symsMapNumEntries[ndx], i) = 0;
             }
         }
     }
-    for (j = key->numLevels[ndx] - 1;
-         j >= 0 && darray_item(key->symsMapNumEntries[ndx], j) == 0; j--)
-        key->numLevels[ndx]--;
+    for (j = keyi->numLevels[ndx] - 1;
+         j >= 0 && darray_item(keyi->symsMapNumEntries[ndx], j) == 0; j--)
+        keyi->numLevels[ndx]--;
     return true;
 }
 
 static bool
-AddActionsToKey(KeyInfo *key, struct xkb_keymap *keymap, ExprDef *arrayNdx,
+AddActionsToKey(KeyInfo *keyi, struct xkb_keymap *keymap, ExprDef *arrayNdx,
                 ExprDef *value, SymbolsInfo *info)
 {
     unsigned int i;
@@ -1025,54 +939,46 @@ AddActionsToKey(KeyInfo *key, struct xkb_keymap *keymap, ExprDef *arrayNdx,
     ExprDef *act;
     struct xkb_any_action *toAct;
 
-    if (!GetGroupIndex(key, keymap, arrayNdx, ACTIONS, &ndx))
+    if (!GetGroupIndex(keyi, keymap, arrayNdx, ACTIONS, &ndx))
         return false;
 
-    if (value == NULL)
-    {
-        key->actsDefined |= (1 << ndx);
+    if (value == NULL) {
+        keyi->actsDefined |= (1 << ndx);
         return true;
     }
-    if (value->op != ExprActionList)
-    {
+    if (value->op != ExprActionList) {
         WSGO("Bad expression type (%d) for action list value\n", value->op);
         ACTION("Ignoring actions for group %d of %s\n", ndx,
-                longText(key->name));
+               longText(keyi->name));
         return false;
     }
-    if (!darray_empty(key->acts[ndx]))
-    {
+    if (!darray_empty(keyi->acts[ndx])) {
         WSGO("Actions for key %s, group %d already defined\n",
-              longText(key->name), ndx);
+             longText(keyi->name), ndx);
         return false;
     }
-    for (nActs = 0, act = value->value.child; act != NULL; nActs++)
-    {
+    for (nActs = 0, act = value->value.child; act != NULL; nActs++) {
         act = (ExprDef *) act->common.next;
     }
-    if (nActs < 1)
-    {
+    if (nActs < 1) {
         WSGO("Action list but not actions in AddActionsToKey\n");
         return false;
     }
-    if ((key->numLevels[ndx] < nActs || darray_empty(key->acts[ndx])) &&
-        !ResizeKeyGroup(key, ndx, nActs, nActs, true))
-    {
+    if ((keyi->numLevels[ndx] < nActs || darray_empty(keyi->acts[ndx])) &&
+        !ResizeKeyGroup(keyi, ndx, nActs, nActs, true)) {
         WSGO("Could not resize group %d of key %s\n", ndx,
-              longText(key->name));
+              longText(keyi->name));
         ACTION("Actions lost\n");
         return false;
     }
-    key->actsDefined |= (1 << ndx);
+    keyi->actsDefined |= (1 << ndx);
 
-    toAct = (struct xkb_any_action *) darray_mem(key->acts[ndx], 0);
+    toAct = (struct xkb_any_action *) darray_mem(keyi->acts[ndx], 0);
     act = value->value.child;
-    for (i = 0; i < nActs; i++, toAct++)
-    {
-        if (!HandleActionDef(act, keymap, toAct, info->action))
-        {
+    for (i = 0; i < nActs; i++, toAct++) {
+        if (!HandleActionDef(act, keymap, toAct, info->action)) {
             ERROR("Illegal action definition for %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
         }
         act = (ExprDef *) act->common.next;
@@ -1081,173 +987,155 @@ AddActionsToKey(KeyInfo *key, struct xkb_keymap *keymap, ExprDef *arrayNdx,
 }
 
 static const LookupEntry lockingEntries[] = {
-    {"true", XkbKB_Lock},
-    {"yes", XkbKB_Lock},
-    {"on", XkbKB_Lock},
-    {"false", XkbKB_Default},
-    {"no", XkbKB_Default},
-    {"off", XkbKB_Default},
-    {"permanent", XkbKB_Lock | XkbKB_Permanent},
-    {NULL, 0}
+    { "true", XkbKB_Lock },
+    { "yes", XkbKB_Lock },
+    { "on", XkbKB_Lock },
+    { "false", XkbKB_Default },
+    { "no", XkbKB_Default },
+    { "off", XkbKB_Default },
+    { "permanent", XkbKB_Lock | XkbKB_Permanent },
+    { NULL, 0 }
 };
 
 static const LookupEntry repeatEntries[] = {
-    {"true", RepeatYes},
-    {"yes", RepeatYes},
-    {"on", RepeatYes},
-    {"false", RepeatNo},
-    {"no", RepeatNo},
-    {"off", RepeatNo},
-    {"default", RepeatUndefined},
-    {NULL, 0}
+    { "true", RepeatYes },
+    { "yes", RepeatYes },
+    { "on", RepeatYes },
+    { "false", RepeatNo },
+    { "no", RepeatNo },
+    { "off", RepeatNo },
+    { "default", RepeatUndefined },
+    { NULL, 0 }
 };
 
 static bool
-SetSymbolsField(KeyInfo *key, struct xkb_keymap *keymap, char *field,
+SetSymbolsField(KeyInfo *keyi, struct xkb_keymap *keymap, char *field,
                 ExprDef *arrayNdx, ExprDef *value, SymbolsInfo *info)
 {
     bool ok = true;
     ExprResult tmp;
 
-    if (strcasecmp(field, "type") == 0)
-    {
+    if (strcasecmp(field, "type") == 0) {
         ExprResult ndx;
         if ((!ExprResolveString(keymap->ctx, value, &tmp))
-            && (warningLevel > 0))
-        {
+            && (warningLevel > 0)) {
             WARN("The type field of a key symbol map must be a string\n");
             ACTION("Ignoring illegal type definition\n");
         }
-        if (arrayNdx == NULL)
-        {
-            key->dfltType = xkb_atom_intern(keymap->ctx, tmp.str);
-            key->defs.defined |= _Key_Type_Dflt;
+        if (arrayNdx == NULL) {
+            keyi->dfltType = xkb_atom_intern(keymap->ctx, tmp.str);
+            keyi->defs.defined |= _Key_Type_Dflt;
         }
-        else if (!ExprResolveGroup(keymap->ctx, arrayNdx, &ndx))
-        {
+        else if (!ExprResolveGroup(keymap->ctx, arrayNdx, &ndx)) {
             ERROR("Illegal group index for type of key %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Definition with non-integer array index ignored\n");
             free(tmp.str);
             return false;
         }
-        else
-        {
-            key->types[ndx.uval - 1] = xkb_atom_intern(keymap->ctx, tmp.str);
-            key->typesDefined |= (1 << (ndx.uval - 1));
+        else {
+            keyi->types[ndx.uval - 1] = xkb_atom_intern(keymap->ctx, tmp.str);
+            keyi->typesDefined |= (1 << (ndx.uval - 1));
         }
         free(tmp.str);
     }
     else if (strcasecmp(field, "symbols") == 0)
-        return AddSymbolsToKey(key, keymap, arrayNdx, value, info);
+        return AddSymbolsToKey(keyi, keymap, arrayNdx, value, info);
     else if (strcasecmp(field, "actions") == 0)
-        return AddActionsToKey(key, keymap, arrayNdx, value, info);
+        return AddActionsToKey(keyi, keymap, arrayNdx, value, info);
     else if ((strcasecmp(field, "vmods") == 0) ||
              (strcasecmp(field, "virtualmods") == 0) ||
-             (strcasecmp(field, "virtualmodifiers") == 0))
-    {
+             (strcasecmp(field, "virtualmodifiers") == 0)) {
         ok = ExprResolveVModMask(value, &tmp, keymap);
-        if (ok)
-        {
-            key->vmodmap = (tmp.uval >> 8);
-            key->defs.defined |= _Key_VModMap;
+        if (ok) {
+            keyi->vmodmap = (tmp.uval >> 8);
+            keyi->defs.defined |= _Key_VModMap;
         }
-        else
-        {
+        else {
             ERROR("Expected a virtual modifier mask, found %s\n",
-                   exprOpText(value->op));
+                  exprOpText(value->op));
             ACTION("Ignoring virtual modifiers definition for key %s\n",
-                    longText(key->name));
+                   longText(keyi->name));
         }
     }
     else if ((strcasecmp(field, "locking") == 0) ||
              (strcasecmp(field, "lock") == 0) ||
-             (strcasecmp(field, "locks") == 0))
-    {
+             (strcasecmp(field, "locks") == 0)) {
         ok = ExprResolveEnum(keymap->ctx, value, &tmp, lockingEntries);
         if (ok)
-            key->behavior.type = tmp.uval;
-        key->defs.defined |= _Key_Behavior;
+            keyi->behavior.type = tmp.uval;
+        keyi->defs.defined |= _Key_Behavior;
     }
     else if ((strcasecmp(field, "radiogroup") == 0) ||
              (strcasecmp(field, "permanentradiogroup") == 0) ||
-             (strcasecmp(field, "allownone") == 0))
-    {
+             (strcasecmp(field, "allownone") == 0)) {
         ERROR("Radio groups not supported\n");
-        ACTION("Ignoring radio group specification for key %s\n", longText(key->name));
+        ACTION("Ignoring radio group specification for key %s\n",
+               longText(keyi->name));
         return false;
     }
     else if (uStrCasePrefix("overlay", field) ||
-             uStrCasePrefix("permanentoverlay", field))
-    {
+             uStrCasePrefix("permanentoverlay", field)) {
         ERROR("Overlays not supported\n");
-        ACTION("Ignoring overlay specification for key %s\n", longText(key->name));
+        ACTION("Ignoring overlay specification for key %s\n",
+               longText(keyi->name));
     }
     else if ((strcasecmp(field, "repeating") == 0) ||
              (strcasecmp(field, "repeats") == 0) ||
-             (strcasecmp(field, "repeat") == 0))
-    {
+             (strcasecmp(field, "repeat") == 0)) {
         ok = ExprResolveEnum(keymap->ctx, value, &tmp, repeatEntries);
-        if (!ok)
-        {
+        if (!ok) {
             ERROR("Illegal repeat setting for %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Non-boolean repeat setting ignored\n");
             return false;
         }
-        key->repeat = tmp.uval;
-        key->defs.defined |= _Key_Repeat;
+        keyi->repeat = tmp.uval;
+        keyi->defs.defined |= _Key_Repeat;
     }
     else if ((strcasecmp(field, "groupswrap") == 0) ||
-             (strcasecmp(field, "wrapgroups") == 0))
-    {
+             (strcasecmp(field, "wrapgroups") == 0)) {
         ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
-        if (!ok)
-        {
+        if (!ok) {
             ERROR("Illegal groupsWrap setting for %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Non-boolean value ignored\n");
             return false;
         }
         if (tmp.uval)
-            key->groupInfo = XkbWrapIntoRange;
+            keyi->out_of_range_group_action = XkbWrapIntoRange;
         else
-            key->groupInfo = XkbClampIntoRange;
-        key->defs.defined |= _Key_GroupInfo;
+            keyi->out_of_range_group_action = XkbClampIntoRange;
+        keyi->defs.defined |= _Key_GroupInfo;
     }
     else if ((strcasecmp(field, "groupsclamp") == 0) ||
-             (strcasecmp(field, "clampgroups") == 0))
-    {
+             (strcasecmp(field, "clampgroups") == 0)) {
         ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
-        if (!ok)
-        {
+        if (!ok) {
             ERROR("Illegal groupsClamp setting for %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Non-boolean value ignored\n");
             return false;
         }
         if (tmp.uval)
-            key->groupInfo = XkbClampIntoRange;
+            keyi->out_of_range_group_action = XkbClampIntoRange;
         else
-            key->groupInfo = XkbWrapIntoRange;
-        key->defs.defined |= _Key_GroupInfo;
+            keyi->out_of_range_group_action = XkbWrapIntoRange;
+        keyi->defs.defined |= _Key_GroupInfo;
     }
     else if ((strcasecmp(field, "groupsredirect") == 0) ||
-             (strcasecmp(field, "redirectgroups") == 0))
-    {
-        if (!ExprResolveGroup(keymap->ctx, value, &tmp))
-        {
+             (strcasecmp(field, "redirectgroups") == 0)) {
+        if (!ExprResolveGroup(keymap->ctx, value, &tmp)) {
             ERROR("Illegal group index for redirect of key %s\n",
-                   longText(key->name));
+                  longText(keyi->name));
             ACTION("Definition with non-integer group ignored\n");
             return false;
         }
-        key->groupInfo =
-            XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
-        key->defs.defined |= _Key_GroupInfo;
+        keyi->out_of_range_group_action = XkbRedirectIntoRange;
+        keyi->out_of_range_group_number = tmp.uval - 1;
+        keyi->defs.defined |= _Key_GroupInfo;
     }
-    else
-    {
+    else {
         ERROR("Unknown field %s in a symbol interpretation\n", field);
         ACTION("Definition ignored\n");
         ok = false;
@@ -1261,20 +1149,17 @@ SetGroupName(SymbolsInfo *info, struct xkb_keymap *keymap, ExprDef *arrayNdx,
 {
     ExprResult tmp, name;
 
-    if ((arrayNdx == NULL) && (warningLevel > 0))
-    {
+    if ((arrayNdx == NULL) && (warningLevel > 0)) {
         WARN("You must specify an index when specifying a group name\n");
         ACTION("Group name definition without array subscript ignored\n");
         return false;
     }
-    if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp))
-    {
+    if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp)) {
         ERROR("Illegal index in group name definition\n");
         ACTION("Definition with non-integer array index ignored\n");
         return false;
     }
-    if (!ExprResolveString(keymap->ctx, value, &name))
-    {
+    if (!ExprResolveString(keymap->ctx, value, &name)) {
         ERROR("Group name must be a string\n");
         ACTION("Illegal name for group %d ignored\n", tmp.uval);
         return false;
@@ -1295,43 +1180,38 @@ HandleSymbolsVar(VarDef *stmt, struct xkb_keymap *keymap, SymbolsInfo *info)
 
     if (ExprResolveLhs(keymap, stmt->name, &elem, &field, &arrayNdx) == 0)
         return 0;               /* internal error, already reported */
-    if (elem.str && (strcasecmp(elem.str, "key") == 0))
-    {
+    if (elem.str && (strcasecmp(elem.str, "key") == 0)) {
         ret = SetSymbolsField(&info->dflt, keymap, field.str, arrayNdx,
                               stmt->value, info);
     }
     else if ((elem.str == NULL) && ((strcasecmp(field.str, "name") == 0) ||
                                     (strcasecmp(field.str, "groupname") ==
-                                     0)))
-    {
+                                     0))) {
         ret = SetGroupName(info, keymap, arrayNdx, stmt->value);
     }
     else if ((elem.str == NULL)
              && ((strcasecmp(field.str, "groupswrap") == 0) ||
-                 (strcasecmp(field.str, "wrapgroups") == 0)))
-    {
+                 (strcasecmp(field.str, "wrapgroups") == 0))) {
         ERROR("Global \"groupswrap\" not supported\n");
         ACTION("Ignored\n");
         ret = true;
     }
     else if ((elem.str == NULL)
              && ((strcasecmp(field.str, "groupsclamp") == 0) ||
-                 (strcasecmp(field.str, "clampgroups") == 0)))
-    {
+                 (strcasecmp(field.str, "clampgroups") == 0))) {
         ERROR("Global \"groupsclamp\" not supported\n");
         ACTION("Ignored\n");
         ret = true;
     }
     else if ((elem.str == NULL)
              && ((strcasecmp(field.str, "groupsredirect") == 0) ||
-                 (strcasecmp(field.str, "redirectgroups") == 0)))
-    {
+                 (strcasecmp(field.str, "redirectgroups") == 0))) {
         ERROR("Global \"groupsredirect\" not supported\n");
         ACTION("Ignored\n");
         ret = true;
     }
-    else if ((elem.str == NULL) && (strcasecmp(field.str, "allownone") == 0))
-    {
+    else if ((elem.str == NULL) &&
+             (strcasecmp(field.str, "allownone") == 0)) {
         ERROR("Radio groups not supported\n");
         ACTION("Ignoring \"allownone\" specification\n");
         ret = true;
@@ -1347,24 +1227,20 @@ HandleSymbolsVar(VarDef *stmt, struct xkb_keymap *keymap, SymbolsInfo *info)
 }
 
 static bool
-HandleSymbolsBody(VarDef *def, struct xkb_keymap *keymap, KeyInfo *key,
+HandleSymbolsBody(VarDef *def, struct xkb_keymap *keymap, KeyInfo *keyi,
                   SymbolsInfo *info)
 {
     bool ok = true;
     ExprResult tmp, field;
     ExprDef *arrayNdx;
 
-    for (; def != NULL; def = (VarDef *) def->common.next)
-    {
-        if ((def->name) && (def->name->type == ExprFieldRef))
-        {
+    for (; def != NULL; def = (VarDef *) def->common.next) {
+        if ((def->name) && (def->name->type == ExprFieldRef)) {
             ok = HandleSymbolsVar(def, keymap, info);
             continue;
         }
-        else
-        {
-            if (def->name == NULL)
-            {
+        else {
+            if (def->name == NULL) {
                 if ((def->value == NULL)
                     || (def->value->op == ExprKeysymList))
                     field.str = strdup("symbols");
@@ -1372,13 +1248,12 @@ HandleSymbolsBody(VarDef *def, struct xkb_keymap *keymap, KeyInfo *key,
                     field.str = strdup("actions");
                 arrayNdx = NULL;
             }
-            else
-            {
+            else {
                 ok = ExprResolveLhs(keymap, def->name, &tmp, &field,
                                     &arrayNdx);
             }
             if (ok)
-                ok = SetSymbolsField(key, keymap, field.str, arrayNdx,
+                ok = SetSymbolsField(keyi, keymap, field.str, arrayNdx,
                                      def->value, info);
             free(field.str);
         }
@@ -1387,42 +1262,40 @@ HandleSymbolsBody(VarDef *def, struct xkb_keymap *keymap, KeyInfo *key,
 }
 
 static bool
-SetExplicitGroup(SymbolsInfo *info, KeyInfo *key)
+SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
 {
     unsigned group = info->explicit_group;
 
     if (group == 0)
         return true;
 
-    if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1)
-    {
+    if ((keyi->typesDefined | keyi->symsDefined | keyi->actsDefined) & ~1) {
         int i;
         WARN("For the map %s an explicit group specified\n", info->name);
         WARN("but key %s has more than one group defined\n",
-              longText(key->name));
+             longText(keyi->name));
         ACTION("All groups except first one will be ignored\n");
-        for (i = 1; i < XkbNumKbdGroups; i++)
-        {
-            key->numLevels[i] = 0;
-            darray_free(key->syms[i]);
-            darray_free(key->acts[i]);
-            key->types[i] = 0;
-        }
-    }
-    key->typesDefined = key->symsDefined = key->actsDefined = 1 << group;
-
-    key->numLevels[group] = key->numLevels[0];
-    key->numLevels[0] = 0;
-    key->syms[group] = key->syms[0];
-    darray_init(key->syms[0]);
-    key->symsMapIndex[group] = key->symsMapIndex[0];
-    darray_init(key->symsMapIndex[0]);
-    key->symsMapNumEntries[group] = key->symsMapNumEntries[0];
-    darray_init(key->symsMapNumEntries[0]);
-    key->acts[group] = key->acts[0];
-    darray_init(key->acts[0]);
-    key->types[group] = key->types[0];
-    key->types[0] = 0;
+        for (i = 1; i < XkbNumKbdGroups; i++) {
+            keyi->numLevels[i] = 0;
+            darray_free(keyi->syms[i]);
+            darray_free(keyi->acts[i]);
+            keyi->types[i] = 0;
+        }
+    }
+    keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 1 << group;
+
+    keyi->numLevels[group] = keyi->numLevels[0];
+    keyi->numLevels[0] = 0;
+    keyi->syms[group] = keyi->syms[0];
+    darray_init(keyi->syms[0]);
+    keyi->symsMapIndex[group] = keyi->symsMapIndex[0];
+    darray_init(keyi->symsMapIndex[0]);
+    keyi->symsMapNumEntries[group] = keyi->symsMapNumEntries[0];
+    darray_init(keyi->symsMapNumEntries[0]);
+    keyi->acts[group] = keyi->acts[0];
+    darray_init(keyi->acts[0]);
+    keyi->types[group] = keyi->types[0];
+    keyi->types[0] = 0;
     return true;
 }
 
@@ -1430,26 +1303,23 @@ static int
 HandleSymbolsDef(SymbolsDef *stmt, struct xkb_keymap *keymap,
                  SymbolsInfo *info)
 {
-    KeyInfo key;
+    KeyInfo keyi;
 
-    InitKeyInfo(&key, info->file_id);
-    CopyKeyInfo(&info->dflt, &key, false);
-    key.defs.merge = stmt->merge;
-    key.name = KeyNameToLong(stmt->keyName);
-    if (!HandleSymbolsBody((VarDef *) stmt->symbols, keymap, &key, info))
-    {
+    InitKeyInfo(&keyi, info->file_id);
+    CopyKeyInfo(&info->dflt, &keyi, false);
+    keyi.defs.merge = stmt->merge;
+    keyi.name = KeyNameToLong(stmt->keyName);
+    if (!HandleSymbolsBody((VarDef *) stmt->symbols, keymap, &keyi, info)) {
         info->errorCount++;
         return false;
     }
 
-    if (!SetExplicitGroup(info, &key))
-    {
+    if (!SetExplicitGroup(info, &keyi)) {
         info->errorCount++;
         return false;
     }
 
-    if (!AddKeySymbols(info, &key, keymap))
-    {
+    if (!AddKeySymbols(info, &keyi, keymap)) {
         info->errorCount++;
         return false;
     }
@@ -1464,32 +1334,27 @@ HandleModMapDef(ModMapDef *def, struct xkb_keymap *keymap, SymbolsInfo *info)
     ExprResult rtrn;
     bool ok;
 
-    if (!LookupModIndex(keymap->ctx, NULL, def->modifier, TypeInt, &rtrn))
-    {
+    if (!LookupModIndex(keymap->ctx, NULL, def->modifier, TypeInt, &rtrn)) {
         ERROR("Illegal modifier map definition\n");
         ACTION("Ignoring map for non-modifier \"%s\"\n",
-                xkb_atom_text(keymap->ctx, def->modifier));
+               xkb_atom_text(keymap->ctx, def->modifier));
         return false;
     }
     ok = true;
     tmp.modifier = rtrn.uval;
-    for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next)
-    {
-        if ((key->op == ExprValue) && (key->type == TypeKeyName))
-        {
+    for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
+        if ((key->op == ExprValue) && (key->type == TypeKeyName)) {
             tmp.haveSymbol = false;
             tmp.u.keyName = KeyNameToLong(key->value.keyName);
         }
-        else if (ExprResolveKeySym(keymap->ctx, key, &rtrn))
-        {
+        else if (ExprResolveKeySym(keymap->ctx, key, &rtrn)) {
             tmp.haveSymbol = true;
             tmp.u.keySym = rtrn.uval;
         }
-        else
-        {
+        else {
             ERROR("Modmap entries may contain only key names or keysyms\n");
             ACTION("Illegal definition for %s modifier ignored\n",
-                    XkbcModIndexText(tmp.modifier));
+                   XkbcModIndexText(tmp.modifier));
             continue;
         }
 
@@ -1509,8 +1374,7 @@ HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
     stmt = file->defs;
     while (stmt)
     {
-        switch (stmt->stmtType)
-        {
+        switch (stmt->stmtType) {
         case StmtInclude:
             if (!HandleIncludeSymbols((IncludeStmt *) stmt, keymap, info))
                 info->errorCount++;
@@ -1543,12 +1407,11 @@ HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
             break;
         default:
             WSGO("Unexpected statement type %d in HandleSymbolsFile\n",
-                  stmt->stmtType);
+                 stmt->stmtType);
             break;
         }
         stmt = stmt->next;
-        if (info->errorCount > 10)
-        {
+        if (info->errorCount > 10) {
 #ifdef NOISY
             ERROR("Too many errors\n");
 #endif
@@ -1559,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.
@@ -1569,22 +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 key;
+    struct xkb_key *key, *ret = NULL;
     unsigned int group, level, min_group = UINT_MAX, min_level = UINT_MAX;
 
-    for (key = keymap->min_key_code; key <= keymap->max_key_code; key++)
-    {
-        for (group = 0; group < XkbKeyNumGroups(keymap, key); 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, key, group, level) != 1 ||
-                    (XkbKeySymEntry(keymap, key, group, level))[0] != sym)
+                 level++) {
+                if (XkbKeyNumSyms(key, group, level) != 1 ||
+                    (XkbKeySymEntry(key, group, level))[0] != sym)
                     continue;
 
                 /*
@@ -1594,10 +1452,11 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym,
                  */
                 if (group < min_group ||
                     (group == min_group && level < min_level)) {
-                    *kc_rtrn = key;
+                    ret = key;
                     if (group == 0 && level == 0) {
-                        return true;
-                    } else {
+                        return ret;
+                    }
+                    else {
                         min_group = group;
                         min_level = level;
                     }
@@ -1606,7 +1465,7 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym,
         }
     }
 
-    return min_group != UINT_MAX;
+    return ret;
 }
 
 /**
@@ -1624,8 +1483,8 @@ FindNamedType(struct xkb_keymap *keymap, xkb_atom_t atom, unsigned *type_rtrn)
     const char *name = xkb_atom_text(keymap->ctx, atom);
     struct xkb_key_type *type;
 
-    if (keymap && keymap->map) {
-        darray_foreach(type, keymap->map->types) {
+    if (keymap) {
+        darray_foreach(type, keymap->types) {
             if (strcmp(type->name, name) == 0) {
                 *type_rtrn = n;
                 return true;
@@ -1662,32 +1521,26 @@ FindAutomaticType(struct xkb_keymap *keymap, int width,
                   bool *autoType)
 {
     *autoType = false;
-    if ((width == 1) || (width == 0))
-    {
+    if ((width == 1) || (width == 0)) {
         *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
         *autoType = true;
     }
-    else if (width == 2)
-    {
+    else if (width == 2) {
         if (syms && xkb_keysym_is_lower(syms[0]) &&
-            xkb_keysym_is_upper(syms[1]))
-        {
+            xkb_keysym_is_upper(syms[1])) {
             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
         }
         else if (syms && (xkb_keysym_is_keypad(syms[0]) ||
-                          xkb_keysym_is_keypad(syms[1])))
-        {
+                          xkb_keysym_is_keypad(syms[1]))) {
             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "KEYPAD");
             *autoType = true;
         }
-        else
-        {
+        else {
             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
             *autoType = true;
         }
     }
-    else if (width <= 4)
-    {
+    else if (width <= 4) {
         if (syms && xkb_keysym_is_lower(syms[0]) &&
             xkb_keysym_is_upper(syms[1]))
             if (xkb_keysym_is_lower(syms[2]) && xkb_keysym_is_upper(syms[3]))
@@ -1712,15 +1565,14 @@ FindAutomaticType(struct xkb_keymap *keymap, int width,
  * groups, and reduce to one group if all groups are identical anyway.
  */
 static void
-PrepareKeyDef(KeyInfo * key)
+PrepareKeyDef(KeyInfo *keyi)
 {
     int i, j, width, defined, lastGroup;
     bool identical;
 
-    defined = key->symsDefined | key->actsDefined | key->typesDefined;
+    defined = keyi->symsDefined | keyi->actsDefined | keyi->typesDefined;
     /* get highest group number */
-    for (i = XkbNumKbdGroups - 1; i >= 0; i--)
-    {
+    for (i = XkbNumKbdGroups - 1; i >= 0; i--) {
         if (defined & (1 << i))
             break;
     }
@@ -1732,101 +1584,89 @@ PrepareKeyDef(KeyInfo * key)
     /* If there are empty groups between non-empty ones fill them with data */
     /* from the first group. */
     /* We can make a wrong assumption here. But leaving gaps is worse. */
-    for (i = lastGroup; i > 0; i--)
-    {
+    for (i = lastGroup; i > 0; i--) {
         if (defined & (1 << i))
             continue;
-        width = key->numLevels[0];
-        if (key->typesDefined & 1)
-        {
-            for (j = 0; j < width; j++)
-            {
-                key->types[i] = key->types[0];
+        width = keyi->numLevels[0];
+        if (keyi->typesDefined & 1) {
+            for (j = 0; j < width; j++) {
+                keyi->types[i] = keyi->types[0];
             }
-            key->typesDefined |= 1 << i;
+            keyi->typesDefined |= 1 << i;
         }
-        if ((key->actsDefined & 1) && !darray_empty(key->acts[0]))
-        {
-            darray_copy(key->acts[i], key->acts[0]);
-            key->actsDefined |= 1 << i;
+        if ((keyi->actsDefined & 1) && !darray_empty(keyi->acts[0])) {
+            darray_copy(keyi->acts[i], keyi->acts[0]);
+            keyi->actsDefined |= 1 << i;
         }
-        if ((key->symsDefined & 1) && !darray_empty(key->syms[0]))
-        {
-            darray_copy(key->syms[i], key->syms[0]);
-            darray_copy(key->symsMapIndex[i], key->symsMapIndex[0]);
-            darray_copy(key->symsMapNumEntries[i], key->symsMapNumEntries[0]);
-            key->symsDefined |= 1 << i;
+        if ((keyi->symsDefined & 1) && !darray_empty(keyi->syms[0])) {
+            darray_copy(keyi->syms[i], keyi->syms[0]);
+            darray_copy(keyi->symsMapIndex[i], keyi->symsMapIndex[0]);
+            darray_copy(keyi->symsMapNumEntries[i],
+                        keyi->symsMapNumEntries[0]);
+            keyi->symsDefined |= 1 << i;
         }
-        if (defined & 1)
-        {
-            key->numLevels[i] = key->numLevels[0];
+        if (defined & 1) {
+            keyi->numLevels[i] = keyi->numLevels[0];
         }
     }
     /* If all groups are completely identical remove them all */
     /* exept the first one. */
     identical = true;
-    for (i = lastGroup; i > 0; i--)
-    {
-        if ((key->numLevels[i] != key->numLevels[0]) ||
-            (key->types[i] != key->types[0]))
-        {
+    for (i = lastGroup; i > 0; i--) {
+        if ((keyi->numLevels[i] != keyi->numLevels[0]) ||
+            (keyi->types[i] != keyi->types[0])) {
             identical = false;
             break;
         }
-        if (!darray_same(key->syms[i], key->syms[0]) &&
-            (darray_empty(key->syms[i]) || darray_empty(key->syms[0]) ||
-             darray_size(key->syms[i]) != darray_size(key->syms[0]) ||
-             memcmp(darray_mem(key->syms[i], 0),
-                    darray_mem(key->syms[0], 0),
-                   sizeof(xkb_keysym_t) * darray_size(key->syms[0]))))
-        {
+        if (!darray_same(keyi->syms[i], keyi->syms[0]) &&
+            (darray_empty(keyi->syms[i]) || darray_empty(keyi->syms[0]) ||
+             darray_size(keyi->syms[i]) != darray_size(keyi->syms[0]) ||
+             memcmp(darray_mem(keyi->syms[i], 0),
+                    darray_mem(keyi->syms[0], 0),
+                   sizeof(xkb_keysym_t) * darray_size(keyi->syms[0])))) {
             identical = false;
             break;
         }
-        if (!darray_same(key->symsMapIndex[i], key->symsMapIndex[0]) &&
-            (darray_empty(key->symsMapIndex[i]) ||
-             darray_empty(key->symsMapIndex[0]) ||
-             memcmp(darray_mem(key->symsMapIndex[i], 0),
-                    darray_mem(key->symsMapIndex[0], 0),
-                    key->numLevels[0] * sizeof(int))))
-        {
+        if (!darray_same(keyi->symsMapIndex[i], keyi->symsMapIndex[0]) &&
+            (darray_empty(keyi->symsMapIndex[i]) ||
+             darray_empty(keyi->symsMapIndex[0]) ||
+             memcmp(darray_mem(keyi->symsMapIndex[i], 0),
+                    darray_mem(keyi->symsMapIndex[0], 0),
+                    keyi->numLevels[0] * sizeof(int)))) {
             identical = false;
             continue;
         }
-        if (!darray_same(key->symsMapNumEntries[i], key->symsMapNumEntries[0]) &&
-            (darray_empty(key->symsMapNumEntries[i]) ||
-             darray_empty(key->symsMapNumEntries[0]) ||
-             memcmp(darray_mem(key->symsMapNumEntries[i], 0),
-                    darray_mem(key->symsMapNumEntries[0], 0),
-                    key->numLevels[0] * sizeof(size_t))))
-        {
+        if (!darray_same(keyi->symsMapNumEntries[i],
+                         keyi->symsMapNumEntries[0]) &&
+            (darray_empty(keyi->symsMapNumEntries[i]) ||
+             darray_empty(keyi->symsMapNumEntries[0]) ||
+             memcmp(darray_mem(keyi->symsMapNumEntries[i], 0),
+                    darray_mem(keyi->symsMapNumEntries[0], 0),
+                    keyi->numLevels[0] * sizeof(size_t)))) {
             identical = false;
             continue;
         }
-        if (!darray_same(key->acts[i], key->acts[0]) &&
-            (darray_empty(key->acts[i]) || darray_empty(key->acts[0]) ||
-             memcmp(darray_mem(key->acts[i], 0),
-                    darray_mem(key->acts[0], 0),
-                    key->numLevels[0] * sizeof(union xkb_action))))
-        {
+        if (!darray_same(keyi->acts[i], keyi->acts[0]) &&
+            (darray_empty(keyi->acts[i]) || darray_empty(keyi->acts[0]) ||
+             memcmp(darray_mem(keyi->acts[i], 0),
+                    darray_mem(keyi->acts[0], 0),
+                    keyi->numLevels[0] * sizeof(union xkb_action)))) {
             identical = false;
             break;
         }
     }
-    if (identical)
-    {
-        for (i = lastGroup; i > 0; i--)
-        {
-            key->numLevels[i] = 0;
-            darray_free(key->syms[i]);
-            darray_free(key->symsMapIndex[i]);
-            darray_free(key->symsMapNumEntries[i]);
-            darray_free(key->acts[i]);
-            key->types[i] = 0;
-        }
-        key->symsDefined &= 1;
-        key->actsDefined &= 1;
-        key->typesDefined &= 1;
+    if (identical) {
+        for (i = lastGroup; i > 0; i--) {
+            keyi->numLevels[i] = 0;
+            darray_free(keyi->syms[i]);
+            darray_free(keyi->symsMapIndex[i]);
+            darray_free(keyi->symsMapNumEntries[i]);
+            darray_free(keyi->acts[i]);
+            keyi->types[i] = 0;
+        }
+        keyi->symsDefined &= 1;
+        keyi->actsDefined &= 1;
+        keyi->typesDefined &= 1;
     }
 }
 
@@ -1836,10 +1676,11 @@ PrepareKeyDef(KeyInfo * key)
  * This function recurses.
  */
 static bool
-CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *key, int start_from)
+CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
 {
     unsigned int i;
     xkb_keycode_t kc;
+    struct xkb_key *key;
     unsigned int sizeSyms = 0;
     unsigned width, tmp, nGroups;
     struct xkb_key_type * type;
@@ -1847,124 +1688,101 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *key, int start_from)
     unsigned types[XkbNumKbdGroups];
     union xkb_action *outActs;
     unsigned int symIndex = 0;
-    struct xkb_sym_map *sym_map;
 
     useAlias = (start_from == 0);
 
-    /* get the keycode for the key. */
-    if (!FindNamedKey(keymap, key->name, &kc, useAlias,
-                      CreateKeyNames(keymap), start_from))
-    {
-        if ((start_from == 0) && (warningLevel >= 5))
-        {
-            WARN("Key %s not found in keycodes\n", longText(key->name));
+    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;
     }
+    kc = XkbKeyGetKeycode(keymap, key);
 
     haveActions = false;
-    for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++)
-    {
+    for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) {
         if (((i + 1) > nGroups)
-            && (((key->symsDefined | key->actsDefined) & (1 << i))
-                || (key->typesDefined) & (1 << i)))
+            && (((keyi->symsDefined | keyi->actsDefined) & (1 << i))
+                || (keyi->typesDefined) & (1 << i)))
             nGroups = i + 1;
-        if (!darray_empty(key->acts[i]))
+        if (!darray_empty(keyi->acts[i]))
             haveActions = true;
         autoType = false;
         /* Assign the type to the key, if it is missing. */
-        if (key->types[i] == XKB_ATOM_NONE)
-        {
-            if (key->dfltType != XKB_ATOM_NONE)
-                key->types[i] = key->dfltType;
-            else if (FindAutomaticType(keymap, key->numLevels[i],
-                                       darray_mem(key->syms[i], 0),
-                                       &key->types[i], &autoType))
-            {
-            }
-            else
-            {
-                if (warningLevel >= 5)
-                {
+        if (keyi->types[i] == XKB_ATOM_NONE) {
+            if (keyi->dfltType != XKB_ATOM_NONE)
+                keyi->types[i] = keyi->dfltType;
+            else if (FindAutomaticType(keymap, keyi->numLevels[i],
+                                       darray_mem(keyi->syms[i], 0),
+                                       &keyi->types[i], &autoType)) { }
+            else {
+                if (warningLevel >= 5) {
                     WARN("No automatic type for %d symbols\n",
-                          (unsigned int) key->numLevels[i]);
+                          (unsigned int) keyi->numLevels[i]);
                     ACTION("Using %s for the %s key (keycode %d)\n",
-                            xkb_atom_text(keymap->ctx, key->types[i]),
-                            longText(key->name), kc);
+                            xkb_atom_text(keymap->ctx, keyi->types[i]),
+                            longText(keyi->name), kc);
                 }
             }
         }
-        if (FindNamedType(keymap, key->types[i], &types[i]))
-        {
-            if (!autoType || key->numLevels[i] > 2)
-                keymap->server->explicit[kc] |= (1 << i);
+        if (FindNamedType(keymap, keyi->types[i], &types[i])) {
+            if (!autoType || keyi->numLevels[i] > 2)
+                key->explicit |= (1 << i);
         }
-        else
-        {
-            if (warningLevel >= 3)
-            {
+        else {
+            if (warningLevel >= 3) {
                 WARN("Type \"%s\" is not defined\n",
-                      xkb_atom_text(keymap->ctx, key->types[i]));
+                     xkb_atom_text(keymap->ctx, keyi->types[i]));
                 ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n",
-                        longText(key->name), kc);
+                       longText(keyi->name), kc);
             }
             types[i] = XkbTwoLevelIndex;
         }
         /* if the type specifies fewer levels than the key has, shrink the key */
-        type = &darray_item(keymap->map->types, types[i]);
-        if (type->num_levels < key->numLevels[i])
-        {
-            if (warningLevel > 0)
-            {
+        type = &darray_item(keymap->types, types[i]);
+        if (type->num_levels < keyi->numLevels[i]) {
+            if (warningLevel > 0) {
                 WARN("Type \"%s\" has %d levels, but %s has %d symbols\n",
                      type->name, type->num_levels,
-                     xkb_atom_text(keymap->ctx, key->name), key->numLevels[i]);
+                     xkb_atom_text(keymap->ctx, keyi->name), keyi->numLevels[i]);
                 ACTION("Ignoring extra symbols\n");
             }
-            key->numLevels[i] = type->num_levels;
+            keyi->numLevels[i] = type->num_levels;
         }
-        if (key->numLevels[i] > width)
-            width = key->numLevels[i];
+        if (keyi->numLevels[i] > width)
+            width = keyi->numLevels[i];
         if (type->num_levels > width)
             width = type->num_levels;
-        sizeSyms += darray_size(key->syms[i]);
+        sizeSyms += darray_size(keyi->syms[i]);
     }
 
-    if (!XkbcResizeKeySyms(keymap, kc, sizeSyms))
-    {
-        WSGO("Could not enlarge symbols for %s (keycode %d)\n",
-              longText(key->name), kc);
-        return false;
-    }
-    if (haveActions)
-    {
-        outActs = XkbcResizeKeyActions(keymap, kc, width * nGroups);
-        if (outActs == NULL)
-        {
+    darray_resize0(key->syms, sizeSyms);
+
+    if (haveActions) {
+        outActs = XkbcResizeKeyActions(keymap, key, width * nGroups);
+        if (outActs == NULL) {
             WSGO("Could not enlarge actions for %s (key %d)\n",
-                  longText(key->name), kc);
+                 longText(keyi->name), kc);
             return false;
         }
-        keymap->server->explicit[kc] |= XkbExplicitInterpretMask;
+        key->explicit |= XkbExplicitInterpretMask;
     }
     else
         outActs = NULL;
 
-    sym_map = &darray_item(keymap->map->key_sym_map, kc);
-
-    if (key->defs.defined & _Key_GroupInfo)
-        i = key->groupInfo;
-    else
-        i = sym_map->group_info;
-
-    sym_map->group_info = XkbSetNumGroups(i, nGroups);
-    sym_map->width = width;
-    sym_map->sym_index = uTypedCalloc(nGroups * width, int);
-    sym_map->num_syms = uTypedCalloc(nGroups * width, unsigned int);
+    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 = calloc(nGroups * width, sizeof(*key->sym_index));
+    key->num_syms = calloc(nGroups * width, sizeof(*key->num_syms));
 
-    for (i = 0; i < nGroups; i++)
-    {
+    for (i = 0; i < nGroups; i++) {
         /* assign kt_index[i] to the index of the type in map->types.
          * kt_index[i] may have been set by a previous run (if we have two
          * layouts specified). Let's not overwrite it with the ONE_LEVEL
@@ -1972,102 +1790,91 @@ CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *key, int start_from)
          *
          * FIXME: There should be a better fix for this.
          */
-        if (key->numLevels[i])
-            sym_map->kt_index[i] = types[i];
-        if (!darray_empty(key->syms[i]))
-        {
+        if (keyi->numLevels[i])
+            key->kt_index[i] = types[i];
+        if (!darray_empty(keyi->syms[i])) {
             /* fill key to "width" symbols*/
-            for (tmp = 0; tmp < width; tmp++)
-            {
-                if (tmp < key->numLevels[i] &&
-                    darray_item(key->symsMapNumEntries[i], tmp) != 0)
-                {
-                    memcpy(darray_mem(sym_map->syms, symIndex),
-                           darray_mem(key->syms[i],
-                                      darray_item(key->symsMapIndex[i], tmp)),
-                           darray_item(key->symsMapNumEntries[i], tmp) * sizeof(xkb_keysym_t));
-                    sym_map->sym_index[(i * width) + tmp] = symIndex;
-                    sym_map->num_syms[(i * width) + tmp] =
-                        darray_item(key->symsMapNumEntries[i], tmp);
-                    symIndex += sym_map->num_syms[(i * width) + tmp];
+            for (tmp = 0; tmp < width; tmp++) {
+                if (tmp < keyi->numLevels[i] &&
+                    darray_item(keyi->symsMapNumEntries[i], tmp) != 0) {
+                    memcpy(darray_mem(key->syms, symIndex),
+                           darray_mem(keyi->syms[i],
+                                      darray_item(keyi->symsMapIndex[i], tmp)),
+                           darray_item(keyi->symsMapNumEntries[i],
+                                       tmp) * sizeof(xkb_keysym_t));
+                    key->sym_index[(i * width) + tmp] = symIndex;
+                    key->num_syms[(i * width) + tmp] =
+                        darray_item(keyi->symsMapNumEntries[i], tmp);
+                    symIndex += key->num_syms[(i * width) + tmp];
                 }
-                else
-                {
-                    sym_map->sym_index[(i * width) + tmp] = -1;
-                    sym_map->num_syms[(i * width) + tmp] = 0;
+                else {
+                    key->sym_index[(i * width) + tmp] = -1;
+                    key->num_syms[(i * width) + tmp] = 0;
                 }
-                if (outActs != NULL && !darray_empty(key->acts[i]))
-                {
-                    if (tmp < key->numLevels[i])
-                        outActs[tmp] = darray_item(key->acts[i], tmp);
+                if (outActs != NULL && !darray_empty(keyi->acts[i])) {
+                    if (tmp < keyi->numLevels[i])
+                        outActs[tmp] = darray_item(keyi->acts[i], tmp);
                     else
                         outActs[tmp].type = XkbSA_NoAction;
                 }
             }
         }
     }
-    switch (key->behavior.type & XkbKB_OpMask)
-    {
+    switch (keyi->behavior.type & XkbKB_OpMask) {
     case XkbKB_Default:
         break;
+
     default:
-        keymap->server->behaviors[kc] = key->behavior;
-        keymap->server->explicit[kc] |= XkbExplicitBehaviorMask;
+        key->behavior = keyi->behavior;
+        key->explicit |= XkbExplicitBehaviorMask;
         break;
     }
-    if (key->defs.defined & _Key_VModMap)
-    {
-        keymap->server->vmodmap[kc] = key->vmodmap;
-        keymap->server->explicit[kc] |= XkbExplicitVModMapMask;
+    if (keyi->defs.defined & _Key_VModMap) {
+        key->vmodmap = keyi->vmodmap;
+        key->explicit |= XkbExplicitVModMapMask;
     }
-    if (key->repeat != RepeatUndefined)
-    {
-        if (key->repeat == RepeatYes)
-            keymap->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8));
-        else
-            keymap->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
-        keymap->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
+    if (keyi->repeat != RepeatUndefined) {
+        key->repeats = keyi->repeat == RepeatYes;
+        key->explicit |= XkbExplicitAutoRepeatMask;
     }
 
-    if (nGroups > keymap->ctrls->num_groups)
-       keymap->ctrls->num_groups = nGroups;
-
     /* do the same thing for the next key */
-    CopySymbolsDef(keymap, key, kc + 1);
+    CopySymbolsDef(keymap, keyi, kc + 1);
     return true;
 }
 
 static bool
 CopyModMapDef(struct xkb_keymap *keymap, ModMapEntry *entry)
 {
-    xkb_keycode_t kc;
-
-    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));
+    struct xkb_key *key;
+
+    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;
     }
-    keymap->map->modmap[kc] |= (1 << entry->modifier);
+
+    key->modmap |= (1 << entry->modifier);
     return true;
 }
 
@@ -2079,11 +1886,13 @@ CopyModMapDef(struct xkb_keymap *keymap, ModMapEntry *entry)
  * @param merge Merge strategy (e.g. MERGE_OVERRIDE).
  */
 bool
-CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
+CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
+               enum merge_mode merge)
 {
-    unsigned int i;
+    int i;
+    struct xkb_key *key;
     SymbolsInfo info;
-    KeyInfo *key;
+    KeyInfo *keyi;
 
     InitSymbolsInfo(&info, keymap, file->id);
     info.dflt.defs.merge = merge;
@@ -2096,66 +1905,39 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
     if (info.errorCount != 0)
         goto err_info;
 
-    /* alloc memory in the xkb struct */
-    if (XkbcAllocNames(keymap, XkbGroupNamesMask, 0) != Success) {
-        WSGO("Can not allocate names in CompileSymbols\n");
-        ACTION("Symbols not added\n");
-        goto err_info;
-    }
-
-    if (XkbcAllocClientMap(keymap, XkbKeySymsMask | XkbModifierMapMask, 0)
-        != Success) {
-        WSGO("Could not allocate client map in CompileSymbols\n");
-        ACTION("Symbols not added\n");
-        goto err_info;
-    }
-
-    if (XkbcAllocServerMap(keymap, XkbAllServerInfoMask, 32) != Success) {
-        WSGO("Could not allocate server map in CompileSymbols\n");
-        ACTION("Symbols not added\n");
-        goto err_info;
-    }
-
-    if (XkbcAllocControls(keymap) != Success) {
-        WSGO("Could not allocate controls in CompileSymbols\n");
-        ACTION("Symbols not added\n");
-        goto err_info;
-    }
+    darray_resize0(keymap->acts, darray_size(keymap->acts) + 32 + 1);
 
     if (info.name)
-        keymap->names->symbols = strdup(info.name);
+        keymap->symbols_section_name = strdup(info.name);
 
     /* now copy info into xkb. */
     ApplyAliases(keymap, &info.aliases);
 
     for (i = 0; i < XkbNumKbdGroups; i++) {
         if (info.groupNames[i] != XKB_ATOM_NONE) {
-            free(keymap->names->groups[i]);
-            keymap->names->groups[i] = xkb_atom_strdup(keymap->ctx,
-                                                       info.groupNames[i]);
+            free(keymap->group_names[i]);
+            keymap->group_names[i] = xkb_atom_strdup(keymap->ctx,
+                                                     info.groupNames[i]);
         }
     }
 
     /* sanitize keys */
-    darray_foreach(key, info.keys)
-        PrepareKeyDef(key);
+    darray_foreach(keyi, info.keys)
+        PrepareKeyDef(keyi);
 
     /* copy! */
-    darray_foreach(key, info.keys)
-        if (!CopySymbolsDef(keymap, key, 0))
+    darray_foreach(keyi, info.keys)
+        if (!CopySymbolsDef(keymap, keyi, 0))
             info.errorCount++;
 
     if (warningLevel > 3) {
-        for (i = keymap->min_key_code; i <= keymap->max_key_code; i++) {
-            if (darray_item(keymap->names->keys, i).name[0] == '\0')
+        xkb_foreach_key(key, keymap) {
+            if (key->name[0] == '\0')
                 continue;
 
-            if (XkbKeyNumGroups(keymap, i) < 1) {
-                char buf[5];
-                memcpy(buf, darray_item(keymap->names->keys, i).name, 4);
-                buf[4] = '\0';
-                WARN("No symbols defined for <%s> (keycode %d)\n", buf, i);
-            }
+            if (key->num_groups < 1)
+                WARN("No symbols defined for <%.4s> (keycode %d)\n",
+                     key->name, XkbKeyGetKeycode(keymap, key));
         }
     }