XKBAlloc.c revision 07fb9b8f
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31
32#include <stdio.h>
33#include "Xlibint.h"
34#include "XKBlibint.h"
35#include "X11/extensions/XKBgeom.h"
36#include <X11/extensions/XKBproto.h>
37#include "XKBlibint.h"
38
39
40/***===================================================================***/
41
42/*ARGSUSED*/
43Status
44XkbAllocCompatMap(XkbDescPtr xkb, unsigned which, unsigned nSI)
45{
46    XkbCompatMapPtr compat;
47
48    if (!xkb)
49        return BadMatch;
50    if (xkb->compat) {
51        if (xkb->compat->size_si >= nSI)
52            return Success;
53        compat = xkb->compat;
54        compat->size_si = nSI;
55        if (compat->sym_interpret == NULL)
56            compat->num_si = 0;
57        _XkbResizeArray(compat->sym_interpret, compat->num_si,
58                        nSI, XkbSymInterpretRec);
59        if (compat->sym_interpret == NULL) {
60            compat->size_si = compat->num_si = 0;
61            return BadAlloc;
62        }
63        return Success;
64    }
65    compat = _XkbTypedCalloc(1, XkbCompatMapRec);
66    if (compat == NULL)
67        return BadAlloc;
68    if (nSI > 0) {
69        compat->sym_interpret = _XkbTypedCalloc(nSI, XkbSymInterpretRec);
70        if (!compat->sym_interpret) {
71            _XkbFree(compat);
72            return BadAlloc;
73        }
74    }
75    compat->size_si = nSI;
76    compat->num_si = 0;
77    bzero((char *) &compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
78    xkb->compat = compat;
79    return Success;
80}
81
82
83void
84XkbFreeCompatMap(XkbDescPtr xkb, unsigned which, Bool freeMap)
85{
86    register XkbCompatMapPtr compat;
87
88    if ((xkb == NULL) || (xkb->compat == NULL))
89        return;
90    compat = xkb->compat;
91    if (freeMap)
92        which = XkbAllCompatMask;
93    if (which & XkbGroupCompatMask)
94        bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
95    if (which & XkbSymInterpMask) {
96        if ((compat->sym_interpret) && (compat->size_si > 0))
97            _XkbFree(compat->sym_interpret);
98        compat->size_si = compat->num_si = 0;
99        compat->sym_interpret = NULL;
100    }
101    if (freeMap) {
102        _XkbFree(compat);
103        xkb->compat = NULL;
104    }
105    return;
106}
107
108/***===================================================================***/
109
110Status
111XkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
112{
113    XkbNamesPtr names;
114
115    if (xkb == NULL)
116        return BadMatch;
117    if (xkb->names == NULL) {
118        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
119        if (xkb->names == NULL)
120            return BadAlloc;
121    }
122    names = xkb->names;
123    if ((which & XkbKTLevelNamesMask) && (xkb->map != NULL) &&
124        (xkb->map->types != NULL)) {
125        register int i;
126        XkbKeyTypePtr type = xkb->map->types;
127
128        for (i = 0; i < xkb->map->num_types; i++, type++) {
129            if (type->level_names == NULL) {
130                type->level_names = _XkbTypedCalloc(type->num_levels, Atom);
131                if (type->level_names == NULL)
132                    return BadAlloc;
133            }
134        }
135    }
136    if ((which & XkbKeyNamesMask) && (names->keys == NULL)) {
137        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
138            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
139            (xkb->max_key_code < xkb->min_key_code))
140            return BadValue;
141        names->keys = _XkbTypedCalloc((xkb->max_key_code + 1), XkbKeyNameRec);
142        if (names->keys == NULL)
143            return BadAlloc;
144    }
145    if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
146        if ((names->key_aliases == NULL) ||
147            (nTotalAliases > names->num_key_aliases)) {
148            _XkbResizeArray(names->key_aliases, names->num_key_aliases,
149                            nTotalAliases, XkbKeyAliasRec);
150        }
151        if (names->key_aliases == NULL) {
152            names->num_key_aliases = 0;
153            return BadAlloc;
154        }
155        names->num_key_aliases = nTotalAliases;
156    }
157    if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
158        if ((names->radio_groups == NULL) || (nTotalRG > names->num_rg)) {
159            _XkbResizeArray(names->radio_groups, names->num_rg, nTotalRG, Atom);
160        }
161        if (names->radio_groups == NULL) {
162            names->num_rg = 0;
163            return BadAlloc;
164        }
165        names->num_rg = nTotalRG;
166    }
167    return Success;
168}
169
170void
171XkbFreeNames(XkbDescPtr xkb, unsigned which, Bool freeMap)
172{
173    XkbNamesPtr names;
174
175    if ((xkb == NULL) || (xkb->names == NULL))
176        return;
177    names = xkb->names;
178    if (freeMap)
179        which = XkbAllNamesMask;
180    if (which & XkbKTLevelNamesMask) {
181        XkbClientMapPtr map = xkb->map;
182
183        if ((map != NULL) && (map->types != NULL)) {
184            register int i;
185            register XkbKeyTypePtr type;
186
187            type = map->types;
188            for (i = 0; i < map->num_types; i++, type++) {
189                    _XkbFree(type->level_names);
190                    type->level_names = NULL;
191            }
192        }
193    }
194    if (which & XkbKeyNamesMask) {
195        _XkbFree(names->keys);
196        names->keys = NULL;
197        names->num_keys = 0;
198    }
199    if (which & XkbKeyAliasesMask) {
200        _XkbFree(names->key_aliases);
201        names->key_aliases = NULL;
202        names->num_key_aliases = 0;
203    }
204    if (which & XkbRGNamesMask) {
205        _XkbFree(names->radio_groups);
206        names->radio_groups = NULL;
207        names->num_rg = 0;
208    }
209    if (freeMap) {
210        _XkbFree(names);
211        xkb->names = NULL;
212    }
213    return;
214}
215
216/***===================================================================***/
217
218/*ARGSUSED*/
219Status
220XkbAllocControls(XkbDescPtr xkb, unsigned which)
221{
222    if (xkb == NULL)
223        return BadMatch;
224
225    if (xkb->ctrls == NULL) {
226        xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
227        if (!xkb->ctrls)
228            return BadAlloc;
229    }
230    return Success;
231}
232
233/*ARGSUSED*/
234void
235XkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap)
236{
237    if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) {
238        _XkbFree(xkb->ctrls);
239        xkb->ctrls = NULL;
240    }
241    return;
242}
243
244/***===================================================================***/
245
246Status
247XkbAllocIndicatorMaps(XkbDescPtr xkb)
248{
249    if (xkb == NULL)
250        return BadMatch;
251    if (xkb->indicators == NULL) {
252        xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
253        if (!xkb->indicators)
254            return BadAlloc;
255    }
256    return Success;
257}
258
259void
260XkbFreeIndicatorMaps(XkbDescPtr xkb)
261{
262    if ((xkb != NULL) && (xkb->indicators != NULL)) {
263        _XkbFree(xkb->indicators);
264        xkb->indicators = NULL;
265    }
266    return;
267}
268
269/***====================================================================***/
270
271XkbDescRec *
272XkbAllocKeyboard(void)
273{
274    XkbDescRec *xkb;
275
276    xkb = _XkbTypedCalloc(1, XkbDescRec);
277    if (xkb)
278        xkb->device_spec = XkbUseCoreKbd;
279    return xkb;
280}
281
282void
283XkbFreeKeyboard(XkbDescPtr xkb, unsigned which, Bool freeAll)
284{
285    if (xkb == NULL)
286        return;
287    if (freeAll)
288        which = XkbAllComponentsMask;
289    if (which & XkbClientMapMask)
290        XkbFreeClientMap(xkb, XkbAllClientInfoMask, True);
291    if (which & XkbServerMapMask)
292        XkbFreeServerMap(xkb, XkbAllServerInfoMask, True);
293    if (which & XkbCompatMapMask)
294        XkbFreeCompatMap(xkb, XkbAllCompatMask, True);
295    if (which & XkbIndicatorMapMask)
296        XkbFreeIndicatorMaps(xkb);
297    if (which & XkbNamesMask)
298        XkbFreeNames(xkb, XkbAllNamesMask, True);
299    if ((which & XkbGeometryMask) && (xkb->geom != NULL)) {
300        XkbFreeGeometry(xkb->geom, XkbGeomAllMask, True);
301        xkb->geom = NULL;
302    }
303    if (which & XkbControlsMask)
304        XkbFreeControls(xkb, XkbAllControlsMask, True);
305    if (freeAll)
306        _XkbFree(xkb);
307    return;
308}
309
310/***====================================================================***/
311
312XkbDeviceLedInfoPtr
313XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi, unsigned ledClass, unsigned ledId)
314{
315    XkbDeviceLedInfoPtr devli;
316    register int i;
317
318    if ((!devi) || (!XkbSingleXIClass(ledClass)) || (!XkbSingleXIId(ledId)))
319        return NULL;
320    for (i = 0, devli = devi->leds; i < devi->num_leds; i++, devli++) {
321        if ((devli->led_class == ledClass) && (devli->led_id == ledId))
322            return devli;
323    }
324    if (devi->num_leds >= devi->sz_leds) {
325        if (devi->sz_leds > 0)
326            devi->sz_leds *= 2;
327        else
328            devi->sz_leds = 1;
329        _XkbResizeArray(devi->leds, devi->num_leds, devi->sz_leds,
330                        XkbDeviceLedInfoRec);
331        if (!devi->leds) {
332            devi->sz_leds = devi->num_leds = 0;
333            return NULL;
334        }
335        i = devi->num_leds;
336        for (devli = &devi->leds[i]; i < devi->sz_leds; i++, devli++) {
337            bzero(devli, sizeof(XkbDeviceLedInfoRec));
338            devli->led_class = XkbXINone;
339            devli->led_id = XkbXINone;
340        }
341    }
342    devli = &devi->leds[devi->num_leds++];
343    bzero(devli, sizeof(XkbDeviceLedInfoRec));
344    devli->led_class = ledClass;
345    devli->led_id = ledId;
346    return devli;
347}
348
349Status
350XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi, unsigned newTotal)
351{
352    if ((!devi) || (newTotal > 255))
353        return BadValue;
354    if ((devi->btn_acts != NULL) && (newTotal == devi->num_btns))
355        return Success;
356    if (newTotal == 0) {
357        if (devi->btn_acts != NULL) {
358            _XkbFree(devi->btn_acts);
359            devi->btn_acts = NULL;
360        }
361        devi->num_btns = 0;
362        return Success;
363    }
364    _XkbResizeArray(devi->btn_acts, devi->num_btns, newTotal, XkbAction);
365    if (devi->btn_acts == NULL) {
366        devi->num_btns = 0;
367        return BadAlloc;
368    }
369    if (newTotal > devi->num_btns) {
370        XkbAction *act;
371
372        act = &devi->btn_acts[devi->num_btns];
373        bzero((char *) act, (newTotal - devi->num_btns) * sizeof(XkbAction));
374    }
375    devi->num_btns = newTotal;
376    return Success;
377}
378
379/*ARGSUSED*/
380XkbDeviceInfoPtr
381XkbAllocDeviceInfo(unsigned deviceSpec, unsigned nButtons, unsigned szLeds)
382{
383    XkbDeviceInfoPtr devi;
384
385    devi = _XkbTypedCalloc(1, XkbDeviceInfoRec);
386    if (devi != NULL) {
387        devi->device_spec = deviceSpec;
388        devi->has_own_state = False;
389        devi->num_btns = 0;
390        devi->btn_acts = NULL;
391        if (nButtons > 0) {
392            devi->num_btns = nButtons;
393            devi->btn_acts = _XkbTypedCalloc(nButtons, XkbAction);
394            if (!devi->btn_acts) {
395                _XkbFree(devi);
396                return NULL;
397            }
398        }
399        devi->dflt_kbd_fb = XkbXINone;
400        devi->dflt_led_fb = XkbXINone;
401        devi->num_leds = 0;
402        devi->sz_leds = 0;
403        devi->leds = NULL;
404        if (szLeds > 0) {
405            devi->sz_leds = szLeds;
406            devi->leds = _XkbTypedCalloc(szLeds, XkbDeviceLedInfoRec);
407            if (!devi->leds) {
408                _XkbFree(devi->btn_acts);
409                _XkbFree(devi);
410                return NULL;
411            }
412        }
413    }
414    return devi;
415}
416
417
418void
419XkbFreeDeviceInfo(XkbDeviceInfoPtr devi, unsigned which, Bool freeDevI)
420{
421    if (devi) {
422        if (freeDevI) {
423            which = XkbXI_AllDeviceFeaturesMask;
424            if (devi->name) {
425                _XkbFree(devi->name);
426                devi->name = NULL;
427            }
428        }
429        if ((which & XkbXI_ButtonActionsMask) && (devi->btn_acts)) {
430            _XkbFree(devi->btn_acts);
431            devi->num_btns = 0;
432            devi->btn_acts = NULL;
433        }
434        if ((which & XkbXI_IndicatorsMask) && (devi->leds)) {
435            register int i;
436
437            if ((which & XkbXI_IndicatorsMask) == XkbXI_IndicatorsMask) {
438                _XkbFree(devi->leds);
439                devi->sz_leds = devi->num_leds = 0;
440                devi->leds = NULL;
441            }
442            else {
443                XkbDeviceLedInfoPtr devli;
444
445                for (i = 0, devli = devi->leds; i < devi->num_leds;
446                     i++, devli++) {
447                    if (which & XkbXI_IndicatorMapsMask)
448                        bzero((char *) &devli->maps[0], sizeof(devli->maps));
449                    else
450                        bzero((char *) &devli->names[0], sizeof(devli->names));
451                }
452            }
453        }
454        if (freeDevI)
455            _XkbFree(devi);
456    }
457    return;
458}
459