Don't run the benchmark by default
[profile/ivi/libxkbcommon.git] / src / alloc.c
index fce6b8c..e782d57 100644 (file)
@@ -23,120 +23,433 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "xkballoc.h"
-#include "xkbgeom.h"
-#include "X11/extensions/XKBcommon.h"
-#include "XKBcommonint.h"
-#include <X11/extensions/XKB.h>
+#include "xkb-priv.h"
+#include "alloc.h"
 
 int
-XkbcAllocCompatMap(XkbcDescPtr xkb, unsigned which, unsigned nSI)
+XkbcAllocClientMap(struct xkb_keymap *keymap, unsigned which,
+                   unsigned nTotalTypes)
 {
-    XkbCompatMapPtr compat;
-    XkbSymInterpretRec *prev_interpret;
+    struct xkb_client_map * map;
 
-    if (!xkb)
+    if (!keymap || ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
+        return BadValue;
+
+    if (!keymap->map) {
+        map = uTypedCalloc(1, struct xkb_client_map);
+        if (!map)
+            return BadAlloc;
+        keymap->map = map;
+    }
+    else
+        map = keymap->map;
+
+    if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
+        if (!map->types) {
+            map->types = uTypedCalloc(nTotalTypes, struct xkb_key_type);
+            if (!map->types)
+                return BadAlloc;
+
+            map->num_types = 0;
+            map->size_types = nTotalTypes;
+        }
+        else if (map->size_types < nTotalTypes) {
+            struct xkb_key_type *prev_types = map->types;
+
+            map->types = uTypedRealloc(map->types, nTotalTypes,
+                                          struct xkb_key_type);
+            if (!map->types) {
+                free(prev_types);
+                map->num_types = map->size_types = 0;
+                return BadAlloc;
+            }
+
+            map->size_types = nTotalTypes;
+            memset(&map->types[map->num_types], 0,
+                   (map->size_types - map->num_types) * sizeof(struct xkb_key_type));
+        }
+    }
+
+    if (which & XkbKeySymsMask) {
+        if (!map->key_sym_map) {
+            map->key_sym_map = uTypedCalloc(keymap->max_key_code + 1,
+                                            struct xkb_sym_map);
+            if (!map->key_sym_map)
+                return BadAlloc;
+        }
+    }
+
+    if (which & XkbModifierMapMask) {
+        if (!map->modmap) {
+            map->modmap = uTypedCalloc(keymap->max_key_code + 1,
+                                       unsigned char);
+            if (!map->modmap)
+                return BadAlloc;
+        }
+    }
+
+    return Success;
+}
+
+int
+XkbcAllocServerMap(struct xkb_keymap *keymap, unsigned which,
+                   unsigned nNewActions)
+{
+    unsigned i;
+    struct xkb_server_map * map;
+
+    if (!keymap)
+        return BadMatch;
+
+    if (!keymap->server) {
+        map = uTypedCalloc(1, struct xkb_server_map);
+        if (!map)
+            return BadAlloc;
+
+        for (i = 0; i < XkbNumVirtualMods; i++)
+            map->vmods[i] = XkbNoModifierMask;
+
+        keymap->server = map;
+    }
+    else
+        map = keymap->server;
+
+    if (!which)
+        return Success;
+
+    if (!map->explicit) {
+        i = keymap->max_key_code + 1;
+        map->explicit = uTypedCalloc(i, unsigned char);
+        if (!map->explicit)
+            return BadAlloc;
+    }
+
+    if (nNewActions < 1)
+        nNewActions = 1;
+
+    if (!map->acts) {
+        map->acts = uTypedCalloc(nNewActions + 1, union xkb_action);
+        if (!map->acts)
+            return BadAlloc;
+        map->num_acts = 1;
+        map->size_acts = nNewActions + 1;
+    }
+    else if ((map->size_acts - map->num_acts) < (int)nNewActions) {
+        unsigned need;
+        union xkb_action *prev_acts = map->acts;
+
+        need = map->num_acts + nNewActions;
+        map->acts = uTypedRealloc(map->acts, need, union xkb_action);
+        if (!map->acts) {
+            free(prev_acts);
+            map->num_acts = map->size_acts = 0;
+            return BadAlloc;
+        }
+
+        map->size_acts = need;
+        memset(&map->acts[map->num_acts], 0,
+               (map->size_acts - map->num_acts) * sizeof(union xkb_action));
+    }
+
+    if (!map->key_acts) {
+        i = keymap->max_key_code + 1;
+        map->key_acts = uTypedCalloc(i, unsigned short);
+        if (!map->key_acts)
+            return BadAlloc;
+    }
+
+    if (!map->behaviors) {
+        i = keymap->max_key_code + 1;
+        map->behaviors = uTypedCalloc(i, struct xkb_behavior);
+        if (!map->behaviors)
+            return BadAlloc;
+    }
+
+    if (!map->vmodmap) {
+        i = keymap->max_key_code + 1;
+        map->vmodmap = uTypedCalloc(i, uint32_t);
+        if (!map->vmodmap)
+            return BadAlloc;
+    }
+
+    return Success;
+}
+
+int
+XkbcCopyKeyType(struct xkb_key_type * from, struct xkb_key_type * into)
+{
+    int i;
+
+    if (!from || !into)
         return BadMatch;
 
-    if (xkb->compat) {
-        if (xkb->compat->size_si >= nSI)
+    free(into->map);
+    into->map = NULL;
+    free(into->preserve);
+    into->preserve= NULL;
+    for (i = 0; i < into->num_levels; i++)
+        free(UNCONSTIFY(into->level_names[i]));
+    free(into->level_names);
+    into->level_names = NULL;
+
+    *into = *from;
+
+    if (from->map && (into->map_count > 0)) {
+        into->map = uTypedCalloc(into->map_count, struct xkb_kt_map_entry);
+        if (!into->map)
+            return BadAlloc;
+        memcpy(into->map, from->map,
+               into->map_count * sizeof(struct xkb_kt_map_entry));
+    }
+
+    if (from->preserve && (into->map_count > 0)) {
+        into->preserve = uTypedCalloc(into->map_count, struct xkb_mods);
+        if (!into->preserve)
+            return BadAlloc;
+        memcpy(into->preserve, from->preserve,
+               into->map_count * sizeof(struct xkb_mods));
+    }
+
+    if (from->level_names && (into->num_levels > 0)) {
+        into->level_names = uTypedCalloc(into->num_levels, const char *);
+        if (!into->level_names)
+            return BadAlloc;
+        for (i = 0; i < into->num_levels; i++)
+            into->level_names[i] = strdup(from->level_names[i]);
+    }
+
+    return Success;
+}
+
+bool
+XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
+                  unsigned int needed)
+{
+    if (keymap->map->key_sym_map[key].size_syms >= needed)
+        return true;
+
+    keymap->map->key_sym_map[key].syms =
+        uTypedRecalloc(keymap->map->key_sym_map[key].syms,
+                       keymap->map->key_sym_map[key].size_syms,
+                       needed,
+                       xkb_keysym_t);
+    if (!keymap->map->key_sym_map[key].syms) {
+        keymap->map->key_sym_map[key].size_syms = 0;
+        return false;
+    }
+    keymap->map->key_sym_map[key].size_syms = needed;
+
+    return true;
+}
+
+union xkb_action *
+XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
+                     uint32_t needed)
+{
+    xkb_keycode_t i, nActs;
+    union xkb_action *newActs;
+
+    if (needed == 0) {
+        keymap->server->key_acts[key] = 0;
+        return NULL;
+    }
+
+    if (XkbKeyHasActions(keymap, key) &&
+        (XkbKeyGroupsWidth(keymap, key) >= needed))
+        return XkbKeyActionsPtr(keymap, key);
+
+    if (keymap->server->size_acts - keymap->server->num_acts >= (int)needed) {
+        keymap->server->key_acts[key] = keymap->server->num_acts;
+        keymap->server->num_acts += needed;
+
+        return &keymap->server->acts[keymap->server->key_acts[key]];
+    }
+
+    keymap->server->size_acts = keymap->server->num_acts + needed + 8;
+    newActs = uTypedCalloc(keymap->server->size_acts, union xkb_action);
+    if (!newActs)
+        return NULL;
+    newActs[0].type = XkbSA_NoAction;
+    nActs = 1;
+
+    for (i = keymap->min_key_code; i <= keymap->max_key_code; i++) {
+        xkb_keycode_t nKeyActs, nCopy;
+
+        if ((keymap->server->key_acts[i] == 0) && (i != key))
+            continue;
+
+        nCopy = nKeyActs = XkbKeyNumActions(keymap, i);
+        if (i == key) {
+            nKeyActs= needed;
+            if (needed < nCopy)
+                nCopy = needed;
+        }
+
+        if (nCopy > 0)
+            memcpy(&newActs[nActs], XkbKeyActionsPtr(keymap, i),
+                   nCopy * sizeof(union xkb_action));
+        if (nCopy < nKeyActs)
+            memset(&newActs[nActs + nCopy], 0,
+                   (nKeyActs - nCopy) * sizeof(union xkb_action));
+
+        keymap->server->key_acts[i] = nActs;
+        nActs += nKeyActs;
+    }
+
+    free(keymap->server->acts);
+    keymap->server->acts = newActs;
+    keymap->server->num_acts = nActs;
+
+    return &keymap->server->acts[keymap->server->key_acts[key]];
+}
+
+void
+XkbcFreeClientMap(struct xkb_keymap *keymap)
+{
+    struct xkb_client_map * map;
+    struct xkb_key_type * type;
+    xkb_keycode_t key;
+    int i;
+
+    if (!keymap || !keymap->map)
+        return;
+
+    map = keymap->map;
+
+    for (i = 0, type = map->types; i < map->num_types && type; i++, type++) {
+        int j;
+        free(type->map);
+        free(type->preserve);
+        for (j = 0; j < type->num_levels; j++)
+            free(UNCONSTIFY(type->level_names[j]));
+        free(type->level_names);
+        free(UNCONSTIFY(type->name));
+    }
+    free(map->types);
+
+    if (map->key_sym_map) {
+        for (key = keymap->min_key_code; key < keymap->max_key_code; key++) {
+            free(map->key_sym_map[key].sym_index);
+            free(map->key_sym_map[key].num_syms);
+            free(map->key_sym_map[key].syms);
+        }
+    }
+    free(map->key_sym_map);
+
+    free(map->modmap);
+    free(keymap->map);
+    keymap->map = NULL;
+}
+
+void
+XkbcFreeServerMap(struct xkb_keymap *keymap)
+{
+    struct xkb_server_map * map;
+
+    if (!keymap || !keymap->server)
+        return;
+
+    map = keymap->server;
+
+    free(map->explicit);
+    free(map->key_acts);
+    free(map->acts);
+    free(map->behaviors);
+    free(map->vmodmap);
+    free(keymap->server);
+    keymap->server = NULL;
+}
+
+int
+XkbcAllocCompatMap(struct xkb_keymap *keymap, unsigned nSI)
+{
+    struct xkb_compat_map * compat;
+    struct xkb_sym_interpret *prev_interpret;
+
+    if (!keymap)
+        return BadMatch;
+
+    if (keymap->compat) {
+        if (keymap->compat->size_si >= nSI)
             return Success;
 
-        compat = xkb->compat;
+        compat = keymap->compat;
         compat->size_si = nSI;
         if (!compat->sym_interpret)
             compat->num_si = 0;
 
         prev_interpret = compat->sym_interpret;
-        compat->sym_interpret = _XkbTypedRealloc(compat->sym_interpret,
-                                                 nSI, XkbSymInterpretRec);
+        compat->sym_interpret = uTypedRecalloc(compat->sym_interpret,
+                                               compat->num_si, nSI,
+                                               struct xkb_sym_interpret);
         if (!compat->sym_interpret) {
-            _XkbFree(prev_interpret);
+            free(prev_interpret);
             compat->size_si = compat->num_si = 0;
             return BadAlloc;
         }
 
-        if (compat->num_si != 0)
-            _XkbClearElems(compat->sym_interpret, compat->num_si,
-                           compat->size_si - 1, XkbSymInterpretRec);
-
         return Success;
     }
 
-    compat = _XkbTypedCalloc(1, XkbCompatMapRec);
+    compat = uTypedCalloc(1, struct xkb_compat_map);
     if (!compat)
         return BadAlloc;
 
     if (nSI > 0) {
-        compat->sym_interpret = _XkbTypedCalloc(nSI, XkbSymInterpretRec);
+        compat->sym_interpret = uTypedCalloc(nSI, struct xkb_sym_interpret);
         if (!compat->sym_interpret) {
-            _XkbFree(compat);
+            free(compat);
             return BadAlloc;
         }
     }
     compat->size_si = nSI;
     compat->num_si = 0;
-    bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
-    xkb->compat = compat;
+    memset(&compat->groups[0], 0, XkbNumKbdGroups * sizeof(struct xkb_mods));
+    keymap->compat = compat;
 
     return Success;
 }
 
 
