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);
439d5e6aabbSmrg            if (width < type->num_levels || width >= new_num_lvls) {
440d5e6aabbSmrg                nTotal += XkbKeyNumSyms(xkb,i);
441818534a1Smrg                continue;
442d5e6aabbSmrg            }
443818534a1Smrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
444818534a1Smrg                 (g >= 0) && (!match); g--) {
445818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
446818534a1Smrg                    matchingKeys[nMatchingKeys++] = i;
447818534a1Smrg                    match = 1;
448818534a1Smrg                }
449818534a1Smrg            }
450d5e6aabbSmrg            if (!match)
451818534a1Smrg                nTotal += XkbKeyNumSyms(xkb, i);
452818534a1Smrg            else {
453818534a1Smrg                nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
454818534a1Smrg                nResize++;
455818534a1Smrg            }
456818534a1Smrg        }
457818534a1Smrg        if (nResize > 0) {
458818534a1Smrg            int nextMatch;
459818534a1Smrg
460d5e6aabbSmrg            xkb->map->size_syms = (nTotal * 15) / 10;
461818534a1Smrg            newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
462818534a1Smrg            if (newSyms == NULL)
463818534a1Smrg                return BadAlloc;
464818534a1Smrg            nextMatch = 0;
465818534a1Smrg            nSyms = 1;
466818534a1Smrg            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
467818534a1Smrg                if (matchingKeys[nextMatch] == i) {
468818534a1Smrg                    KeySym *pOld;
469818534a1Smrg
470818534a1Smrg                    nextMatch++;
471818534a1Smrg                    width = XkbKeyGroupsWidth(xkb, i);
472818534a1Smrg                    pOld = XkbKeySymsPtr(xkb, i);
473818534a1Smrg                    for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
474818534a1Smrg                        memcpy(&newSyms[nSyms + (new_num_lvls * g)],
475818534a1Smrg                               &pOld[width * g], width * sizeof(KeySym));
476818534a1Smrg                    }
477818534a1Smrg                    xkb->map->key_sym_map[i].offset = nSyms;
478818534a1Smrg                    nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
479818534a1Smrg                }
480818534a1Smrg                else {
481818534a1Smrg                    memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
482818534a1Smrg                           XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
483818534a1Smrg                    xkb->map->key_sym_map[i].offset = nSyms;
484818534a1Smrg                    nSyms += XkbKeyNumSyms(xkb, i);
485818534a1Smrg                }
486818534a1Smrg            }
487818534a1Smrg            type->num_levels = new_num_lvls;
488818534a1Smrg            _XkbFree(xkb->map->syms);
489818534a1Smrg            xkb->map->syms = newSyms;
490818534a1Smrg            xkb->map->num_syms = nSyms;
491818534a1Smrg            return Success;
492818534a1Smrg        }
493818534a1Smrg    }
494818534a1Smrg    else if (new_num_lvls < type->num_levels) {
495818534a1Smrg        int width, match;
496818534a1Smrg        register int g, i;
497818534a1Smrg
498818534a1Smrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
499818534a1Smrg            width = XkbKeyGroupsWidth(xkb, i);
500818534a1Smrg            if (width < type->num_levels)
501818534a1Smrg                continue;
502818534a1Smrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
503818534a1Smrg                 (g >= 0) && (!match); g--) {
504818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
505818534a1Smrg                    matchingKeys[nMatchingKeys++] = i;
506818534a1Smrg                    match = 1;
507818534a1Smrg                }
508818534a1Smrg            }
509818534a1Smrg        }
510818534a1Smrg    }
511818534a1Smrg    if (nMatchingKeys > 0) {
512818534a1Smrg        int key, firstClear;
513818534a1Smrg        register int i, g;
514818534a1Smrg
515818534a1Smrg        if (new_num_lvls > type->num_levels)
516818534a1Smrg            firstClear = type->num_levels;
517818534a1Smrg        else
518818534a1Smrg            firstClear = new_num_lvls;
519818534a1Smrg        for (i = 0; i < nMatchingKeys; i++) {
520818534a1Smrg            KeySym *pSyms;
521818534a1Smrg            int width, nClear;
522818534a1Smrg
523818534a1Smrg            key = matchingKeys[i];
524818534a1Smrg            width = XkbKeyGroupsWidth(xkb, key);
525818534a1Smrg            nClear = width - firstClear;
526818534a1Smrg            pSyms = XkbKeySymsPtr(xkb, key);
527818534a1Smrg            for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
528818534a1Smrg                if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
529818534a1Smrg                    if (nClear > 0)
530818534a1Smrg                        bzero(&pSyms[g * width + firstClear],
531818534a1Smrg                              nClear * sizeof(KeySym));
532818534a1Smrg                }
533818534a1Smrg            }
534818534a1Smrg        }
535818534a1Smrg    }
536818534a1Smrg    type->num_levels = new_num_lvls;
5371ab64890Smrg    return Success;
5381ab64890Smrg}
5391ab64890Smrg
5401ab64890SmrgKeySym *
541818534a1SmrgXkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
5421ab64890Smrg{
543818534a1Smrg    register int i, nSyms, nKeySyms;
544818534a1Smrg    unsigned nOldSyms;
545818534a1Smrg    KeySym *newSyms;
546818534a1Smrg
547818534a1Smrg    if (needed == 0) {
548818534a1Smrg        xkb->map->key_sym_map[key].offset = 0;
549818534a1Smrg        return xkb->map->syms;
550818534a1Smrg    }
551818534a1Smrg    nOldSyms = XkbKeyNumSyms(xkb, key);
552818534a1Smrg    if (nOldSyms >= (unsigned) needed) {
553818534a1Smrg        return XkbKeySymsPtr(xkb, key);
554818534a1Smrg    }
555818534a1Smrg    if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
556818534a1Smrg        if (nOldSyms > 0) {
557818534a1Smrg            memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
558818534a1Smrg                   nOldSyms * sizeof(KeySym));
559818534a1Smrg        }
560818534a1Smrg        if ((needed - nOldSyms) > 0) {
561818534a1Smrg            bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)],
562818534a1Smrg                  (needed - nOldSyms) * sizeof(KeySym));
563818534a1Smrg        }
564818534a1Smrg        xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
565818534a1Smrg        xkb->map->num_syms += needed;
566818534a1Smrg        return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
567818534a1Smrg    }
568818534a1Smrg    xkb->map->size_syms += (needed > 32 ? needed : 32);
569818534a1Smrg    newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
570818534a1Smrg    if (newSyms == NULL)
571818534a1Smrg        return NULL;
572818534a1Smrg    newSyms[0] = NoSymbol;
5731ab64890Smrg    nSyms = 1;
574818534a1Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
575818534a1Smrg        int nCopy;
576818534a1Smrg
577818534a1Smrg        nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
578818534a1Smrg        if ((nKeySyms == 0) && (i != key))
579818534a1Smrg            continue;
580818534a1Smrg        if (i == key)
581818534a1Smrg            nKeySyms = needed;
582818534a1Smrg        if (nCopy != 0)
583818534a1Smrg            memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
584818534a1Smrg                   nCopy * sizeof(KeySym));
585818534a1Smrg        if (nKeySyms > nCopy)
586818534a1Smrg            bzero(&newSyms[nSyms + nCopy], (nKeySyms - nCopy) * sizeof(KeySym));
587818534a1Smrg        xkb->map->key_sym_map[i].offset = nSyms;
588818534a1Smrg        nSyms += nKeySyms;
5891ab64890Smrg    }
5901ab64890Smrg    _XkbFree(xkb->map->syms);
5911ab64890Smrg    xkb->map->syms = newSyms;
5921ab64890Smrg    xkb->map->num_syms = nSyms;
5931ab64890Smrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
5941ab64890Smrg}
5951ab64890Smrg
5961ab64890Smrgstatic unsigned
597818534a1Smrg_ExtendRange(unsigned int old_flags,
598818534a1Smrg             unsigned int flag,
599818534a1Smrg             KeyCode newKC,
600818534a1Smrg             KeyCode *old_min,
601818534a1Smrg             unsigned char *old_num)
6021ab64890Smrg{
603818534a1Smrg    if ((old_flags & flag) == 0) {
604818534a1Smrg        old_flags |= flag;
605818534a1Smrg        *old_min = newKC;
606818534a1Smrg        *old_num = 1;
6071ab64890Smrg    }
6081ab64890Smrg    else {
609818534a1Smrg        int last = (*old_min) + (*old_num) - 1;
610818534a1Smrg
611818534a1Smrg        if (newKC < *old_min) {
612818534a1Smrg            *old_min = newKC;
613818534a1Smrg            *old_num = (last - newKC) + 1;
614818534a1Smrg        }
615818534a1Smrg        else if (newKC > last) {
616818534a1Smrg            *old_num = (newKC - (*old_min)) + 1;
617818534a1Smrg        }
6181ab64890Smrg    }
6191ab64890Smrg    return old_flags;
6201ab64890Smrg}
6211ab64890Smrg
6221ab64890SmrgStatus
623818534a1SmrgXkbChangeKeycodeRange(XkbDescPtr xkb,
624818534a1Smrg                      int minKC,
625818534a1Smrg                      int maxKC,
626818534a1Smrg                      XkbChangesPtr changes)
6271ab64890Smrg{
628818534a1Smrg    int tmp;
629818534a1Smrg
630818534a1Smrg    if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
631818534a1Smrg        return BadValue;
632818534a1Smrg    if (minKC > maxKC)
633818534a1Smrg        return BadMatch;
634818534a1Smrg    if (minKC < xkb->min_key_code) {
635818534a1Smrg        if (changes)
636818534a1Smrg            changes->map.min_key_code = minKC;
637818534a1Smrg        tmp = xkb->min_key_code - minKC;
638818534a1Smrg        if (xkb->map) {
639818534a1Smrg            if (xkb->map->key_sym_map) {
640818534a1Smrg                bzero((char *) &xkb->map->key_sym_map[minKC],
641818534a1Smrg                      tmp * sizeof(XkbSymMapRec));
642818534a1Smrg                if (changes) {
643818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
644818534a1Smrg                                                XkbKeySymsMask, minKC,
645818534a1Smrg                                                &changes->map.first_key_sym,
646818534a1Smrg                                                &changes->map.num_key_syms);
647818534a1Smrg                }
648818534a1Smrg            }
649818534a1Smrg            if (xkb->map->modmap) {
650818534a1Smrg                bzero((char *) &xkb->map->modmap[minKC], tmp);
651818534a1Smrg                if (changes) {
652818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
653818534a1Smrg                                                XkbModifierMapMask, minKC,
654818534a1Smrg                                                &changes->map.first_modmap_key,
655818534a1Smrg                                                &changes->map.num_modmap_keys);
656818534a1Smrg                }
657818534a1Smrg            }
658818534a1Smrg        }
659818534a1Smrg        if (xkb->server) {
660818534a1Smrg            if (xkb->server->behaviors) {
661818534a1Smrg                bzero((char *) &xkb->server->behaviors[minKC],
662818534a1Smrg                      tmp * sizeof(XkbBehavior));
663818534a1Smrg                if (changes) {
664818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
665818534a1Smrg                                              XkbKeyBehaviorsMask, minKC,
666818534a1Smrg                                              &changes->map.first_key_behavior,
667818534a1Smrg                                              &changes->map.num_key_behaviors);
668818534a1Smrg                }
669818534a1Smrg            }
670818534a1Smrg            if (xkb->server->key_acts) {
671818534a1Smrg                bzero((char *) &xkb->server->key_acts[minKC],
672818534a1Smrg                      tmp * sizeof(unsigned short));
673818534a1Smrg                if (changes) {
674818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
675818534a1Smrg                                                XkbKeyActionsMask, minKC,
676818534a1Smrg                                                &changes->map.first_key_act,
677818534a1Smrg                                                &changes->map.num_key_acts);
678818534a1Smrg                }
679818534a1Smrg            }
680818534a1Smrg            if (xkb->server->vmodmap) {
681818534a1Smrg                bzero((char *) &xkb->server->vmodmap[minKC],
682818534a1Smrg                      tmp * sizeof(unsigned short));
683818534a1Smrg                if (changes) {
684818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
685818534a1Smrg                                                XkbVirtualModMapMask, minKC,
6860ef0e59aSmrg                                                &changes->map.first_vmodmap_key,
687818534a1Smrg                                                &changes->map.num_vmodmap_keys);
688818534a1Smrg                }
689818534a1Smrg            }
690818534a1Smrg        }
691818534a1Smrg        if ((xkb->names) && (xkb->names->keys)) {
692818534a1Smrg            bzero((char *) &xkb->names->keys[minKC],
693818534a1Smrg                  tmp * sizeof(XkbKeyNameRec));
694818534a1Smrg            if (changes) {
695818534a1Smrg                changes->names.changed = _ExtendRange(changes->names.changed,
696818534a1Smrg                                                      XkbKeyNamesMask, minKC,
697818534a1Smrg                                                      &changes->names.first_key,
698818534a1Smrg                                                      &changes->names.num_keys);
699818534a1Smrg            }
700818534a1Smrg        }
701818534a1Smrg        xkb->min_key_code = minKC;
702818534a1Smrg    }
703818534a1Smrg    if (maxKC > xkb->max_key_code) {
704818534a1Smrg        if (changes)
705818534a1Smrg            changes->map.max_key_code = maxKC;
706818534a1Smrg        tmp = maxKC - xkb->max_key_code;
707818534a1Smrg        if (xkb->map) {
708818534a1Smrg            if (xkb->map->key_sym_map) {
709f2d49d05Smrg                _XkbResizeArray(xkb->map->key_sym_map, xkb->max_key_code + 1,
710f2d49d05Smrg                                (maxKC + 1), XkbSymMapRec);
711818534a1Smrg                if (!xkb->map->key_sym_map) {
712818534a1Smrg                    return BadAlloc;
713818534a1Smrg                }
714818534a1Smrg                if (changes) {
715818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
716818534a1Smrg                                                XkbKeySymsMask, maxKC,
717818534a1Smrg                                                &changes->map.first_key_sym,
718818534a1Smrg                                                &changes->map.num_key_syms);
719818534a1Smrg                }
720818534a1Smrg            }
721818534a1Smrg            if (xkb->map->modmap) {
722f2d49d05Smrg                _XkbResizeArray(xkb->map->modmap, xkb->max_key_code + 1,
723f2d49d05Smrg                                (maxKC + 1), unsigned char);
724818534a1Smrg                if (!xkb->map->modmap) {
725818534a1Smrg                    return BadAlloc;
726818534a1Smrg                }
727818534a1Smrg                if (changes) {
728818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
729818534a1Smrg                                                XkbModifierMapMask, maxKC,
730818534a1Smrg                                                &changes->map.first_modmap_key,
731818534a1Smrg                                                &changes->map.num_modmap_keys);
732818534a1Smrg                }
733818534a1Smrg            }
734818534a1Smrg        }
735818534a1Smrg        if (xkb->server) {
736818534a1Smrg            if (xkb->server->behaviors) {
737f2d49d05Smrg                _XkbResizeArray(xkb->server->behaviors, xkb->max_key_code + 1,
738f2d49d05Smrg                                (maxKC + 1), XkbBehavior);
739818534a1Smrg                if (!xkb->server->behaviors) {
740818534a1Smrg                    return BadAlloc;
741818534a1Smrg                }
742818534a1Smrg                if (changes) {
743818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
744818534a1Smrg                                                XkbKeyBehaviorsMask, maxKC,
745818534a1Smrg                                                &changes->map.first_key_behavior,
746818534a1Smrg                                                &changes->map.num_key_behaviors);
747818534a1Smrg                }
748818534a1Smrg            }
749818534a1Smrg            if (xkb->server->key_acts) {
750f2d49d05Smrg                _XkbResizeArray(xkb->server->key_acts, xkb->max_key_code + 1,
751f2d49d05Smrg                                (maxKC + 1), unsigned short);
752818534a1Smrg                if (!xkb->server->key_acts) {
753818534a1Smrg                    return BadAlloc;
754818534a1Smrg                }
755818534a1Smrg                if (changes) {
756818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
757818534a1Smrg                                                XkbKeyActionsMask, maxKC,
758818534a1Smrg                                                &changes->map.first_key_act,
759818534a1Smrg                                                &changes->map.num_key_acts);
760818534a1Smrg                }
761818534a1Smrg            }
762818534a1Smrg            if (xkb->server->vmodmap) {
763f2d49d05Smrg                _XkbResizeArray(xkb->server->vmodmap, xkb->max_key_code + 1,
764f2d49d05Smrg                                (maxKC + 1), unsigned short);
765818534a1Smrg                if (!xkb->server->vmodmap) {
766818534a1Smrg                    return BadAlloc;
767818534a1Smrg                }
768818534a1Smrg                if (changes) {
769818534a1Smrg                    changes->map.changed = _ExtendRange(changes->map.changed,
770818534a1Smrg                                                XkbVirtualModMapMask, maxKC,
7710ef0e59aSmrg                                                &changes->map.first_vmodmap_key,
772818534a1Smrg                                                &changes->map.num_vmodmap_keys);
773818534a1Smrg                }
774818534a1Smrg            }
775818534a1Smrg        }
776818534a1Smrg        if ((xkb->names) && (xkb->names->keys)) {
777f2d49d05Smrg            _XkbResizeArray(xkb->names->keys, xkb->max_key_code + 1,
778f2d49d05Smrg                            (maxKC + 1), XkbKeyNameRec);
779818534a1Smrg            if (!xkb->names->keys) {
780818534a1Smrg                return BadAlloc;
781818534a1Smrg            }
782818534a1Smrg            if (changes) {
783818534a1Smrg                changes->names.changed = _ExtendRange(changes->names.changed,
784818534a1Smrg                                                      XkbKeyNamesMask, maxKC,
785818534a1Smrg                                                      &changes->names.first_key,
786818534a1Smrg                                                      &changes->names.num_keys);
787818534a1Smrg            }
788818534a1Smrg        }
789818534a1Smrg        xkb->max_key_code = maxKC;
7901ab64890Smrg    }
7911ab64890Smrg    return Success;
7921ab64890Smrg}
7931ab64890Smrg
7941ab64890SmrgXkbAction *
795818534a1SmrgXkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
7961ab64890Smrg{
797818534a1Smrg    register int i, nActs;
798818534a1Smrg    XkbAction *newActs;
799818534a1Smrg
8006e467124Smrg    if (needed <= 0) {
801818534a1Smrg        xkb->server->key_acts[key] = 0;
802818534a1Smrg        return NULL;
803818534a1Smrg    }
804818534a1Smrg    if (XkbKeyHasActions(xkb, key) &&
805818534a1Smrg        (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
806818534a1Smrg        return XkbKeyActionsPtr(xkb, key);
807818534a1Smrg    if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
808818534a1Smrg        xkb->server->key_acts[key] = xkb->server->num_acts;
809818534a1Smrg        xkb->server->num_acts += needed;
810818534a1Smrg        return &xkb->server->acts[xkb->server->key_acts[key]];
811818534a1Smrg    }
812818534a1Smrg    xkb->server->size_acts = xkb->server->num_acts + needed + 8;
813818534a1Smrg    newActs = _XkbTypedCalloc(xkb->server->size_acts, XkbAction);
814818534a1Smrg    if (newActs == NULL)
815818534a1Smrg        return NULL;
8161ab64890Smrg    newActs[0].type = XkbSA_NoAction;
8171ab64890Smrg    nActs = 1;
818818534a1Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
819818534a1Smrg        int nKeyActs, nCopy;
820818534a1Smrg
821818534a1Smrg        if ((xkb->server->key_acts[i] == 0) && (i != key))
822818534a1Smrg            continue;
823818534a1Smrg
824818534a1Smrg        nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
825818534a1Smrg        if (i == key) {
826818534a1Smrg            nKeyActs = needed;
827818534a1Smrg            if (needed < nCopy)
828818534a1Smrg                nCopy = needed;
829818534a1Smrg        }
830818534a1Smrg
831818534a1Smrg        if (nCopy > 0)
832818534a1Smrg            memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
833818534a1Smrg                   nCopy * sizeof(XkbAction));
834818534a1Smrg        if (nCopy < nKeyActs)
835818534a1Smrg            bzero(&newActs[nActs + nCopy],
836818534a1Smrg                  (nKeyActs - nCopy) * sizeof(XkbAction));
837818534a1Smrg        xkb->server->key_acts[i] = nActs;
838818534a1Smrg        nActs += nKeyActs;
8391ab64890Smrg    }
8401ab64890Smrg    _XkbFree(xkb->server->acts);
8411ab64890Smrg    xkb->server->acts = newActs;
842818534a1Smrg    xkb->server->num_acts = nActs;
8431ab64890Smrg    return &xkb->server->acts[xkb->server->key_acts[key]];
8441ab64890Smrg}
8451ab64890Smrg
8461ab64890Smrgvoid
847818534a1SmrgXkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
8481ab64890Smrg{
849818534a1Smrg    XkbClientMapPtr map;
8501ab64890Smrg
851818534a1Smrg    if ((xkb == NULL) || (xkb->map == NULL))
852818534a1Smrg        return;
8531ab64890Smrg    if (freeMap)
854818534a1Smrg        what = XkbAllClientInfoMask;
855818534a1Smrg    map = xkb->map;
856818534a1Smrg    if (what & XkbKeyTypesMask) {
857818534a1Smrg        if (map->types != NULL) {
858818534a1Smrg            if (map->num_types > 0) {
859818534a1Smrg                register int i;
860818534a1Smrg                XkbKeyTypePtr type;
861818534a1Smrg
862818534a1Smrg                for (i = 0, type = map->types; i < map->num_types; i++, type++) {
863cf2acddeSmrg                    _XkbFree(type->map);
864cf2acddeSmrg                    type->map = NULL;
865cf2acddeSmrg
866cf2acddeSmrg                    _XkbFree(type->preserve);
867cf2acddeSmrg                    type->preserve = NULL;
868cf2acddeSmrg
869818534a1Smrg                    type->map_count = 0;
870cf2acddeSmrg
871cf2acddeSmrg                    _XkbFree(type->level_names);
872cf2acddeSmrg                    type->level_names = NULL;
873818534a1Smrg                }
874818534a1Smrg            }
875818534a1Smrg            _XkbFree(map->types);
876818534a1Smrg            map->num_types = map->size_types = 0;
877818534a1Smrg            map->types = NULL;
878818534a1Smrg        }
879818534a1Smrg    }
880818534a1Smrg    if (what & XkbKeySymsMask) {
881cf2acddeSmrg        _XkbFree(map->key_sym_map);
882cf2acddeSmrg        map->key_sym_map = NULL;
883cf2acddeSmrg
884cf2acddeSmrg        _XkbFree(map->syms);
885cf2acddeSmrg        map->size_syms = map->num_syms = 0;
886cf2acddeSmrg        map->syms = NULL;
887818534a1Smrg    }
888cf2acddeSmrg    if (what & XkbModifierMapMask) {
889818534a1Smrg        _XkbFree(map->modmap);
890818534a1Smrg        map->modmap = NULL;
8911ab64890Smrg    }
8921ab64890Smrg    if (freeMap) {
893818534a1Smrg        _XkbFree(xkb->map);
894818534a1Smrg        xkb->map = NULL;
8951ab64890Smrg    }
8961ab64890Smrg    return;
8971ab64890Smrg}
8981ab64890Smrg
8991ab64890Smrgvoid
900818534a1SmrgXkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
9011ab64890Smrg{
902818534a1Smrg    XkbServerMapPtr map;
9031ab64890Smrg
904818534a1Smrg    if ((xkb == NULL) || (xkb->server == NULL))
905818534a1Smrg        return;
9061ab64890Smrg    if (freeMap)
907818534a1Smrg        what = XkbAllServerInfoMask;
908818534a1Smrg    map = xkb->server;
909cf2acddeSmrg    if (what & XkbExplicitComponentsMask) {
910818534a1Smrg        _XkbFree(map->explicit);
911818534a1Smrg        map->explicit = NULL;
912818534a1Smrg    }
913818534a1Smrg    if (what & XkbKeyActionsMask) {
914cf2acddeSmrg           _XkbFree(map->key_acts);
915818534a1Smrg            map->key_acts = NULL;
916cf2acddeSmrg
917cf2acddeSmrg           _XkbFree(map->acts);
918818534a1Smrg            map->num_acts = map->size_acts = 0;
919818534a1Smrg            map->acts = NULL;
920818534a1Smrg    }
921cf2acddeSmrg    if (what & XkbKeyBehaviorsMask) {
922818534a1Smrg        _XkbFree(map->behaviors);
923818534a1Smrg        map->behaviors = NULL;
924818534a1Smrg    }
925cf2acddeSmrg    if (what & XkbVirtualModMapMask)  {
926818534a1Smrg        _XkbFree(map->vmodmap);
927818534a1Smrg        map->vmodmap = NULL;
9281ab64890Smrg    }
9291ab64890Smrg
9301ab64890Smrg    if (freeMap) {
931818534a1Smrg        _XkbFree(xkb->server);
932818534a1Smrg        xkb->server = NULL;
9331ab64890Smrg    }
9341ab64890Smrg    return;
9351ab64890Smrg}
936