XKBAlloc.c revision 258a0ebe
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    if (which & XkbControlsMask)
302        XkbFreeControls(xkb, XkbAllControlsMask, True);
303    if (freeAll)
304        _XkbFree(xkb);
305    return;
306}
307
308/***====================================================================***/
309
310XkbDeviceLedInfoPtr
311XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi, unsigned ledClass, unsigned ledId)
312{
313    XkbDeviceLedInfoPtr devli;
314    register int i;
315
316    if ((!devi) || (!XkbSingleXIClass(ledClass)) || (!XkbSingleXIId(ledId)))
317        return NULL;
318    for (i = 0, devli = devi->leds; i < devi->num_leds; i++, devli++) {
319        if ((devli->led_class == ledClass) && (devli->led_id == ledId))
320            return devli;
321    }
322    if (devi->num_leds >= devi->sz_leds) {
323        if (devi->sz_leds > 0)
324            devi->sz_leds *= 2;
325        else
326            devi->sz_leds = 1;
327        _XkbResizeArray(devi->leds, devi->num_leds, devi->sz_leds,
328                        XkbDeviceLedInfoRec);
329        if (!devi->leds) {
330            devi->sz_leds = devi->num_leds = 0;
331            return NULL;
332        }
333        i = devi->num_leds;
334        for (devli = &devi->leds[i]; i < devi->sz_leds; i++, devli++) {
335            bzero(devli, sizeof(XkbDeviceLedInfoRec));
336            devli->led_class = XkbXINone;
337            devli->led_id = XkbXINone;
338        }
339    }
340    devli = &devi->leds[devi->num_leds++];
341    bzero(devli, sizeof(XkbDeviceLedInfoRec));
342    devli->led_class = ledClass;
343    devli->led_id = ledId;
344    return devli;
345}
346
347Status
348XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi, unsigned newTotal)
349{
350    if ((!devi) || (newTotal > 255))
351        return BadValue;
352    if ((devi->btn_acts != NULL) && (newTotal == devi->num_btns))
353        return Success;
354    if (newTotal == 0) {
355        if (devi->btn_acts != NULL) {
356            _XkbFree(devi->btn_acts);
357            devi->btn_acts = NULL;
358        }
359        devi->num_btns = 0;
360        return Success;
361    }
362    _XkbResizeArray(devi->btn_acts, devi->num_btns, newTotal, XkbAction);
363    if (devi->btn_acts == NULL) {
364        devi->num_btns = 0;
365        return BadAlloc;
366    }
367    if (newTotal > devi->num_btns) {
368        XkbAction *act;
369
370        act = &devi->btn_acts[devi->num_btns];
371        bzero((char *) act, (newTotal - devi->num_btns) * sizeof(XkbAction));
372    }
373    devi->num_btns = newTotal;
374    return Success;
375}
376
377/*ARGSUSED*/
378XkbDeviceInfoPtr
379XkbAllocDeviceInfo(unsigned deviceSpec, unsigned nButtons, unsigned szLeds)
380{
381    XkbDeviceInfoPtr devi;
382
383    devi = _XkbTypedCalloc(1, XkbDeviceInfoRec);
384    if (devi != NULL) {
385        devi->device_spec = deviceSpec;
386        devi->has_own_state = False;
387        devi->num_btns = 0;
388        devi->btn_acts = NULL;
389        if (nButtons > 0) {
390            devi->num_btns = nButtons;
391            devi->btn_acts = _XkbTypedCalloc(nButtons, XkbAction);
392            if (!devi->btn_acts) {
393                _XkbFree(devi);
394                return NULL;
395            }
396        }
397        devi->dflt_kbd_fb = XkbXINone;
398        devi->dflt_led_fb = XkbXINone;
399        devi->num_leds = 0;
400        devi->sz_leds = 0;
401        devi->leds = NULL;
402        if (szLeds > 0) {
403            devi->sz_leds = szLeds;
404            devi->leds = _XkbTypedCalloc(szLeds, XkbDeviceLedInfoRec);
405            if (!devi->leds) {
406                _XkbFree(devi->btn_acts);
407                _XkbFree(devi);
408                return NULL;
409            }
410        }
411    }
412    return devi;
413}
414
415
416void
417XkbFreeDeviceInfo(XkbDeviceInfoPtr devi, unsigned which, Bool freeDevI)
418{
419    if (devi) {
420        if (freeDevI) {
421            which = XkbXI_AllDeviceFeaturesMask;
422            if (devi->name) {
423                _XkbFree(devi->name);
424                devi->name = NULL;
425            }
426        }
427        if ((which & XkbXI_ButtonActionsMask) && (devi->btn_acts)) {
428            _XkbFree(devi->btn_acts);
429            devi->num_btns = 0;
430            devi->btn_acts = NULL;
431        }
432        if ((which & XkbXI_IndicatorsMask) && (devi->leds)) {
433            register int i;
434
435            if ((which & XkbXI_IndicatorsMask) == XkbXI_IndicatorsMask) {
436                _XkbFree(devi->leds);
437                devi->sz_leds = devi->num_leds = 0;
438                devi->leds = NULL;
439            }
440            else {
441                XkbDeviceLedInfoPtr devli;
442
443                for (i = 0, devli = devi->leds; i < devi->num_leds;
444                     i++, devli++) {
445                    if (which & XkbXI_IndicatorMapsMask)
446                        bzero((char *) &devli->maps[0], sizeof(devli->maps));
447                    else
448                        bzero((char *) &devli->names[0], sizeof(devli->names));
449                }
450            }
451        }
452        if (freeDevI)
453            _XkbFree(devi);
454    }
455    return;
456}
457