XKBAlloc.c revision 3233502e
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    XkbSymInterpretRec *prev_interpret;
48
49    if (!xkb)
50        return BadMatch;
51    if (xkb->compat) {
52        if (xkb->compat->size_si >= nSI)
53            return Success;
54        compat = xkb->compat;
55        compat->size_si = nSI;
56        if (compat->sym_interpret == NULL)
57            compat->num_si = 0;
58        prev_interpret = compat->sym_interpret;
59        compat->sym_interpret = _XkbTypedRealloc(compat->sym_interpret,
60                                                 nSI, XkbSymInterpretRec);
61        if (compat->sym_interpret == NULL) {
62            _XkbFree(prev_interpret);
63            compat->size_si = compat->num_si = 0;
64            return BadAlloc;
65        }
66        if (compat->num_si != 0) {
67            _XkbClearElems(compat->sym_interpret, compat->num_si,
68                           compat->size_si - 1, XkbSymInterpretRec);
69        }
70        return Success;
71    }
72    compat = _XkbTypedCalloc(1, XkbCompatMapRec);
73    if (compat == NULL)
74        return BadAlloc;
75    if (nSI > 0) {
76        compat->sym_interpret = _XkbTypedCalloc(nSI, XkbSymInterpretRec);
77        if (!compat->sym_interpret) {
78            _XkbFree(compat);
79            return BadAlloc;
80        }
81    }
82    compat->size_si = nSI;
83    compat->num_si = 0;
84    bzero((char *) &compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
85    xkb->compat = compat;
86    return Success;
87}
88
89
90void
91XkbFreeCompatMap(XkbDescPtr xkb, unsigned which, Bool freeMap)
92{
93    register XkbCompatMapPtr compat;
94
95    if ((xkb == NULL) || (xkb->compat == NULL))
96        return;
97    compat = xkb->compat;
98    if (freeMap)
99        which = XkbAllCompatMask;
100    if (which & XkbGroupCompatMask)
101        bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbModsRec));
102    if (which & XkbSymInterpMask) {
103        if ((compat->sym_interpret) && (compat->size_si > 0))
104            _XkbFree(compat->sym_interpret);
105        compat->size_si = compat->num_si = 0;
106        compat->sym_interpret = NULL;
107    }
108    if (freeMap) {
109        _XkbFree(compat);
110        xkb->compat = NULL;
111    }
112    return;
113}
114
115/***===================================================================***/
116
117Status
118XkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
119{
120    XkbNamesPtr names;
121
122    if (xkb == NULL)
123        return BadMatch;
124    if (xkb->names == NULL) {
125        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
126        if (xkb->names == NULL)
127            return BadAlloc;
128    }
129    names = xkb->names;
130    if ((which & XkbKTLevelNamesMask) && (xkb->map != NULL) &&
131        (xkb->map->types != NULL)) {
132        register int i;
133        XkbKeyTypePtr type = xkb->map->types;
134
135        for (i = 0; i < xkb->map->num_types; i++, type++) {
136            if (type->level_names == NULL) {
137                type->level_names = _XkbTypedCalloc(type->num_levels, Atom);
138                if (type->level_names == NULL)
139                    return BadAlloc;
140            }
141        }
142    }
143    if ((which & XkbKeyNamesMask) && (names->keys == NULL)) {
144        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
145            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
146            (xkb->max_key_code < xkb->min_key_code))
147            return BadValue;
148        names->keys = _XkbTypedCalloc((xkb->max_key_code + 1), XkbKeyNameRec);
149        if (names->keys == NULL)
150            return BadAlloc;
151    }
152    if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
153        if (names->key_aliases == NULL) {
154            names->key_aliases = _XkbTypedCalloc(nTotalAliases, XkbKeyAliasRec);
155        }
156        else if (nTotalAliases > names->num_key_aliases) {
157            XkbKeyAliasRec *prev_aliases = names->key_aliases;
158
159            names->key_aliases = _XkbTypedRealloc(names->key_aliases,
160                                                  nTotalAliases,
161                                                  XkbKeyAliasRec);
162            if (names->key_aliases != NULL) {
163                _XkbClearElems(names->key_aliases, names->num_key_aliases,
164                               nTotalAliases - 1, XkbKeyAliasRec);
165            }
166            else {
167                _XkbFree(prev_aliases);
168            }
169        }
170        if (names->key_aliases == NULL) {
171            names->num_key_aliases = 0;
172            return BadAlloc;
173        }
174        names->num_key_aliases = nTotalAliases;
175    }
176    if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
177        if (names->radio_groups == NULL) {
178            names->radio_groups = _XkbTypedCalloc(nTotalRG, Atom);
179        }
180        else if (nTotalRG > names->num_rg) {
181            Atom *prev_radio_groups = names->radio_groups;
182
183            names->radio_groups =
184                _XkbTypedRealloc(names->radio_groups, nTotalRG, Atom);
185            if (names->radio_groups != NULL) {
186                _XkbClearElems(names->radio_groups, names->num_rg, nTotalRG - 1,
187                               Atom);
188            }
189            else {
190                _XkbFree(prev_radio_groups);
191            }
192        }
193        if (names->radio_groups == NULL)
194            return BadAlloc;
195        names->num_rg = nTotalRG;
196    }
197    return Success;
198}
199
200void
201XkbFreeNames(XkbDescPtr xkb, unsigned which, Bool freeMap)
202{
203    XkbNamesPtr names;
204
205    if ((xkb == NULL) || (xkb->names == NULL))
206        return;
207    names = xkb->names;
208    if (freeMap)
209        which = XkbAllNamesMask;
210    if (which & XkbKTLevelNamesMask) {
211        XkbClientMapPtr map = xkb->map;
212
213        if ((map != NULL) && (map->types != NULL)) {
214            register int i;
215            register XkbKeyTypePtr type;
216
217            type = map->types;
218            for (i = 0; i < map->num_types; i++, type++) {
219                    _XkbFree(type->level_names);
220                    type->level_names = NULL;
221            }
222        }
223    }
224    if (which & XkbKeyNamesMask) {
225        _XkbFree(names->keys);
226        names->keys = NULL;
227        names->num_keys = 0;
228    }
229    if (which & XkbKeyAliasesMask) {
230        _XkbFree(names->key_aliases);
231        names->key_aliases = NULL;
232        names->num_key_aliases = 0;
233    }
234    if (which & XkbRGNamesMask) {
235        _XkbFree(names->radio_groups);
236        names->radio_groups = NULL;
237        names->num_rg = 0;
238    }
239    if (freeMap) {
240        _XkbFree(names);
241        xkb->names = NULL;
242    }
243    return;
244}
245
246/***===================================================================***/
247
248/*ARGSUSED*/
249Status
250XkbAllocControls(XkbDescPtr xkb, unsigned which)
251{
252    if (xkb == NULL)
253        return BadMatch;
254
255    if (xkb->ctrls == NULL) {
256        xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
257        if (!xkb->ctrls)
258            return BadAlloc;
259    }
260    return Success;
261}
262
263/*ARGSUSED*/
264void
265XkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap)
266{
267    if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) {
268        _XkbFree(xkb->ctrls);
269        xkb->ctrls = NULL;
270    }
271    return;
272}
273
274/***===================================================================***/
275
276Status
277XkbAllocIndicatorMaps(XkbDescPtr xkb)
278{
279    if (xkb == NULL)
280        return BadMatch;
281    if (xkb->indicators == NULL) {
282        xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
283        if (!xkb->indicators)
284            return BadAlloc;
285    }
286    return Success;
287}
288
289void
290XkbFreeIndicatorMaps(XkbDescPtr xkb)
291{
292    if ((xkb != NULL) && (xkb->indicators != NULL)) {
293        _XkbFree(xkb->indicators);
294        xkb->indicators = NULL;
295    }
296    return;
297}
298
299/***====================================================================***/
300
301XkbDescRec *
302XkbAllocKeyboard(void)
303{
304    XkbDescRec *xkb;
305
306    xkb = _XkbTypedCalloc(1, XkbDescRec);
307    if (xkb)
308        xkb->device_spec = XkbUseCoreKbd;
309    return xkb;
310}
311
312void
313XkbFreeKeyboard(XkbDescPtr xkb, unsigned which, Bool freeAll)
314{
315    if (xkb == NULL)
316        return;
317    if (freeAll)
318        which = XkbAllComponentsMask;
319    if (which & XkbClientMapMask)
320        XkbFreeClientMap(xkb, XkbAllClientInfoMask, True);
321    if (which & XkbServerMapMask)
322        XkbFreeServerMap(xkb, XkbAllServerInfoMask, True);
323    if (which & XkbCompatMapMask)
324        XkbFreeCompatMap(xkb, XkbAllCompatMask, True);
325    if (which & XkbIndicatorMapMask)
326        XkbFreeIndicatorMaps(xkb);
327    if (which & XkbNamesMask)
328        XkbFreeNames(xkb, XkbAllNamesMask, True);
329    if ((which & XkbGeometryMask) && (xkb->geom != NULL))
330        XkbFreeGeometry(xkb->geom, XkbGeomAllMask, True);
331    if (which & XkbControlsMask)
332        XkbFreeControls(xkb, XkbAllControlsMask, True);
333    if (freeAll)
334        _XkbFree(xkb);
335    return;
336}
337
338/***====================================================================***/
339
340XkbDeviceLedInfoPtr
341XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi, unsigned ledClass, unsigned ledId)
342{
343    XkbDeviceLedInfoPtr devli;
344    register int i;
345
346    if ((!devi) || (!XkbSingleXIClass(ledClass)) || (!XkbSingleXIId(ledId)))
347        return NULL;
348    for (i = 0, devli = devi->leds; i < devi->num_leds; i++, devli++) {
349        if ((devli->led_class == ledClass) && (devli->led_id == ledId))
350            return devli;
351    }
352    if (devi->num_leds >= devi->sz_leds) {
353        XkbDeviceLedInfoRec *prev_leds = devi->leds;
354
355        if (devi->sz_leds > 0)
356            devi->sz_leds *= 2;
357        else
358            devi->sz_leds = 1;
359        devi->leds = _XkbTypedRealloc(devi->leds, devi->sz_leds,
360                                      XkbDeviceLedInfoRec);
361        if (!devi->leds) {
362            _XkbFree(prev_leds);
363            devi->sz_leds = devi->num_leds = 0;
364            return NULL;
365        }
366        i = devi->num_leds;
367        for (devli = &devi->leds[i]; i < devi->sz_leds; i++, devli++) {
368            bzero(devli, sizeof(XkbDeviceLedInfoRec));
369            devli->led_class = XkbXINone;
370            devli->led_id = XkbXINone;
371        }
372    }
373    devli = &devi->leds[devi->num_leds++];
374    bzero(devli, sizeof(XkbDeviceLedInfoRec));
375    devli->led_class = ledClass;
376    devli->led_id = ledId;
377    return devli;
378}
379
380Status
381XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi, unsigned newTotal)
382{
383    XkbAction *prev_btn_acts;
384
385    if ((!devi) || (newTotal > 255))
386        return BadValue;
387    if ((devi->btn_acts != NULL) && (newTotal == devi->num_btns))
388        return Success;
389    if (newTotal == 0) {
390        if (devi->btn_acts != NULL) {
391            _XkbFree(devi->btn_acts);
392            devi->btn_acts = NULL;
393        }
394        devi->num_btns = 0;
395        return Success;
396    }
397    prev_btn_acts = devi->btn_acts;
398    devi->btn_acts = _XkbTypedRealloc(devi->btn_acts, newTotal, XkbAction);
399    if (devi->btn_acts == NULL) {
400        _XkbFree(prev_btn_acts);
401        devi->num_btns = 0;
402        return BadAlloc;
403    }
404    if (newTotal > devi->num_btns) {
405        XkbAction *act;
406
407        act = &devi->btn_acts[devi->num_btns];
408        bzero((char *) act, (newTotal - devi->num_btns) * sizeof(XkbAction));
409    }
410    devi->num_btns = newTotal;
411    return Success;
412}
413
414/*ARGSUSED*/
415XkbDeviceInfoPtr
416XkbAllocDeviceInfo(unsigned deviceSpec, unsigned nButtons, unsigned szLeds)
417{
418    XkbDeviceInfoPtr devi;
419
420    devi = _XkbTypedCalloc(1, XkbDeviceInfoRec);
421    if (devi != NULL) {
422        devi->device_spec = deviceSpec;
423        devi->has_own_state = False;
424        devi->num_btns = 0;
425        devi->btn_acts = NULL;
426        if (nButtons > 0) {
427            devi->num_btns = nButtons;
428            devi->btn_acts = _XkbTypedCalloc(nButtons, XkbAction);
429            if (!devi->btn_acts) {
430                _XkbFree(devi);
431                return NULL;
432            }
433        }
434        devi->dflt_kbd_fb = XkbXINone;
435        devi->dflt_led_fb = XkbXINone;
436        devi->num_leds = 0;
437        devi->sz_leds = 0;
438        devi->leds = NULL;
439        if (szLeds > 0) {
440            devi->sz_leds = szLeds;
441            devi->leds = _XkbTypedCalloc(szLeds, XkbDeviceLedInfoRec);
442            if (!devi->leds) {
443                _XkbFree(devi->btn_acts);
444                _XkbFree(devi);
445                return NULL;
446            }
447        }
448    }
449    return devi;
450}
451
452
453void
454XkbFreeDeviceInfo(XkbDeviceInfoPtr devi, unsigned which, Bool freeDevI)
455{
456    if (devi) {
457        if (freeDevI) {
458            which = XkbXI_AllDeviceFeaturesMask;
459            if (devi->name) {
460                _XkbFree(devi->name);
461                devi->name = NULL;
462            }
463        }
464        if ((which & XkbXI_ButtonActionsMask) && (devi->btn_acts)) {
465            _XkbFree(devi->btn_acts);
466            devi->num_btns = 0;
467            devi->btn_acts = NULL;
468        }
469        if ((which & XkbXI_IndicatorsMask) && (devi->leds)) {
470            register int i;
471
472            if ((which & XkbXI_IndicatorsMask) == XkbXI_IndicatorsMask) {
473                _XkbFree(devi->leds);
474                devi->sz_leds = devi->num_leds = 0;
475                devi->leds = NULL;
476            }
477            else {
478                XkbDeviceLedInfoPtr devli;
479
480                for (i = 0, devli = devi->leds; i < devi->num_leds;
481                     i++, devli++) {
482                    if (which & XkbXI_IndicatorMapsMask)
483                        bzero((char *) &devli->maps[0], sizeof(devli->maps));
484                    else
485                        bzero((char *) &devli->names[0], sizeof(devli->names));
486                }
487            }
488        }
489        if (freeDevI)
490            _XkbFree(devi);
491    }
492    return;
493}
494