-void
-XkbcFreeCompatMap(XkbcDescPtr xkb, unsigned which, Bool freeMap)
+static void
+XkbcFreeCompatMap(struct xkb_keymap *keymap)
 {
-    XkbCompatMapPtr compat;
+    struct xkb_compat_map * compat;
 
-    if (!xkb || !xkb->compat)
+    if (!keymap || !keymap->compat)
         return;
 
-    compat = xkb->compat;
-    if (freeMap)
-        which = XkbAllCompatMask;
+    compat = keymap->compat;
 
-    if (which & XkbGroupCompatMask)
-        bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
-
-    if (which & XkbSymInterpMask) {
-        if (compat->sym_interpret && (compat->size_si > 0))
-            _XkbFree(compat->sym_interpret);
-        compat->size_si = compat->num_si = 0;
-        compat->sym_interpret = NULL;
-    }
-
-    if (freeMap) {
-        _XkbFree(compat);
-        xkb->compat = NULL;
-    }
+    free(compat->sym_interpret);
+    free(compat);
+    keymap->compat = NULL;
 }
 
 int
-XkbcAllocNames(XkbcDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
+XkbcAllocNames(struct xkb_keymap *keymap, unsigned which,
+               unsigned nTotalAliases)
 {
-    XkbNamesPtr names;
+    struct xkb_names * names;
 
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->names) {
-        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
-        if (!xkb->names)
+    if (!keymap->names) {
+        keymap->names = uTypedCalloc(1, struct xkb_names);
+        if (!keymap->names)
             return BadAlloc;
     }
-    names = xkb->names;
+    names = keymap->names;
 
-    if ((which & XkbKTLevelNamesMask) && xkb->map && xkb->map->types) {
+    if ((which & XkbKTLevelNamesMask) && keymap->map && keymap->map->types) {
         int i;
-        XkbKeyTypePtr type;
+        struct xkb_key_type * type;
 
-        type = xkb->map->types;
-        for (i = 0; i < xkb->map->num_types; i++, type++) {
+        type = keymap->map->types;
+        for (i = 0; i < keymap->map->num_types; i++, type++) {
             if (!type->level_names) {
-                type->level_names = _XkbTypedCalloc(type->num_levels, Atom);
+                type->level_names = uTypedCalloc(type->num_levels, const char *);
                 if (!type->level_names)
                     return BadAlloc;
             }
@@ -144,31 +457,25 @@ XkbcAllocNames(XkbcDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
     }
 
     if ((which & XkbKeyNamesMask) && !names->keys) {
-        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
-            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
-            (xkb->max_key_code < xkb->min_key_code))
-            return BadValue;
-
-        names->keys = _XkbTypedCalloc(xkb->max_key_code + 1, XkbKeyNameRec);
+        names->keys = uTypedCalloc(keymap->max_key_code + 1,
+                                   struct xkb_key_name);
         if (!names->keys)
             return BadAlloc;
     }
 
     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
         if (!names->key_aliases)
-            names->key_aliases = _XkbTypedCalloc(nTotalAliases,
-                                                 XkbKeyAliasRec);
+            names->key_aliases = uTypedCalloc(nTotalAliases,
+                                                 struct xkb_key_alias);
         else if (nTotalAliases > names->num_key_aliases) {
-            XkbKeyAliasRec *prev_aliases = names->key_aliases;
-
-            names->key_aliases = _XkbTypedRealloc(names->key_aliases,
-                                                  nTotalAliases,
-                                                  XkbKeyAliasRec);
-            if (names->key_aliases)
-                _XkbClearElems(names->key_aliases, names->num_key_aliases,
-                               nTotalAliases - 1, XkbKeyAliasRec);
-            else
-                _XkbFree(prev_aliases);
+            struct xkb_key_alias *prev_aliases = names->key_aliases;
+
+            names->key_aliases = uTypedRecalloc(names->key_aliases,
+                                                names->num_key_aliases,
+                                                nTotalAliases,
+                                                struct xkb_key_alias);
+            if (!names->key_aliases)
+                free(prev_aliases);
         }
 
         if (!names->key_aliases) {
@@ -179,164 +486,128 @@ XkbcAllocNames(XkbcDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
         names->num_key_aliases = nTotalAliases;
     }
 
-    if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
-        if (!names->radio_groups)
-            names->radio_groups = _XkbTypedCalloc(nTotalRG, Atom);
-        else if (nTotalRG > names->num_rg) {
-            Atom *prev_radio_groups = names->radio_groups;
-
-            names->radio_groups = _XkbTypedRealloc(names->radio_groups,
-                                                   nTotalRG, Atom);
-            if (names->radio_groups)
-                _XkbClearElems(names->radio_groups, names->num_rg,
-                               nTotalRG - 1, Atom);
-            else
-                _XkbFree(prev_radio_groups);
-        }
-
-        if (!names->radio_groups)
-            return BadAlloc;
-
-        names->num_rg = nTotalRG;
-    }
-
     return Success;
 }
 
-void
-XkbcFreeNames(XkbcDescPtr xkb, unsigned which, Bool freeMap)
+static void
+XkbcFreeNames(struct xkb_keymap *keymap)
 {
-    XkbNamesPtr names;
+    struct xkb_names * names;
+    struct xkb_client_map * map;
+    int i;
 
-    if (!xkb || !xkb->names)
+    if (!keymap || !keymap->names)
         return;
 
-    names = xkb->names;
-    if (freeMap)
-        which = XkbAllNamesMask;
+    names = keymap->names;
+    map = keymap->map;
 
-    if (which & XkbKTLevelNamesMask) {
-        XkbClientMapPtr map = xkb->map;
+    if (map && map->types) {
+        struct xkb_key_type * type = map->types;
 
-        if (map && map->types) {
-            int i;
-            XkbKeyTypePtr type = map->types;
-
-            for (i = 0; i < map->num_types; i++, type++) {
-                if (type->level_names) {
-                    _XkbFree(type->level_names);
-                    type->level_names = NULL;
-                }
-            }
+        for (i = 0; i < map->num_types; i++, type++) {
+            int j;
+            for (j = 0; j < type->num_levels; j++)
+                free(UNCONSTIFY(type->level_names[i]));
+            free(type->level_names);
+            type->level_names = NULL;
         }
     }
 
-    if ((which & XkbKeyNamesMask) && names->keys) {
-        _XkbFree(names->keys);
-        names->keys = NULL;
-        names->num_keys = 0;
-    }
-
-    if ((which & XkbKeyAliasesMask) && names->key_aliases) {
-        _XkbFree(names->key_aliases);
-        names->key_aliases = NULL;
-        names->num_key_aliases = 0;
-    }
-
-    if ((which & XkbRGNamesMask) && names->radio_groups) {
-        _XkbFree(names->radio_groups);
-        names->radio_groups = NULL;
-        names->num_rg = 0;
-    }
-
-    if (freeMap) {
-        _XkbFree(names);
-        xkb->names = NULL;
-    }
+    for (i = 0; i < XkbNumVirtualMods; i++)
+        free(UNCONSTIFY(names->vmods[i]));
+    for (i = 0; i < XkbNumIndicators; i++)
+        free(UNCONSTIFY(names->indicators[i]));
+    for (i = 0; i < XkbNumKbdGroups; i++)
+        free(UNCONSTIFY(names->groups[i]));
+
+    free(names->keys);
+    free(names->key_aliases);
+    free(names);
+    keymap->names = NULL;
 }
 
 int
-XkbcAllocControls(XkbcDescPtr xkb, unsigned which)
+XkbcAllocControls(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->ctrls) {
-        xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
-        if (!xkb->ctrls)
+    if (!keymap->ctrls) {
+        keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
+        if (!keymap->ctrls)
             return BadAlloc;
     }
 
+    keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
+                                                 unsigned char);
+    if (!keymap->ctrls->per_key_repeat)
+        return BadAlloc;
+
     return Success;
 }
 
-void
-XkbcFreeControls(XkbcDescPtr xkb, unsigned which, Bool freeMap)
+static void
+XkbcFreeControls(struct xkb_keymap *keymap)
 {
-    if (freeMap && xkb && xkb->ctrls) {
-        _XkbFree(xkb->ctrls);
-        xkb->ctrls = NULL;
+    if (keymap && keymap->ctrls) {
+        free(keymap->ctrls->per_key_repeat);
+        free(keymap->ctrls);
+        keymap->ctrls = NULL;
     }
 }
 
 int
-XkbcAllocIndicatorMaps(XkbcDescPtr xkb)
+XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->indicators) {
-        xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
-        if (!xkb->indicators)
+    if (!keymap->indicators) {
+        keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
+        if (!keymap->indicators)
             return BadAlloc;
     }
 
     return Success;
 }
 
-void
-XkbcFreeIndicatorMaps(XkbcDescPtr xkb)
+static void
+XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
 {
-    if (xkb && xkb->indicators) {
-        _XkbFree(xkb->indicators);
-        xkb->indicators = NULL;
+    if (keymap) {
+        free(keymap->indicators);
+        keymap->indicators = NULL;
     }
 }
 
-XkbcDescRec *
-XkbcAllocKeyboard(void)
+struct xkb_keymap *
+XkbcAllocKeyboard(struct xkb_context *ctx)
 {
-    XkbcDescRec *xkb;
+    struct xkb_keymap *keymap;
+
+    keymap = uTypedCalloc(1, struct xkb_keymap);
+    if (!keymap)
+        return NULL;
+
+    keymap->refcnt = 1;
+    keymap->ctx = xkb_context_ref(ctx);
 
-    xkb = _XkbTypedCalloc(1, XkbcDescRec);
-    if (xkb)
-        xkb->device_spec = XkbUseCoreKbd;
-    return xkb;
+    return keymap;
 }
 
 void
-XkbcFreeKeyboard(XkbcDescPtr xkb, unsigned which, Bool freeAll)
+XkbcFreeKeyboard(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return;
 
-    if (freeAll)
-        which = XkbAllComponentsMask;
-
-    if (which & XkbClientMapMask)
-        XkbcFreeClientMap(xkb, XkbAllClientInfoMask, True);
-    if (which & XkbServerMapMask)
-        XkbcFreeServerMap(xkb, XkbAllServerInfoMask, True);
-    if (which & XkbCompatMapMask)
-        XkbcFreeCompatMap(xkb, XkbAllCompatMask, True);
-    if (which & XkbIndicatorMapMask)
-        XkbcFreeIndicatorMaps(xkb);
-    if (which & XkbNamesMask)
-        XkbcFreeNames(xkb, XkbAllNamesMask, True);
-    if ((which & XkbGeometryMask) && xkb->geom)
-        XkbcFreeGeometry(xkb->geom, XkbGeomAllMask, True);
-    if (which & XkbControlsMask)
-        XkbcFreeControls(xkb, XkbAllControlsMask, True);
-    if (freeAll)
-        _XkbFree(xkb);
+    XkbcFreeClientMap(keymap);
+    XkbcFreeServerMap(keymap);
+    XkbcFreeCompatMap(keymap);
+    XkbcFreeIndicatorMaps(keymap);
+    XkbcFreeNames(keymap);
+    XkbcFreeControls(keymap);
+    xkb_context_unref(keymap->ctx);
+    free(keymap);
 }