XKBAlloc.c revision 0f8248bf
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 "XKBlibint.h"
351ab64890Smrg#include <X11/extensions/XKBgeom.h>
361ab64890Smrg#include <X11/extensions/XKBproto.h>
371ab64890Smrg#include "XKBlibint.h"
381ab64890Smrg
391ab64890Smrg
401ab64890Smrg/***===================================================================***/
411ab64890Smrg
421ab64890Smrg/*ARGSUSED*/
431ab64890SmrgStatus
44818534a1SmrgXkbAllocCompatMap(XkbDescPtr xkb, unsigned which, unsigned nSI)
451ab64890Smrg{
46818534a1Smrg    XkbCompatMapPtr compat;
47818534a1Smrg    XkbSymInterpretRec *prev_interpret;
481ab64890Smrg
491ab64890Smrg    if (!xkb)
50818534a1Smrg        return BadMatch;
511ab64890Smrg    if (xkb->compat) {
52818534a1Smrg        if (xkb->compat->size_si >= nSI)
53818534a1Smrg            return Success;
54818534a1Smrg        compat = xkb->compat;
55818534a1Smrg        compat->size_si = nSI;
56818534a1Smrg        if (compat->sym_interpret == NULL)
57818534a1Smrg            compat->num_si = 0;
58818534a1Smrg        prev_interpret = compat->sym_interpret;
59818534a1Smrg        compat->sym_interpret = _XkbTypedRealloc(compat->sym_interpret,
60818534a1Smrg                                                 nSI, XkbSymInterpretRec);
61818534a1Smrg        if (compat->sym_interpret == NULL) {
62818534a1Smrg            _XkbFree(prev_interpret);
63818534a1Smrg            compat->size_si = compat->num_si = 0;
64818534a1Smrg            return BadAlloc;
65818534a1Smrg        }
66818534a1Smrg        if (compat->num_si != 0) {
67818534a1Smrg            _XkbClearElems(compat->sym_interpret, compat->num_si,
68818534a1Smrg                           compat->size_si - 1, XkbSymInterpretRec);
69818534a1Smrg        }
70818534a1Smrg        return Success;
711ab64890Smrg    }
72818534a1Smrg    compat = _XkbTypedCalloc(1, XkbCompatMapRec);
73818534a1Smrg    if (compat == NULL)
74818534a1Smrg        return BadAlloc;
75818534a1Smrg    if (nSI > 0) {
76818534a1Smrg        compat->sym_interpret = _XkbTypedCalloc(nSI, XkbSymInterpretRec);
77818534a1Smrg        if (!compat->sym_interpret) {
78818534a1Smrg            _XkbFree(compat);
79818534a1Smrg            return BadAlloc;
80818534a1Smrg        }
811ab64890Smrg    }
82818534a1Smrg    compat->size_si = nSI;
83818534a1Smrg    compat->num_si = 0;
84818534a1Smrg    bzero((char *) &compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
85818534a1Smrg    xkb->compat = compat;
861ab64890Smrg    return Success;
871ab64890Smrg}
881ab64890Smrg
891ab64890Smrg
901ab64890Smrgvoid
91818534a1SmrgXkbFreeCompatMap(XkbDescPtr xkb, unsigned which, Bool freeMap)
921ab64890Smrg{
93818534a1Smrg    register XkbCompatMapPtr compat;
941ab64890Smrg
95818534a1Smrg    if ((xkb == NULL) || (xkb->compat == NULL))
96818534a1Smrg        return;
97818534a1Smrg    compat = xkb->compat;
981ab64890Smrg    if (freeMap)
99818534a1Smrg        which = XkbAllCompatMask;
100818534a1Smrg    if (which & XkbGroupCompatMask)
101818534a1Smrg        bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
102818534a1Smrg    if (which & XkbSymInterpMask) {
103818534a1Smrg        if ((compat->sym_interpret) && (compat->size_si > 0))
104818534a1Smrg            _XkbFree(compat->sym_interpret);
105818534a1Smrg        compat->size_si = compat->num_si = 0;
106818534a1Smrg        compat->sym_interpret = NULL;
1071ab64890Smrg    }
1081ab64890Smrg    if (freeMap) {
109818534a1Smrg        _XkbFree(compat);
110818534a1Smrg        xkb->compat = NULL;
1111ab64890Smrg    }
1121ab64890Smrg    return;
1131ab64890Smrg}
1141ab64890Smrg
1151ab64890Smrg/***===================================================================***/
1161ab64890Smrg
1171ab64890SmrgStatus
118818534a1SmrgXkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
1191ab64890Smrg{
120818534a1Smrg    XkbNamesPtr names;
121818534a1Smrg
122818534a1Smrg    if (xkb == NULL)
123818534a1Smrg        return BadMatch;
124818534a1Smrg    if (xkb->names == NULL) {
125818534a1Smrg        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
126818534a1Smrg        if (xkb->names == NULL)
127818534a1Smrg            return BadAlloc;
1281ab64890Smrg    }
129818534a1Smrg    names = xkb->names;
130818534a1Smrg    if ((which & XkbKTLevelNamesMask) && (xkb->map != NULL) &&
131818534a1Smrg        (xkb->map->types != NULL)) {
132818534a1Smrg        register int i;
133818534a1Smrg        XkbKeyTypePtr type = xkb->map->types;
134818534a1Smrg
135818534a1Smrg        for (i = 0; i < xkb->map->num_types; i++, type++) {
136818534a1Smrg            if (type->level_names == NULL) {
137818534a1Smrg                type->level_names = _XkbTypedCalloc(type->num_levels, Atom);
138818534a1Smrg                if (type->level_names == NULL)
139818534a1Smrg                    return BadAlloc;
140818534a1Smrg            }
141818534a1Smrg        }
1421ab64890Smrg    }
143818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys == NULL)) {
144818534a1Smrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
145818534a1Smrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
146818534a1Smrg            (xkb->max_key_code < xkb->min_key_code))
147818534a1Smrg            return BadValue;
148818534a1Smrg        names->keys = _XkbTypedCalloc((xkb->max_key_code + 1), XkbKeyNameRec);
149818534a1Smrg        if (names->keys == NULL)
150818534a1Smrg            return BadAlloc;
1511ab64890Smrg    }
152818534a1Smrg    if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
153818534a1Smrg        if (names->key_aliases == NULL) {
154818534a1Smrg            names->key_aliases = _XkbTypedCalloc(nTotalAliases, XkbKeyAliasRec);
155818534a1Smrg        }
156818534a1Smrg        else if (nTotalAliases > names->num_key_aliases) {
157818534a1Smrg            XkbKeyAliasRec *prev_aliases = names->key_aliases;
158818534a1Smrg
159818534a1Smrg            names->key_aliases = _XkbTypedRealloc(names->key_aliases,
160818534a1Smrg                                                  nTotalAliases,
161818534a1Smrg                                                  XkbKeyAliasRec);
162818534a1Smrg            if (names->key_aliases != NULL) {
163818534a1Smrg                _XkbClearElems(names->key_aliases, names->num_key_aliases,
164818534a1Smrg                               nTotalAliases - 1, XkbKeyAliasRec);
165818534a1Smrg            }
166818534a1Smrg            else {
167818534a1Smrg                _XkbFree(prev_aliases);
168818534a1Smrg            }
169818534a1Smrg        }
170818534a1Smrg        if (names->key_aliases == NULL) {
171818534a1Smrg            names->num_key_aliases = 0;
172818534a1Smrg            return BadAlloc;
173818534a1Smrg        }
174818534a1Smrg        names->num_key_aliases = nTotalAliases;
1751ab64890Smrg    }
176818534a1Smrg    if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
177818534a1Smrg        if (names->radio_groups == NULL) {
178818534a1Smrg            names->radio_groups = _XkbTypedCalloc(nTotalRG, Atom);
179818534a1Smrg        }
180818534a1Smrg        else if (nTotalRG > names->num_rg) {
181818534a1Smrg            Atom *prev_radio_groups = names->radio_groups;
182818534a1Smrg
183818534a1Smrg            names->radio_groups =
184818534a1Smrg                _XkbTypedRealloc(names->radio_groups, nTotalRG, Atom);
185818534a1Smrg            if (names->radio_groups != NULL) {
186818534a1Smrg                _XkbClearElems(names->radio_groups, names->num_rg, nTotalRG - 1,
187818534a1Smrg                               Atom);
188818534a1Smrg            }
189818534a1Smrg            else {
190818534a1Smrg                _XkbFree(prev_radio_groups);
191818534a1Smrg            }
192818534a1Smrg        }
193818534a1Smrg        if (names->radio_groups == NULL)
194818534a1Smrg            return BadAlloc;
195818534a1Smrg        names->num_rg = nTotalRG;
1961ab64890Smrg    }
1971ab64890Smrg    return Success;
1981ab64890Smrg}
1991ab64890Smrg
2001ab64890Smrgvoid
201818534a1SmrgXkbFreeNames(XkbDescPtr xkb, unsigned which, Bool freeMap)
2021ab64890Smrg{
203818534a1Smrg    XkbNamesPtr names;
2041ab64890Smrg
205818534a1Smrg    if ((xkb == NULL) || (xkb->names == NULL))
206818534a1Smrg        return;
207818534a1Smrg    names = xkb->names;
2081ab64890Smrg    if (freeMap)
209818534a1Smrg        which = XkbAllNamesMask;
210818534a1Smrg    if (which & XkbKTLevelNamesMask) {
211818534a1Smrg        XkbClientMapPtr map = xkb->map;
212818534a1Smrg
213818534a1Smrg        if ((map != NULL) && (map->types != NULL)) {
214818534a1Smrg            register int i;
215818534a1Smrg            register XkbKeyTypePtr type;
216818534a1Smrg
217818534a1Smrg            type = map->types;
218818534a1Smrg            for (i = 0; i < map->num_types; i++, type++) {
219818534a1Smrg                if (type->level_names != NULL) {
220818534a1Smrg                    _XkbFree(type->level_names);
221818534a1Smrg                    type->level_names = NULL;
222818534a1Smrg                }
223818534a1Smrg            }
224818534a1Smrg        }
2251ab64890Smrg    }
226818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
227818534a1Smrg        _XkbFree(names->keys);
228818534a1Smrg        names->keys = NULL;
229818534a1Smrg        names->num_keys = 0;
2301ab64890Smrg    }
231818534a1Smrg    if ((which & XkbKeyAliasesMask) && (names->key_aliases)) {
232818534a1Smrg        _XkbFree(names->key_aliases);
233818534a1Smrg        names->key_aliases = NULL;
234818534a1Smrg        names->num_key_aliases = 0;
2351ab64890Smrg    }
236818534a1Smrg    if ((which & XkbRGNamesMask) && (names->radio_groups)) {
237818534a1Smrg        _XkbFree(names->radio_groups);
238818534a1Smrg        names->radio_groups = NULL;
239818534a1Smrg        names->num_rg = 0;
2401ab64890Smrg    }
2411ab64890Smrg    if (freeMap) {
242818534a1Smrg        _XkbFree(names);
243818534a1Smrg        xkb->names = NULL;
2441ab64890Smrg    }
2451ab64890Smrg    return;
2461ab64890Smrg}
2471ab64890Smrg
2481ab64890Smrg/***===================================================================***/
2491ab64890Smrg
2501ab64890Smrg/*ARGSUSED*/
2511ab64890SmrgStatus
252818534a1SmrgXkbAllocControls(XkbDescPtr xkb, unsigned which)
2531ab64890Smrg{
254818534a1Smrg    if (xkb == NULL)
255818534a1Smrg        return BadMatch;
2561ab64890Smrg
257818534a1Smrg    if (xkb->ctrls == NULL) {
258818534a1Smrg        xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
259818534a1Smrg        if (!xkb->ctrls)
260818534a1Smrg            return BadAlloc;
2611ab64890Smrg    }
2621ab64890Smrg    return Success;
2631ab64890Smrg}
2641ab64890Smrg
2651ab64890Smrg/*ARGSUSED*/
2661ab64890Smrgvoid
267818534a1SmrgXkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap)
2681ab64890Smrg{
269818534a1Smrg    if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) {
270818534a1Smrg        _XkbFree(xkb->ctrls);
271818534a1Smrg        xkb->ctrls = NULL;
2721ab64890Smrg    }
2731ab64890Smrg    return;
2741ab64890Smrg}
2751ab64890Smrg
2761ab64890Smrg/***===================================================================***/
2771ab64890Smrg
27861b2299dSmrgStatus
2791ab64890SmrgXkbAllocIndicatorMaps(XkbDescPtr xkb)
2801ab64890Smrg{
281818534a1Smrg    if (xkb == NULL)
282818534a1Smrg        return BadMatch;
283818534a1Smrg    if (xkb->indicators == NULL) {
284818534a1Smrg        xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
285818534a1Smrg        if (!xkb->indicators)
286818534a1Smrg            return BadAlloc;
2871ab64890Smrg    }
2881ab64890Smrg    return Success;
2891ab64890Smrg}
2901ab64890Smrg
2911ab64890Smrgvoid
2921ab64890SmrgXkbFreeIndicatorMaps(XkbDescPtr xkb)
2931ab64890Smrg{
294818534a1Smrg    if ((xkb != NULL) && (xkb->indicators != NULL)) {
295818534a1Smrg        _XkbFree(xkb->indicators);
296818534a1Smrg        xkb->indicators = NULL;
2971ab64890Smrg    }
2981ab64890Smrg    return;
2991ab64890Smrg}
3001ab64890Smrg
3011ab64890Smrg/***====================================================================***/
3021ab64890Smrg
303818534a1SmrgXkbDescRec *
3041ab64890SmrgXkbAllocKeyboard(void)
3051ab64890Smrg{
306818534a1Smrg    XkbDescRec *xkb;
3071ab64890Smrg
308818534a1Smrg    xkb = _XkbTypedCalloc(1, XkbDescRec);
3091ab64890Smrg    if (xkb)
310818534a1Smrg        xkb->device_spec = XkbUseCoreKbd;
3111ab64890Smrg    return xkb;
3121ab64890Smrg}
3131ab64890Smrg
3141ab64890Smrgvoid
315818534a1SmrgXkbFreeKeyboard(XkbDescPtr xkb, unsigned which, Bool freeAll)
3161ab64890Smrg{
317818534a1Smrg    if (xkb == NULL)
318818534a1Smrg        return;
3191ab64890Smrg    if (freeAll)
320818534a1Smrg        which = XkbAllComponentsMask;
321818534a1Smrg    if (which & XkbClientMapMask)
322818534a1Smrg        XkbFreeClientMap(xkb, XkbAllClientInfoMask, True);
323818534a1Smrg    if (which & XkbServerMapMask)
324818534a1Smrg        XkbFreeServerMap(xkb, XkbAllServerInfoMask, True);
325818534a1Smrg    if (which & XkbCompatMapMask)
326818534a1Smrg        XkbFreeCompatMap(xkb, XkbAllCompatMask, True);
327818534a1Smrg    if (which & XkbIndicatorMapMask)
328818534a1Smrg        XkbFreeIndicatorMaps(xkb);
329818534a1Smrg    if (which & XkbNamesMask)
330818534a1Smrg        XkbFreeNames(xkb, XkbAllNamesMask, True);
331818534a1Smrg    if ((which & XkbGeometryMask) && (xkb->geom != NULL))
332818534a1Smrg        XkbFreeGeometry(xkb->geom, XkbGeomAllMask, True);
333818534a1Smrg    if (which & XkbControlsMask)
334818534a1Smrg        XkbFreeControls(xkb, XkbAllControlsMask, True);
3351ab64890Smrg    if (freeAll)
336818534a1Smrg        _XkbFree(xkb);
3371ab64890Smrg    return;
3381ab64890Smrg}
3391ab64890Smrg
3401ab64890Smrg/***====================================================================***/
3411ab64890Smrg
3421ab64890SmrgXkbDeviceLedInfoPtr
343818534a1SmrgXkbAddDeviceLedInfo(XkbDeviceInfoPtr devi, unsigned ledClass, unsigned ledId)
3441ab64890Smrg{
345818534a1Smrg    XkbDeviceLedInfoPtr devli;
346818534a1Smrg    register int i;
347818534a1Smrg
348818534a1Smrg    if ((!devi) || (!XkbSingleXIClass(ledClass)) || (!XkbSingleXIId(ledId)))
349818534a1Smrg        return NULL;
350818534a1Smrg    for (i = 0, devli = devi->leds; i < devi->num_leds; i++, devli++) {
351818534a1Smrg        if ((devli->led_class == ledClass) && (devli->led_id == ledId))
352818534a1Smrg            return devli;
3531ab64890Smrg    }
354818534a1Smrg    if (devi->num_leds >= devi->sz_leds) {
355818534a1Smrg        XkbDeviceLedInfoRec *prev_leds = devi->leds;
356818534a1Smrg
357818534a1Smrg        if (devi->sz_leds > 0)
358818534a1Smrg            devi->sz_leds *= 2;
359818534a1Smrg        else
360818534a1Smrg            devi->sz_leds = 1;
361818534a1Smrg        devi->leds = _XkbTypedRealloc(devi->leds, devi->sz_leds,
362818534a1Smrg                                      XkbDeviceLedInfoRec);
363818534a1Smrg        if (!devi->leds) {
364818534a1Smrg            _XkbFree(prev_leds);
365818534a1Smrg            devi->sz_leds = devi->num_leds = 0;
366818534a1Smrg            return NULL;
367818534a1Smrg        }
368818534a1Smrg        i = devi->num_leds;
369818534a1Smrg        for (devli = &devi->leds[i]; i < devi->sz_leds; i++, devli++) {
370818534a1Smrg            bzero(devli, sizeof(XkbDeviceLedInfoRec));
371818534a1Smrg            devli->led_class = XkbXINone;
372818534a1Smrg            devli->led_id = XkbXINone;
373818534a1Smrg        }
3741ab64890Smrg    }
375818534a1Smrg    devli = &devi->leds[devi->num_leds++];
376818534a1Smrg    bzero(devli, sizeof(XkbDeviceLedInfoRec));
377818534a1Smrg    devli->led_class = ledClass;
378818534a1Smrg    devli->led_id = ledId;
3791ab64890Smrg    return devli;
3801ab64890Smrg}
3811ab64890Smrg
3821ab64890SmrgStatus
383818534a1SmrgXkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi, unsigned newTotal)
3841ab64890Smrg{
3851ab64890Smrg    XkbAction *prev_btn_acts;
3861ab64890Smrg
387818534a1Smrg    if ((!devi) || (newTotal > 255))
388818534a1Smrg        return BadValue;
389818534a1Smrg    if ((devi->btn_acts != NULL) && (newTotal == devi->num_btns))
390818534a1Smrg        return Success;
391818534a1Smrg    if (newTotal == 0) {
392818534a1Smrg        if (devi->btn_acts != NULL) {
393818534a1Smrg            _XkbFree(devi->btn_acts);
394818534a1Smrg            devi->btn_acts = NULL;
395818534a1Smrg        }
396818534a1Smrg        devi->num_btns = 0;
397818534a1Smrg        return Success;
3981ab64890Smrg    }
3991ab64890Smrg    prev_btn_acts = devi->btn_acts;
400818534a1Smrg    devi->btn_acts = _XkbTypedRealloc(devi->btn_acts, newTotal, XkbAction);
401818534a1Smrg    if (devi->btn_acts == NULL) {
402818534a1Smrg        _XkbFree(prev_btn_acts);
403818534a1Smrg        devi->num_btns = 0;
404818534a1Smrg        return BadAlloc;
4051ab64890Smrg    }
406818534a1Smrg    if (newTotal > devi->num_btns) {
407818534a1Smrg        XkbAction *act;
408818534a1Smrg
409818534a1Smrg        act = &devi->btn_acts[devi->num_btns];
410818534a1Smrg        bzero((char *) act, (newTotal - devi->num_btns) * sizeof(XkbAction));
4111ab64890Smrg    }
412818534a1Smrg    devi->num_btns = newTotal;
4131ab64890Smrg    return Success;
4141ab64890Smrg}
4151ab64890Smrg
4161ab64890Smrg/*ARGSUSED*/
4171ab64890SmrgXkbDeviceInfoPtr
418818534a1SmrgXkbAllocDeviceInfo(unsigned deviceSpec, unsigned nButtons, unsigned szLeds)
4191ab64890Smrg{
420818534a1Smrg    XkbDeviceInfoPtr devi;
421818534a1Smrg
422818534a1Smrg    devi = _XkbTypedCalloc(1, XkbDeviceInfoRec);
423818534a1Smrg    if (devi != NULL) {
424818534a1Smrg        devi->device_spec = deviceSpec;
425818534a1Smrg        devi->has_own_state = False;
426818534a1Smrg        devi->num_btns = 0;
427818534a1Smrg        devi->btn_acts = NULL;
428818534a1Smrg        if (nButtons > 0) {
429818534a1Smrg            devi->num_btns = nButtons;
430818534a1Smrg            devi->btn_acts = _XkbTypedCalloc(nButtons, XkbAction);
431818534a1Smrg            if (!devi->btn_acts) {
432818534a1Smrg                _XkbFree(devi);
433818534a1Smrg                return NULL;
434818534a1Smrg            }
435818534a1Smrg        }
436818534a1Smrg        devi->dflt_kbd_fb = XkbXINone;
437818534a1Smrg        devi->dflt_led_fb = XkbXINone;
438818534a1Smrg        devi->num_leds = 0;
439818534a1Smrg        devi->sz_leds = 0;
440818534a1Smrg        devi->leds = NULL;
441818534a1Smrg        if (szLeds > 0) {
442818534a1Smrg            devi->sz_leds = szLeds;
443818534a1Smrg            devi->leds = _XkbTypedCalloc(szLeds, XkbDeviceLedInfoRec);
444818534a1Smrg            if (!devi->leds) {
4450f8248bfSmrg                _XkbFree(devi->btn_acts);
446818534a1Smrg                _XkbFree(devi);
447818534a1Smrg                return NULL;
448818534a1Smrg            }
449818534a1Smrg        }
4501ab64890Smrg    }
4511ab64890Smrg    return devi;
4521ab64890Smrg}
4531ab64890Smrg
4541ab64890Smrg
45561b2299dSmrgvoid
456818534a1SmrgXkbFreeDeviceInfo(XkbDeviceInfoPtr devi, unsigned which, Bool freeDevI)
4571ab64890Smrg{
4581ab64890Smrg    if (devi) {
459818534a1Smrg        if (freeDevI) {
460818534a1Smrg            which = XkbXI_AllDeviceFeaturesMask;
461818534a1Smrg            if (devi->name) {
462818534a1Smrg                _XkbFree(devi->name);
463818534a1Smrg                devi->name = NULL;
464818534a1Smrg            }
465818534a1Smrg        }
466818534a1Smrg        if ((which & XkbXI_ButtonActionsMask) && (devi->btn_acts)) {
467818534a1Smrg            _XkbFree(devi->btn_acts);
468818534a1Smrg            devi->num_btns = 0;
469818534a1Smrg            devi->btn_acts = NULL;
470818534a1Smrg        }
471818534a1Smrg        if ((which & XkbXI_IndicatorsMask) && (devi->leds)) {
472818534a1Smrg            register int i;
473818534a1Smrg
474818534a1Smrg            if ((which & XkbXI_IndicatorsMask) == XkbXI_IndicatorsMask) {
475818534a1Smrg                _XkbFree(devi->leds);
476818534a1Smrg                devi->sz_leds = devi->num_leds = 0;
477818534a1Smrg                devi->leds = NULL;
478818534a1Smrg            }
479818534a1Smrg            else {
480818534a1Smrg                XkbDeviceLedInfoPtr devli;
481818534a1Smrg
482818534a1Smrg                for (i = 0, devli = devi->leds; i < devi->num_leds;
483818534a1Smrg                     i++, devli++) {
484818534a1Smrg                    if (which & XkbXI_IndicatorMapsMask)
485818534a1Smrg                        bzero((char *) &devli->maps[0], sizeof(devli->maps));
486818534a1Smrg                    else
487818534a1Smrg                        bzero((char *) &devli->names[0], sizeof(devli->names));
488818534a1Smrg                }
489818534a1Smrg            }
490818534a1Smrg        }
491818534a1Smrg        if (freeDevI)
492818534a1Smrg            _XkbFree(devi);
4931ab64890Smrg    }
4941ab64890Smrg    return;
4951ab64890Smrg}
496