XKBMAlloc.c revision f2d49d05
11ab64890Smrg/************************************************************
21ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
31ab64890Smrg
41ab64890SmrgPermission to use, copy, modify, and distribute this
51ab64890Smrgsoftware and its documentation for any purpose and without
61ab64890Smrgfee is hereby granted, provided that the above copyright
71ab64890Smrgnotice appear in all copies and that both that copyright
81ab64890Smrgnotice and this permission notice appear in supporting
961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1061b2299dSmrgused in advertising or publicity pertaining to distribution
111ab64890Smrgof the software without specific prior written permission.
1261b2299dSmrgSilicon Graphics makes no representation about the suitability
131ab64890Smrgof this software for any purpose. It is provided "as is"
141ab64890Smrgwithout any express or implied warranty.
151ab64890Smrg
1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241ab64890Smrg
251ab64890Smrg********************************************************/
261ab64890Smrg
27818534a1Smrg#ifdef HAVE_CONFIG_H
281ab64890Smrg#include <config.h>
291ab64890Smrg#endif
301ab64890Smrg
311ab64890Smrg
321ab64890Smrg#include <stdio.h>
331ab64890Smrg#include "Xlibint.h"
341ab64890Smrg#include <X11/extensions/XKBproto.h>
351ab64890Smrg#include <X11/keysym.h>
361ab64890Smrg#include "XKBlibint.h"
371ab64890Smrg
381ab64890Smrg
391ab64890Smrg/***====================================================================***/
401ab64890Smrg
411ab64890SmrgStatus
42818534a1SmrgXkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes)
431ab64890Smrg{
44818534a1Smrg    register int i;
45818534a1Smrg    XkbClientMapPtr map;
46818534a1Smrg
47818534a1Smrg    if ((xkb == NULL) ||
48818534a1Smrg        ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
49818534a1Smrg        return BadValue;
50818534a1Smrg    if ((which & XkbKeySymsMask) &&
51818534a1Smrg        ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
52818534a1Smrg         (!XkbIsLegalKeycode(xkb->max_key_code)) ||
53818534a1Smrg         (xkb->max_key_code < xkb->min_key_code))) {
541ab64890Smrg#ifdef DEBUG
55818534a1Smrg        fprintf(stderr, "bad keycode (%d,%d) in XkbAllocClientMap\n",
56818534a1Smrg                xkb->min_key_code, xkb->max_key_code);
571ab64890Smrg#endif
58818534a1Smrg        return BadValue;
59818534a1Smrg    }
60818534a1Smrg
61818534a1Smrg    if (xkb->map == NULL) {
62818534a1Smrg        map = _XkbTypedCalloc(1, XkbClientMapRec);
63818534a1Smrg        if (map == NULL)
64818534a1Smrg            return BadAlloc;
65818534a1Smrg        xkb->map = map;
66818534a1Smrg    }
67818534a1Smrg    else
68818534a1Smrg        map = xkb->map;
69818534a1Smrg
70818534a1Smrg    if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
71818534a1Smrg        if (map->types == NULL) {
72f2d49d05Smrg            map->num_types = map->size_types = 0;
73818534a1Smrg        }
74f2d49d05Smrg        if ((map->types == NULL) || (map->size_types < nTotalTypes)) {
75f2d49d05Smrg            _XkbResizeArray(map->types, map->size_types, nTotalTypes,
76f2d49d05Smrg                            XkbKeyTypeRec);
77818534a1Smrg
78818534a1Smrg            if (map->types == NULL) {
79818534a1Smrg                map->num_types = map->size_types = 0;
80818534a1Smrg                return BadAlloc;
81818534a1Smrg            }
82818534a1Smrg            map->size_types = nTotalTypes;
83818534a1Smrg        }
84818534a1Smrg    }
85818534a1Smrg    if (which & XkbKeySymsMask) {
86818534a1Smrg        int nKeys = XkbNumKeys(xkb);
87818534a1Smrg
88818534a1Smrg        if (map->syms == NULL) {
89818534a1Smrg            map->size_syms = (nKeys * 15) / 10;
90818534a1Smrg            map->syms = _XkbTypedCalloc(map->size_syms, KeySym);
91818534a1Smrg            if (!map->syms) {
92818534a1Smrg                map->size_syms = 0;
93818534a1Smrg                return BadAlloc;
94818534a1Smrg            }
95818534a1Smrg            map->num_syms = 1;
96818534a1Smrg            map->syms[0] = NoSymbol;
97818534a1Smrg        }
98818534a1Smrg        if (map->key_sym_map == NULL) {
99818534a1Smrg            i = xkb->max_key_code + 1;
100818534a1Smrg            map->key_sym_map = _XkbTypedCalloc(i, XkbSymMapRec);
101818534a1Smrg            if (map->key_sym_map == NULL)
102818534a1Smrg                return BadAlloc;
103818534a1Smrg        }
104818534a1Smrg    }
105818534a1Smrg    if (which & XkbModifierMapMask) {
106818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
107818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
108818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
109818534a1Smrg            return BadMatch;
110818534a1Smrg        if (map->modmap == NULL) {
111818534a1Smrg            i = xkb->max_key_code + 1;
112818534a1Smrg            map->modmap = _XkbTypedCalloc(i, unsigned char);
113818534a1Smrg            if (map->modmap == NULL)
114818534a1Smrg                return BadAlloc;
115818534a1Smrg        }
1161ab64890Smrg    }
1171ab64890Smrg    return Success;
1181ab64890Smrg}
1191ab64890Smrg
1201ab64890SmrgStatus
121818534a1SmrgXkbAllocServerMap(XkbDescPtr xkb, unsigned which, unsigned nNewActions)
1221ab64890Smrg{
123818534a1Smrg    register int i;
124818534a1Smrg    XkbServerMapPtr map;
125818534a1Smrg
126818534a1Smrg    if (xkb == NULL)
127818534a1Smrg        return BadMatch;
128818534a1Smrg    if (xkb->server == NULL) {
129818534a1Smrg        map = _XkbTypedCalloc(1, XkbServerMapRec);
130818534a1Smrg        if (map == NULL)
131818534a1Smrg            return BadAlloc;
132818534a1Smrg        for (i = 0; i < XkbNumVirtualMods; i++) {
133818534a1Smrg            map->vmods[i] = XkbNoModifierMask;
134818534a1Smrg        }
135818534a1Smrg        xkb->server = map;
136818534a1Smrg    }
137818534a1Smrg    else
138818534a1Smrg        map = xkb->server;
139818534a1Smrg    if (which & XkbExplicitComponentsMask) {
140818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
141818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
142818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
143818534a1Smrg            return BadMatch;
144818534a1Smrg        if (map->explicit == NULL) {
145818534a1Smrg            i = xkb->max_key_code + 1;
146818534a1Smrg            map->explicit = _XkbTypedCalloc(i, unsigned char);
147818534a1Smrg            if (map->explicit == NULL)
148818534a1Smrg                return BadAlloc;
149818534a1Smrg        }
150818534a1Smrg    }
151818534a1Smrg    if (which & XkbKeyActionsMask) {
152818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
153818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
154818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
155818534a1Smrg            return BadMatch;
156818534a1Smrg        if (nNewActions < 1)
157818534a1Smrg            nNewActions = 1;
158818534a1Smrg        if (map->acts == NULL) {
159818534a1Smrg            map->num_acts = 1;
160f2d49d05Smrg            map->size_acts = 0;
161818534a1Smrg        }
162f2d49d05Smrg        if ((map->acts == NULL) ||
163f2d49d05Smrg            ((map->size_acts - map->num_acts) < nNewActions)) {
164818534a1Smrg            unsigned need;
165818534a1Smrg
166818534a1Smrg            need = map->num_acts + nNewActions;
167f2d49d05Smrg            _XkbResizeArray(map->acts, map->size_acts, need, XkbAction);
168818534a1Smrg            if (map->acts == NULL) {
169818534a1Smrg                map->num_acts = map->size_acts = 0;
170818534a1Smrg                return BadAlloc;
171818534a1Smrg            }
172818534a1Smrg            map->size_acts = need;
173818534a1Smrg        }
174818534a1Smrg        if (map->key_acts == NULL) {
175818534a1Smrg            i = xkb->max_key_code + 1;
176818534a1Smrg            map->key_acts = _XkbTypedCalloc(i, unsigned short);
177818534a1Smrg            if (map->key_acts == NULL)
178818534a1Smrg                return BadAlloc;
179818534a1Smrg        }
180818534a1Smrg    }
181818534a1Smrg    if (which & XkbKeyBehaviorsMask) {
182818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
183818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
184818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
185818534a1Smrg            return BadMatch;
186818534a1Smrg        if (map->behaviors == NULL) {
187818534a1Smrg            i = xkb->max_key_code + 1;
188818534a1Smrg            map->behaviors = _XkbTypedCalloc(i, XkbBehavior);
189818534a1Smrg            if (map->behaviors == NULL)
190818534a1Smrg                return BadAlloc;
191818534a1Smrg        }
192818534a1Smrg    }
193818534a1Smrg    if (which & XkbVirtualModMapMask) {
194818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
195818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
196818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
197818534a1Smrg            return BadMatch;
198818534a1Smrg        if (map->vmodmap == NULL) {
199818534a1Smrg            i = xkb->max_key_code + 1;
200818534a1Smrg            map->vmodmap = _XkbTypedCalloc(i, unsigned short);
201818534a1Smrg            if (map->vmodmap == NULL)
202818534a1Smrg                return BadAlloc;
203818534a1Smrg        }
2041ab64890Smrg    }
2051ab64890Smrg    return Success;
2061ab64890Smrg}
2071ab64890Smrg
2081ab64890Smrg/***====================================================================***/
2091ab64890Smrg
2101ab64890SmrgStatus
211818534a1SmrgXkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into)
2121ab64890Smrg{
213818534a1Smrg    if ((!from) || (!into))
214818534a1Smrg        return BadMatch;
215cf2acddeSmrg
216cf2acddeSmrg    _XkbFree(into->map);
217cf2acddeSmrg    into->map = NULL;
218cf2acddeSmrg
219cf2acddeSmrg    _XkbFree(into->preserve);
220cf2acddeSmrg    into->preserve = NULL;
221cf2acddeSmrg
222cf2acddeSmrg    _XkbFree(into->level_names);
223cf2acddeSmrg    into->level_names = NULL;
224cf2acddeSmrg
225818534a1Smrg    *into = *from;
226818534a1Smrg    if ((from->map) && (into->map_count > 0)) {
227818534a1Smrg        into->map = _XkbTypedCalloc(into->map_count, XkbKTMapEntryRec);
228818534a1Smrg        if (!into->map)
229818534a1Smrg            return BadAlloc;
230818534a1Smrg        memcpy(into->map, from->map,
231818534a1Smrg               into->map_count * sizeof(XkbKTMapEntryRec));
232818534a1Smrg    }
233818534a1Smrg    if ((from->preserve) && (into->map_count > 0)) {
234818534a1Smrg        into->preserve = _XkbTypedCalloc(into->map_count, XkbModsRec);
235818534a1Smrg        if (!into->preserve)
236818534a1Smrg            return BadAlloc;
237818534a1Smrg        memcpy(into->preserve, from->preserve,
238818534a1Smrg               into->map_count * sizeof(XkbModsRec));
239818534a1Smrg    }
240818534a1Smrg    if ((from->level_names) && (into->num_levels > 0)) {
241818534a1Smrg        into->level_names = _XkbTypedCalloc(into->num_levels, Atom);
242818534a1Smrg        if (!into->level_names)
243818534a1Smrg            return BadAlloc;
244818534a1Smrg        memcpy(into->level_names, from->level_names,
245818534a1Smrg               into->num_levels * sizeof(Atom));
2461ab64890Smrg    }
2471ab64890Smrg    return Success;
2481ab64890Smrg}
2491ab64890Smrg
2501ab64890SmrgStatus
251818534a1SmrgXkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types)
2521ab64890Smrg{
253818534a1Smrg    register int i, rtrn;
2541ab64890Smrg
255818534a1Smrg    if ((!from) || (!into) || (num_types < 0))
256818534a1Smrg        return BadMatch;
257818534a1Smrg    for (i = 0; i < num_types; i++) {
258818534a1Smrg        if ((rtrn = XkbCopyKeyType(from++, into++)) != Success)
259818534a1Smrg            return rtrn;
2601ab64890Smrg    }
2611ab64890Smrg    return Success;
2621ab64890Smrg}
2631ab64890Smrg
2641ab64890SmrgXkbKeyTypePtr
265818534a1SmrgXkbAddKeyType(XkbDescPtr xkb,
266818534a1Smrg              Atom name,
267818534a1Smrg              int map_count,
268818534a1Smrg              Bool want_preserve,
269818534a1Smrg              int num_lvls)
2701ab64890Smrg{
271818534a1Smrg    register int i;
272818534a1Smrg    unsigned tmp;
273818534a1Smrg    XkbKeyTypePtr type;
274818534a1Smrg    XkbClientMapPtr map;
275818534a1Smrg
276818534a1Smrg    if ((!xkb) || (num_lvls < 1))
277818534a1Smrg        return NULL;
278818534a1Smrg    map = xkb->map;
279818534a1Smrg    if ((map) && (map->types)) {
280818534a1Smrg        for (i = 0; i < map->num_types; i++) {
281818534a1Smrg            if (map->types[i].name == name) {
282818534a1Smrg                Status status =
283818534a1Smrg                    XkbResizeKeyType(xkb, i, map_count, want_preserve,
284818534a1Smrg                                     num_lvls);
285818534a1Smrg                return (status == Success ? &map->types[i] : NULL);
286818534a1Smrg            }
287818534a1Smrg        }
288818534a1Smrg    }
289cf2acddeSmrg    if ((!map) || (!map->types) || (map->num_types < XkbNumRequiredTypes)) {
290818534a1Smrg        tmp = XkbNumRequiredTypes + 1;
291818534a1Smrg        if (XkbAllocClientMap(xkb, XkbKeyTypesMask, tmp) != Success)
292818534a1Smrg            return NULL;
2931ab64890Smrg        if (!map)
2941ab64890Smrg            map = xkb->map;
295818534a1Smrg        tmp = 0;
296818534a1Smrg        if (map->num_types <= XkbKeypadIndex)
297818534a1Smrg            tmp |= XkbKeypadMask;
298818534a1Smrg        if (map->num_types <= XkbAlphabeticIndex)
299818534a1Smrg            tmp |= XkbAlphabeticMask;
300818534a1Smrg        if (map->num_types <= XkbTwoLevelIndex)
301818534a1Smrg            tmp |= XkbTwoLevelMask;
302818534a1Smrg        if (map->num_types <= XkbOneLevelIndex)
303818534a1Smrg            tmp |= XkbOneLevelMask;
304818534a1Smrg        if (XkbInitCanonicalKeyTypes(xkb, tmp, XkbNoModifier) == Success) {
305818534a1Smrg            for (i = 0; i < map->num_types; i++) {
306818534a1Smrg                Status status;
307818534a1Smrg
308818534a1Smrg                if (map->types[i].name != name)
309818534a1Smrg                    continue;
310818534a1Smrg                status = XkbResizeKeyType(xkb, i, map_count, want_preserve,
311818534a1Smrg                                          num_lvls);
312818534a1Smrg                return (status == Success ? &map->types[i] : NULL);
313818534a1Smrg            }
314818534a1Smrg        }
315818534a1Smrg    }
316818534a1Smrg    if ((map->num_types <= map->size_types) &&
317818534a1Smrg        (XkbAllocClientMap(xkb, XkbKeyTypesMask, map->num_types + 1) !=
318818534a1Smrg         Success)) {
319818534a1Smrg        return NULL;
320818534a1Smrg    }
321818534a1Smrg    type = &map->types[map->num_types];
3221ab64890Smrg    map->num_types++;
323818534a1Smrg    bzero((char *) type, sizeof(XkbKeyTypeRec));
324818534a1Smrg    type->num_levels = num_lvls;
325818534a1Smrg    type->map_count = map_count;
326818534a1Smrg    type->name = name;
327818534a1Smrg    if (map_count > 0) {
328818534a1Smrg        type->map = _XkbTypedCalloc(map_count, XkbKTMapEntryRec);
329818534a1Smrg        if (!type->map) {
330818534a1Smrg            map->num_types--;
331818534a1Smrg            return NULL;
332818534a1Smrg        }
333818534a1Smrg        if (want_preserve) {
334818534a1Smrg            type->preserve = _XkbTypedCalloc(map_count, XkbModsRec);
335818534a1Smrg            if (!type->preserve) {
336818534a1Smrg                _XkbFree(type->map);
337818534a1Smrg                map->num_types--;
338818534a1Smrg                return NULL;
339818534a1Smrg            }
340818534a1Smrg        }
3411ab64890Smrg    }
3421ab64890Smrg    return type;
3431ab64890Smrg}
3441ab64890Smrg
3451ab64890SmrgStatus
346818534a1SmrgXkbResizeKeyType(XkbDescPtr xkb,
347818534a1Smrg                 int type_ndx,
348818534a1Smrg                 int map_count,
349818534a1Smrg                 Bool want_preserve,
350818534a1Smrg                 int new_num_lvls)
3511ab64890Smrg{
352818534a1Smrg    XkbKeyTypePtr type;
353818534a1Smrg    KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys;
3541ab64890Smrg
355818534a1Smrg    if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0)
356818534a1Smrg        || (new_num_lvls < 1))
357818534a1Smrg        return BadValue;
3581ab64890Smrg    switch (type_ndx) {
359818534a1Smrg    case XkbOneLevelIndex:
360818534a1Smrg        if (new_num_lvls != 1)
361818534a1Smrg            return BadMatch;
362818534a1Smrg        break;
363818534a1Smrg    case XkbTwoLevelIndex:
364818534a1Smrg    case XkbAlphabeticIndex:
365818534a1Smrg    case XkbKeypadIndex:
366818534a1Smrg        if (new_num_lvls != 2)
367818534a1Smrg            return BadMatch;
368818534a1Smrg        break;
369818534a1Smrg    }
370818534a1Smrg    type = &xkb->map->types[type_ndx];
371818534a1Smrg    if (map_count == 0) {
372cf2acddeSmrg        _XkbFree(type->map);
373818534a1Smrg        type->map = NULL;
374cf2acddeSmrg        _XkbFree(type->preserve);
375818534a1Smrg        type->preserve = NULL;
376818534a1Smrg        type->map_count = 0;
3771ab64890Smrg    }
3781ab64890Smrg    else {
379818534a1Smrg        if ((map_count > type->map_count) || (type->map == NULL))
380f2d49d05Smrg            _XkbResizeArray(type->map, type->map_count, map_count,
381f2d49d05Smrg                            XkbKTMapEntryRec);
382818534a1Smrg        if (!type->map) {
383818534a1Smrg            return BadAlloc;
384818534a1Smrg        }
385818534a1Smrg        if (want_preserve) {
386818534a1Smrg            if ((map_count > type->map_count) || (type->preserve == NULL)) {
387f2d49d05Smrg                _XkbResizeArray(type->preserve, type->map_count, map_count,
388f2d49d05Smrg                                XkbModsRec);
389818534a1Smrg            }
390818534a1Smrg            if (!type->preserve) {
391818534a1Smrg                return BadAlloc;
392818534a1Smrg            }
393818534a1Smrg        }
394cf2acddeSmrg        else {
395818534a1Smrg            _XkbFree(type->preserve);
396818534a1Smrg            type->preserve = NULL;
397818534a1Smrg        }
398818534a1Smrg        type->map_count = map_count;
399818534a1Smrg    }
400818534a1Smrg
401818534a1Smrg    if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) {
402f2d49d05Smrg        _XkbResizeArray(type->level_names, type->num_levels, new_num_lvls, Atom);
403818534a1Smrg        if (!type->level_names) {
404818534a1Smrg            return BadAlloc;
405818534a1Smrg        }
4061ab64890Smrg    }
4071ab64890Smrg    /*
4081ab64890Smrg     * Here's the theory:
4091ab64890Smrg     *    If the width of the type changed, we might have to resize the symbol
4101ab64890Smrg     * maps for any keys that use the type for one or more groups.  This is
4111ab64890Smrg     * expensive, so we'll try to cull out any keys that are obviously okay:
4121ab64890Smrg     * In any case:
4131ab64890Smrg     *    - keys that have a group width <= the old width are okay (because
4141ab64890Smrg     *      they could not possibly have been associated with the old type)
4151ab64890Smrg     * If the key type increased in size:
4161ab64890Smrg     *    - keys that already have a group width >= to the new width are okay
4171ab64890Smrg     *    + keys that have a group width >= the old width but < the new width
4181ab64890Smrg     *      might have to be enlarged.
4191ab64890Smrg     * If the key type decreased in size:
4201ab64890Smrg     *    - keys that have a group width > the old width don't have to be
42161b2299dSmrg     *      resized (because they must have some other wider type associated
4221ab64890Smrg     *      with some group).
4231ab64890Smrg     *    + keys that have a group width == the old width might have to be
4241ab64890Smrg     *      shrunk.
4251ab64890Smrg     * The possibilities marked with '+' require us to examine the key types
4261ab64890Smrg     * associated with each group for the key.
4271ab64890Smrg     */
428818534a1Smrg    bzero(matchingKeys, XkbMaxKeyCount * sizeof(KeyCode));
429818534a1Smrg    nMatchingKeys = 0;
430818534a1Smrg    if (new_num_lvls > type->num_levels) {
431818534a1Smrg        int nTotal;
432818534a1Smrg        KeySym *newSyms;
433818534a1Smrg        int width, match, nResize;
434818534a1Smrg        register int i, g, nSyms;
435818534a1Smrg
436818534a1Smrg        nResize = 0;
437818534a1Smrg        for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
438818534a1Smrg            width = XkbKeyGroupsWidth(xkb, i);
439818534a1Smrg            if (width < type->num_levels)
440818534a1Smrg                continue;
441818534a1Smrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
442818534a1Smrg                 (g >= 0) && (!match); g--) {
443818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
444818534a1Smrg                    matchingKeys[nMatchingKeys++] = i;
445818534a1Smrg                    match = 1;
446818534a1Smrg                }
447818534a1Smrg            }
448818534a1Smrg            if ((!match) || (width >= new_num_lvls))
449818534a1Smrg                nTotal += XkbKeyNumSyms(xkb, i);
450818534a1Smrg            else {
451818534a1Smrg                nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
452818534a1Smrg                nResize++;
453818534a1Smrg            }
454818534a1Smrg        }
455818534a1Smrg        if (nResize > 0) {
456818534a1Smrg            int nextMatch;
457818534a1Smrg
458818534a1Smrg            xkb->map->size_syms = (nTotal * 12) / 10;
459818534a1Smrg            newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
460818534a1Smrg            if (newSyms == NULL)
461818534a1Smrg                return BadAlloc;
462818534a1Smrg            nextMatch = 0;
463818534a1Smrg            nSyms = 1;
464818534a1Smrg            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
465818534a1Smrg                if (matchingKeys[nextMatch] == i) {
466818534a1Smrg                    KeySym *pOld;
467818534a1Smrg
468818534a1Smrg                    nextMatch++;
469818534a1Smrg                    width = XkbKeyGroupsWidth(xkb, i);
470818534a1Smrg                    pOld = XkbKeySymsPtr(xkb, i);
471818534a1Smrg                    for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
472818534a1Smrg                        memcpy(&newSyms[nSyms + (new_num_lvls * g)],
473818534a1Smrg                               &pOld[width * g], width * sizeof(KeySym));
474818534a1Smrg                    }
475818534a1Smrg                    xkb->map->key_sym_map[i].offset = nSyms;
476818534a1Smrg                    nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
477818534a1Smrg                }
478818534a1Smrg                else {
479818534a1Smrg                    memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
480818534a1Smrg                           XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
481818534a1Smrg                    xkb->map->key_sym_map[i].offset = nSyms;
482818534a1Smrg                    nSyms += XkbKeyNumSyms(xkb, i);
483818534a1Smrg                }
484818534a1Smrg            }
485818534a1Smrg            type->num_levels = new_num_lvls;
486818534a1Smrg            _XkbFree(xkb->map->syms);
487818534a1Smrg            xkb->map->syms = newSyms;
488818534a1Smrg            xkb->map->num_syms = nSyms;
489818534a1Smrg            return Success;
490818534a1Smrg        }
491818534a1Smrg    }
492818534a1Smrg    else if (new_num_lvls < type->num_levels) {
493818534a1Smrg        int width, match;
494818534a1Smrg        register int g, i;
495818534a1Smrg
496818534a1Smrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
497818534a1Smrg            width = XkbKeyGroupsWidth(xkb, i);
498818534a1Smrg            if (width < type->num_levels)
499818534a1Smrg                continue;
500818534a1Smrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
501818534a1Smrg                 (g >= 0) && (!match); g--) {
502818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
503818534a1Smrg                    matchingKeys[nMatchingKeys++] = i;
504818534a1Smrg                    match = 1;
505818534a1Smrg                }
506818534a1Smrg            }
507818534a1Smrg        }
508818534a1Smrg    }
509818534a1Smrg    if (nMatchingKeys > 0) {
510818534a1Smrg        int key, firstClear;
511818534a1Smrg        register int i, g;
512818534a1Smrg
513818534a1Smrg        if (new_num_lvls > type->num_levels)
514818534a1Smrg            firstClear = type->num_levels;
515818534a1Smrg        else
516818534a1Smrg            firstClear = new_num_lvls;
517818534a1Smrg        for (i = 0; i < nMatchingKeys; i++) {
518818534a1Smrg            KeySym *pSyms;
519818534a1Smrg            int width, nClear;
520818534a1Smrg
521818534a1Smrg            key = matchingKeys[i];
522818534a1Smrg            width = XkbKeyGroupsWidth(xkb, key);
523818534a1Smrg            nClear = width - firstClear;
524818534a1Smrg            pSyms = XkbKeySymsPtr(xkb, key);
525818534a1Smrg            for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
526818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
527818534a1Smrg                    if (nClear > 0)
528818534a1Smrg                        bzero(&pSyms[g * width + firstClear],
529818534a1Smrg                              nClear * sizeof(KeySym));
530818534a1Smrg                }
531818534a1Smrg            }
532818534a1Smrg        }
533818534a1Smrg    }
534818534a1Smrg    type->num_levels = new_num_lvls;
5351ab64890Smrg    return Success;
5361ab64890Smrg}
5371ab64890Smrg
5381ab64890SmrgKeySym *
539818534a1SmrgXkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
5401ab64890Smrg{
541818534a1Smrg    register int i, nSyms, nKeySyms;
542818534a1Smrg    unsigned nOldSyms;
543818534a1Smrg    KeySym *newSyms;
544818534a1Smrg
545818534a1Smrg    if (needed == 0) {
546818534a1Smrg        xkb->map->key_sym_map[key].offset = 0;
547818534a1Smrg        return xkb->map->syms;
548818534a1Smrg    }
549818534a1Smrg    nOldSyms = XkbKeyNumSyms(xkb, key);
550818534a1Smrg    if (nOldSyms >= (unsigned) needed) {
551818534a1Smrg        return XkbKeySymsPtr(xkb, key);
552818534a1Smrg    }
553818534a1Smrg    if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
554818534a1Smrg        if (nOldSyms > 0) {
555818534a1Smrg            memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
556818534a1Smrg                   nOldSyms * sizeof(KeySym));
557818534a1Smrg        }
558818534a1Smrg        if ((needed - nOldSyms) > 0) {
559818534a1Smrg            bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)],
560818534a1Smrg                  (needed - nOldSyms) * sizeof(KeySym));
561818534a1Smrg        }
562818534a1Smrg        xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
563818534a1Smrg        xkb->map->num_syms += needed;
564818534a1Smrg        return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
565818534a1Smrg    }
566818534a1Smrg    xkb->map->size_syms += (needed > 32 ? needed : 32);
567818534a1Smrg    newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
568818534a1Smrg    if (newSyms == NULL)
569818534a1Smrg        return NULL;
570818534a1Smrg    newSyms[0] = NoSymbol;
5711ab64890Smrg    nSyms = 1;
572818534a1Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
573818534a1Smrg        int nCopy;
574818534a1Smrg
575818534a1Smrg        nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
576818534a1Smrg        if ((nKeySyms == 0) && (i != key))
577818534a1Smrg            continue;
578818534a1Smrg        if (i == key)
579818534a1Smrg            nKeySyms = needed;
580818534a1Smrg        if (nCopy != 0)
581818534a1Smrg            memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
582818534a1Smrg                   nCopy * sizeof(KeySym));
583818534a1Smrg        if (nKeySyms > nCopy)
584818534a1Smrg            bzero(&newSyms[nSyms + nCopy], (nKeySyms - nCopy) * sizeof(KeySym));
585818534a1Smrg        xkb->map->key_sym_map[i].offset = nSyms;
586818534a1Smrg        nSyms += nKeySyms;
5871ab64890Smrg    }
5881ab64890Smrg    _XkbFree(xkb->map->syms);
5891ab64890Smrg    xkb->map->syms = newSyms;
5901ab64890Smrg    xkb->map->num_syms = nSyms;
5911ab64890Smrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
5921ab64890Smrg}
5931ab64890Smrg
5941ab64890Smrgstatic unsigned
595818534a1Smrg_ExtendRange(unsigned int old_flags,
596818534a1Smrg             unsigned int flag,
597818534a1Smrg             KeyCode newKC,
598818534a1Smrg             KeyCode *old_min,
599818534a1Smrg             unsigned char *old_num)
6001ab64890Smrg{
601818534a1Smrg    if ((old_flags & flag) == 0) {
602818534a1Smrg        old_flags |= flag;
603818534a1Smrg        *old_min = newKC;
604818534a1Smrg        *old_num = 1;
6051ab64890Smrg    }
6061ab64890Smrg    else {
607818534a1Smrg        int last = (*old_min) + (*old_num) - 1;
608818534a1Smrg
609818534a1Smrg        if (newKC < *old_min) {
610818534a1Smrg            *old_min = newKC;
611818534a1Smrg            *old_num = (last - newKC) + 1;
612818534a1Smrg        }
613818534a1Smrg        else if (newKC > last) {
614818534a1Smrg            *old_num = (newKC - (*old_min)) + 1;
615818534a1Smrg        }
6161ab64890Smrg    }
6171ab64890Smrg    return old_flags;
6181ab64890Smrg}
6191ab64890Smrg
6201ab64890SmrgStatus
621818534a1SmrgXkbChangeKeycodeRange(XkbDescPtr xkb,
622818534a1Smrg                      int minKC,
623818534a1Smrg                      int maxKC,
624818534a1Smrg                      XkbChangesPtr changes)
6251ab64890Smrg{
626818534a1Smrg    int tmp;
627818534a1Smrg
628818534a1Smrg    if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
629818534a1Smrg        return BadValue;
630818534a1Smrg    if (minKC > maxKC)
631818534a1Smrg        return BadMatch;
632818534a1Smrg    if (minKC < xkb->min_key_code) {
633818534a1Smrg        if (changes)
634818534a1Smrg            changes->map.min_key_code = minKC;
635818534a1Smrg        tmp = xkb->min_key_code - minKC;
636818534a1Smrg        if (xkb->map) {
637818534a1Smrg            if (xkb->map->key_sym_map) {
638818534a1Smrg                bzero((char *) &xkb->map->key_sym_map[minKC],
639818534a1Smrg                      tmp * sizeof(XkbSymMapRec));
640818534a1Smrg                if (changes) {
641818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
642818534a1Smrg                                                XkbKeySymsMask, minKC,
643818534a1Smrg                                                &changes->map.first_key_sym,
644818534a1Smrg                                                &changes->map.num_key_syms);
645818534a1Smrg                }
646818534a1Smrg            }
647818534a1Smrg            if (xkb->map->modmap) {
648818534a1Smrg                bzero((char *) &xkb->map->modmap[minKC], tmp);
649818534a1Smrg                if (changes) {
650818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
651818534a1Smrg                                                XkbModifierMapMask, minKC,
652818534a1Smrg                                                &changes->map.first_modmap_key,
653818534a1Smrg                                                &changes->map.num_modmap_keys);
654818534a1Smrg                }
655818534a1Smrg            }
656818534a1Smrg        }
657818534a1Smrg        if (xkb->server) {
658818534a1Smrg            if (xkb->server->behaviors) {
659818534a1Smrg                bzero((char *) &xkb->server->behaviors[minKC],
660818534a1Smrg                      tmp * sizeof(XkbBehavior));
661818534a1Smrg                if (changes) {
662818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
663818534a1Smrg                                              XkbKeyBehaviorsMask, minKC,
664818534a1Smrg                                              &changes->map.first_key_behavior,
665818534a1Smrg                                              &changes->map.num_key_behaviors);
666818534a1Smrg                }
667818534a1Smrg            }
668818534a1Smrg            if (xkb->server->key_acts) {
669818534a1Smrg                bzero((char *) &xkb->server->key_acts[minKC],
670818534a1Smrg                      tmp * sizeof(unsigned short));
671818534a1Smrg                if (changes) {
672818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
673818534a1Smrg                                                XkbKeyActionsMask, minKC,
674818534a1Smrg                                                &changes->map.first_key_act,
675818534a1Smrg                                                &changes->map.num_key_acts);
676818534a1Smrg                }
677818534a1Smrg            }
678818534a1Smrg            if (xkb->server->vmodmap) {
679818534a1Smrg                bzero((char *) &xkb->server->vmodmap[minKC],
680818534a1Smrg                      tmp * sizeof(unsigned short));
681818534a1Smrg                if (changes) {
682818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
683818534a1Smrg                                                XkbVirtualModMapMask, minKC,
684818534a1Smrg                                                &changes->map.first_modmap_key,
685818534a1Smrg                                                &changes->map.num_vmodmap_keys);
686818534a1Smrg                }
687818534a1Smrg            }
688818534a1Smrg        }
689818534a1Smrg        if ((xkb->names) && (xkb->names->keys)) {
690818534a1Smrg            bzero((char *) &xkb->names->keys[minKC],
691818534a1Smrg                  tmp * sizeof(XkbKeyNameRec));
692818534a1Smrg            if (changes) {
693818534a1Smrg                changes->names.changed = _ExtendRange(changes->names.changed,
694818534a1Smrg                                                      XkbKeyNamesMask, minKC,
695818534a1Smrg                                                      &changes->names.first_key,
696818534a1Smrg                                                      &changes->names.num_keys);
697818534a1Smrg            }
698818534a1Smrg        }
699818534a1Smrg        xkb->min_key_code = minKC;
700818534a1Smrg    }
701818534a1Smrg    if (maxKC > xkb->max_key_code) {
702818534a1Smrg        if (changes)
703818534a1Smrg            changes->map.max_key_code = maxKC;
704818534a1Smrg        tmp = maxKC - xkb->max_key_code;
705818534a1Smrg        if (xkb->map) {
706818534a1Smrg            if (xkb->map->key_sym_map) {
707f2d49d05Smrg                _XkbResizeArray(xkb->map->key_sym_map, xkb->max_key_code + 1,
708f2d49d05Smrg                                (maxKC + 1), XkbSymMapRec);
709818534a1Smrg                if (!xkb->map->key_sym_map) {
710818534a1Smrg                    return BadAlloc;
711818534a1Smrg                }
712818534a1Smrg                if (changes) {
713818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
714818534a1Smrg                                                XkbKeySymsMask, maxKC,
715818534a1Smrg                                                &changes->map.first_key_sym,
716818534a1Smrg                                                &changes->map.num_key_syms);
717818534a1Smrg                }
718818534a1Smrg            }
719818534a1Smrg            if (xkb->map->modmap) {
720f2d49d05Smrg                _XkbResizeArray(xkb->map->modmap, xkb->max_key_code + 1,
721f2d49d05Smrg                                (maxKC + 1), unsigned char);
722818534a1Smrg                if (!xkb->map->modmap) {
723818534a1Smrg                    return BadAlloc;
724818534a1Smrg                }
725818534a1Smrg                if (changes) {
726818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
727818534a1Smrg                                                XkbModifierMapMask, maxKC,
728818534a1Smrg                                                &changes->map.first_modmap_key,
729818534a1Smrg                                                &changes->map.num_modmap_keys);
730818534a1Smrg                }
731818534a1Smrg            }
732818534a1Smrg        }
733818534a1Smrg        if (xkb->server) {
734818534a1Smrg            if (xkb->server->behaviors) {
735f2d49d05Smrg                _XkbResizeArray(xkb->server->behaviors, xkb->max_key_code + 1,
736f2d49d05Smrg                                (maxKC + 1), XkbBehavior);
737818534a1Smrg                if (!xkb->server->behaviors) {
738818534a1Smrg                    return BadAlloc;
739818534a1Smrg                }
740818534a1Smrg                if (changes) {
741818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
742818534a1Smrg                                                XkbKeyBehaviorsMask, maxKC,
743818534a1Smrg                                                &changes->map.first_key_behavior,
744818534a1Smrg                                                &changes->map.num_key_behaviors);
745818534a1Smrg                }
746818534a1Smrg            }
747818534a1Smrg            if (xkb->server->key_acts) {
748f2d49d05Smrg                _XkbResizeArray(xkb->server->key_acts, xkb->max_key_code + 1,
749f2d49d05Smrg                                (maxKC + 1), unsigned short);
750818534a1Smrg                if (!xkb->server->key_acts) {
751818534a1Smrg                    return BadAlloc;
752818534a1Smrg                }
753818534a1Smrg                if (changes) {
754818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
755818534a1Smrg                                                XkbKeyActionsMask, maxKC,
756818534a1Smrg                                                &changes->map.first_key_act,
757818534a1Smrg                                                &changes->map.num_key_acts);
758818534a1Smrg                }
759818534a1Smrg            }
760818534a1Smrg            if (xkb->server->vmodmap) {
761f2d49d05Smrg                _XkbResizeArray(xkb->server->vmodmap, xkb->max_key_code + 1,
762f2d49d05Smrg                                (maxKC + 1), unsigned short);
763818534a1Smrg                if (!xkb->server->vmodmap) {
764818534a1Smrg                    return BadAlloc;
765818534a1Smrg                }
766818534a1Smrg                if (changes) {
767818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
768818534a1Smrg                                                XkbVirtualModMapMask, maxKC,
769818534a1Smrg                                                &changes->map.first_modmap_key,
770818534a1Smrg                                                &changes->map.num_vmodmap_keys);
771818534a1Smrg                }
772818534a1Smrg            }
773818534a1Smrg        }
774818534a1Smrg        if ((xkb->names) && (xkb->names->keys)) {
775f2d49d05Smrg            _XkbResizeArray(xkb->names->keys, xkb->max_key_code + 1,
776f2d49d05Smrg                            (maxKC + 1), XkbKeyNameRec);
777818534a1Smrg            if (!xkb->names->keys) {
778818534a1Smrg                return BadAlloc;
779818534a1Smrg            }
780818534a1Smrg            if (changes) {
781818534a1Smrg                changes->names.changed = _ExtendRange(changes->names.changed,
782818534a1Smrg                                                      XkbKeyNamesMask, maxKC,
783818534a1Smrg                                                      &changes->names.first_key,
784818534a1Smrg                                                      &changes->names.num_keys);
785818534a1Smrg            }
786818534a1Smrg        }
787818534a1Smrg        xkb->max_key_code = maxKC;
7881ab64890Smrg    }
7891ab64890Smrg    return Success;
7901ab64890Smrg}
7911ab64890Smrg
7921ab64890SmrgXkbAction *
793818534a1SmrgXkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
7941ab64890Smrg{
795818534a1Smrg    register int i, nActs;
796818534a1Smrg    XkbAction *newActs;
797818534a1Smrg
798818534a1Smrg    if (needed == 0) {
799818534a1Smrg        xkb->server->key_acts[key] = 0;
800818534a1Smrg        return NULL;
801818534a1Smrg    }
802818534a1Smrg    if (XkbKeyHasActions(xkb, key) &&
803818534a1Smrg        (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
804818534a1Smrg        return XkbKeyActionsPtr(xkb, key);
805818534a1Smrg    if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
806818534a1Smrg        xkb->server->key_acts[key] = xkb->server->num_acts;
807818534a1Smrg        xkb->server->num_acts += needed;
808818534a1Smrg        return &xkb->server->acts[xkb->server->key_acts[key]];
809818534a1Smrg    }
810818534a1Smrg    xkb->server->size_acts = xkb->server->num_acts + needed + 8;
811818534a1Smrg    newActs = _XkbTypedCalloc(xkb->server->size_acts, XkbAction);
812818534a1Smrg    if (newActs == NULL)
813818534a1Smrg        return NULL;
8141ab64890Smrg    newActs[0].type = XkbSA_NoAction;
8151ab64890Smrg    nActs = 1;
816818534a1Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
817818534a1Smrg        int nKeyActs, nCopy;
818818534a1Smrg
819818534a1Smrg        if ((xkb->server->key_acts[i] == 0) && (i != key))
820818534a1Smrg            continue;
821818534a1Smrg
822818534a1Smrg        nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
823818534a1Smrg        if (i == key) {
824818534a1Smrg            nKeyActs = needed;
825818534a1Smrg            if (needed < nCopy)
826818534a1Smrg                nCopy = needed;
827818534a1Smrg        }
828818534a1Smrg
829818534a1Smrg        if (nCopy > 0)
830818534a1Smrg            memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
831818534a1Smrg                   nCopy * sizeof(XkbAction));
832818534a1Smrg        if (nCopy < nKeyActs)
833818534a1Smrg            bzero(&newActs[nActs + nCopy],
834818534a1Smrg                  (nKeyActs - nCopy) * sizeof(XkbAction));
835818534a1Smrg        xkb->server->key_acts[i] = nActs;
836818534a1Smrg        nActs += nKeyActs;
8371ab64890Smrg    }
8381ab64890Smrg    _XkbFree(xkb->server->acts);
8391ab64890Smrg    xkb->server->acts = newActs;
840818534a1Smrg    xkb->server->num_acts = nActs;
8411ab64890Smrg    return &xkb->server->acts[xkb->server->key_acts[key]];
8421ab64890Smrg}
8431ab64890Smrg
8441ab64890Smrgvoid
845818534a1SmrgXkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
8461ab64890Smrg{
847818534a1Smrg    XkbClientMapPtr map;
8481ab64890Smrg
849818534a1Smrg    if ((xkb == NULL) || (xkb->map == NULL))
850818534a1Smrg        return;
8511ab64890Smrg    if (freeMap)
852818534a1Smrg        what = XkbAllClientInfoMask;
853818534a1Smrg    map = xkb->map;
854818534a1Smrg    if (what & XkbKeyTypesMask) {
855818534a1Smrg        if (map->types != NULL) {
856818534a1Smrg            if (map->num_types > 0) {
857818534a1Smrg                register int i;
858818534a1Smrg                XkbKeyTypePtr type;
859818534a1Smrg
860818534a1Smrg                for (i = 0, type = map->types; i < map->num_types; i++, type++) {
861cf2acddeSmrg                    _XkbFree(type->map);
862cf2acddeSmrg                    type->map = NULL;
863cf2acddeSmrg
864cf2acddeSmrg                    _XkbFree(type->preserve);
865cf2acddeSmrg                    type->preserve = NULL;
866cf2acddeSmrg
867818534a1Smrg                    type->map_count = 0;
868cf2acddeSmrg
869cf2acddeSmrg                    _XkbFree(type->level_names);
870cf2acddeSmrg                    type->level_names = NULL;
871818534a1Smrg                }
872818534a1Smrg            }
873818534a1Smrg            _XkbFree(map->types);
874818534a1Smrg            map->num_types = map->size_types = 0;
875818534a1Smrg            map->types = NULL;
876818534a1Smrg        }
877818534a1Smrg    }
878818534a1Smrg    if (what & XkbKeySymsMask) {
879cf2acddeSmrg        _XkbFree(map->key_sym_map);
880cf2acddeSmrg        map->key_sym_map = NULL;
881cf2acddeSmrg
882cf2acddeSmrg        _XkbFree(map->syms);
883cf2acddeSmrg        map->size_syms = map->num_syms = 0;
884cf2acddeSmrg        map->syms = NULL;
885818534a1Smrg    }
886cf2acddeSmrg    if (what & XkbModifierMapMask) {
887818534a1Smrg        _XkbFree(map->modmap);
888818534a1Smrg        map->modmap = NULL;
8891ab64890Smrg    }
8901ab64890Smrg    if (freeMap) {
891818534a1Smrg        _XkbFree(xkb->map);
892818534a1Smrg        xkb->map = NULL;
8931ab64890Smrg    }
8941ab64890Smrg    return;
8951ab64890Smrg}
8961ab64890Smrg
8971ab64890Smrgvoid
898818534a1SmrgXkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
8991ab64890Smrg{
900818534a1Smrg    XkbServerMapPtr map;
9011ab64890Smrg
902818534a1Smrg    if ((xkb == NULL) || (xkb->server == NULL))
903818534a1Smrg        return;
9041ab64890Smrg    if (freeMap)
905818534a1Smrg        what = XkbAllServerInfoMask;
906818534a1Smrg    map = xkb->server;
907cf2acddeSmrg    if (what & XkbExplicitComponentsMask) {
908818534a1Smrg        _XkbFree(map->explicit);
909818534a1Smrg        map->explicit = NULL;
910818534a1Smrg    }
911818534a1Smrg    if (what & XkbKeyActionsMask) {
912cf2acddeSmrg           _XkbFree(map->key_acts);
913818534a1Smrg            map->key_acts = NULL;
914cf2acddeSmrg
915cf2acddeSmrg           _XkbFree(map->acts);
916818534a1Smrg            map->num_acts = map->size_acts = 0;
917818534a1Smrg            map->acts = NULL;
918818534a1Smrg    }
919cf2acddeSmrg    if (what & XkbKeyBehaviorsMask) {
920818534a1Smrg        _XkbFree(map->behaviors);
921818534a1Smrg        map->behaviors = NULL;
922818534a1Smrg    }
923cf2acddeSmrg    if (what & XkbVirtualModMapMask)  {
924818534a1Smrg        _XkbFree(map->vmodmap);
925818534a1Smrg        map->vmodmap = NULL;
9261ab64890Smrg    }
9271ab64890Smrg
9281ab64890Smrg    if (freeMap) {
929818534a1Smrg        _XkbFree(xkb->server);
930818534a1Smrg        xkb->server = NULL;
9311ab64890Smrg    }
9321ab64890Smrg    return;
9331ab64890Smrg}
934