XKBAlloc.c revision 0f8248bf
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                if (type->level_names != NULL) {
220                    _XkbFree(type->level_names);
221                    type->level_names = NULL;
222                }
223            }
224        }
225    }
226    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
227        _XkbFree(names->keys);
228        names->keys = NULL;
229        names->num_keys = 0;
230    }
231    if ((which & XkbKeyAliasesMask) && (names->key_aliases)) {
232        _XkbFree(names->key_aliases);
233        names->key_aliases = NULL;
234        names->num_key_aliases = 0;
235    }
236    if ((which & XkbRGNamesMask) && (names->radio_groups)) {
237        _XkbFree(names->radio_groups);
238        names->radio_groups = NULL;
239        names->num_rg = 0;
240    }
241    if (freeMap) {
242        _XkbFree(names);
243        xkb->names = NULL;
244    }
245    return;
246}
247
248/***===================================================================***/
249
250/*ARGSUSED*/
251Status
252XkbAllocControls(XkbDescPtr xkb, unsigned which)
253{
254    if (xkb == NULL)
255        return BadMatch;
256
257    if (xkb->ctrls == NULL) {
258        xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
259        if (!xkb->ctrls)
260            return BadAlloc;
261    }
262    return Success;
263}
264
265/*ARGSUSED*/
266void
267XkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap)
268{
269    if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) {
270        _XkbFree(xkb->ctrls);
271        xkb->ctrls = NULL;
272    }
273    return;
274}
275
276/***===================================================================***/
277
278Status
279XkbAllocIndicatorMaps(XkbDescPtr xkb)
280{
281    if (xkb == NULL)
282        return BadMatch;
283    if (xkb->indicators == NULL) {
284        xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
285        if (!xkb->indicators)
286            return BadAlloc;
287    }
288    return Success;
289}
290
291void
292XkbFreeIndicatorMaps(XkbDescPtr xkb)
293{
294    if ((xkb != NULL) && (xkb->indicators != NULL)) {
295        _XkbFree(xkb->indicators);
296        xkb->indicators = NULL;
297    }
298    return;
299}
300
301/***====================================================================***/
302
303XkbDescRec *
304XkbAllocKeyboard(void)
305{
306    XkbDescRec *xkb;
307
308    xkb = _XkbTypedCalloc(1, XkbDescRec);
309    if (xkb)
310        xkb->device_spec = XkbUseCoreKbd;
311    return xkb;
312}
313
314void
315XkbFreeKeyboard(XkbDescPtr xkb, unsigned which, Bool freeAll)
316{
317    if (xkb == NULL)
318        return;
319    if (freeAll)
320        which = XkbAllComponentsMask;
321    if (which & XkbClientMapMask)
322        XkbFreeClientMap(xkb, XkbAllClientInfoMask, True);
323    if (which & XkbServerMapMask)
324        XkbFreeServerMap(xkb, XkbAllServerInfoMask, True);
325    if (which & XkbCompatMapMask)
326        XkbFreeCompatMap(xkb, XkbAllCompatMask, True);
327    if (which & XkbIndicatorMapMask)
328        XkbFreeIndicatorMaps(xkb);
329    if (which & XkbNamesMask)
330        XkbFreeNames(xkb, XkbAllNamesMask, True);
331    if ((which & XkbGeometryMask) && (xkb->geom != NULL))
332        XkbFreeGeometry(xkb->geom, XkbGeomAllMask, True);
333    if (which & XkbControlsMask)
334        XkbFreeControls(xkb, XkbAllControlsMask, True);
335    if (freeAll)
336        _XkbFree(xkb);
337    return;
338}
339
340/***====================================================================***/
341
342XkbDeviceLedInfoPtr
343XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi, unsigned ledClass, unsigned ledId)
344{
345    XkbDeviceLedInfoPtr devli;
346    register int i;
347
348    if ((!devi) || (!XkbSingleXIClass(ledClass)) || (!XkbSingleXIId(ledId)))
349        return NULL;
350    for (i = 0, devli = devi->leds; i < devi->num_leds; i++, devli++) {
351        if ((devli->led_class == ledClass) && (devli->led_id == ledId))
352            return devli;
353    }
354    if (devi->num_leds >= devi->sz_leds) {
355        XkbDeviceLedInfoRec *prev_leds = devi->leds;
356
357        if (devi->sz_leds > 0)
358            devi->sz_leds *= 2;
359        else
360            devi->sz_leds = 1;
361        devi->leds = _XkbTypedRealloc(devi->leds, devi->sz_leds,
362                                      XkbDeviceLedInfoRec);
363        if (!devi->leds) {
364            _XkbFree(prev_leds);
365            devi->sz_leds = devi->num_leds = 0;
366            return NULL;
367        }
368        i = devi->num_leds;
369        for (devli = &devi->leds[i]; i < devi->sz_leds; i++, devli++) {
370            bzero(devli, sizeof(XkbDeviceLedInfoRec));
371            devli->led_class = XkbXINone;
372            devli->led_id = XkbXINone;
373        }
374    }
375    devli = &devi->leds[devi->num_leds++];
376    bzero(devli, sizeof(XkbDeviceLedInfoRec));
377    devli->led_class = ledClass;
378    devli->led_id = ledId;
379    return devli;
380}
381
382Status
383XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi, unsigned newTotal)
384{
385    XkbAction *prev_btn_acts;
386
387    if ((!devi) || (newTotal > 255))
388        return BadValue;
389    if ((devi->btn_acts != NULL) && (newTotal == devi->num_btns))
390        return Success;
391    if (newTotal == 0) {
392        if (devi->btn_acts != NULL) {
393            _XkbFree(devi->btn_acts);
394            devi->btn_acts = NULL;
395        }
396        devi->num_btns = 0;
397        return Success;
398    }
399    prev_btn_acts = devi->btn_acts;
400    devi->btn_acts = _XkbTypedRealloc(devi->btn_acts, newTotal, XkbAction);
401    if (devi->btn_acts == NULL) {
402        _XkbFree(prev_btn_acts);
403        devi->num_btns = 0;
404        return BadAlloc;
405    }
406    if (newTotal > devi->num_btns) {
407        XkbAction *act;
408
409        act = &devi->btn_acts[devi->num_btns];
410        bzero((char *) act, (newTotal - devi->num_btns) * sizeof(XkbAction));
411    }
412    devi->num_btns = newTotal;
413    return Success;
414}
415
416/*ARGSUSED*/
417XkbDeviceInfoPtr
418XkbAllocDeviceInfo(unsigned deviceSpec, unsigned nButtons, unsigned szLeds)
419{
420    XkbDeviceInfoPtr devi;
421
422    devi = _XkbTypedCalloc(1, XkbDeviceInfoRec);
423    if (devi != NULL) {
424        devi->device_spec = deviceSpec;
425        devi->has_own_state = False;
426        devi->num_btns = 0;
427        devi->btn_acts = NULL;
428        if (nButtons > 0) {
429            devi->num_btns = nButtons;
430            devi->btn_acts = _XkbTypedCalloc(nButtons, XkbAction);
431            if (!devi->btn_acts) {
432                _XkbFree(devi);
433                return NULL;
434            }
435        }
436        devi->dflt_kbd_fb = XkbXINone;
437        devi->dflt_led_fb = XkbXINone;
438        devi->num_leds = 0;
439        devi->sz_leds = 0;
440        devi->leds = NULL;
441        if (szLeds > 0) {
442            devi->sz_leds = szLeds;
443            devi->leds = _XkbTypedCalloc(szLeds, XkbDeviceLedInfoRec);
444            if (!devi->leds) {
445                _XkbFree(devi->btn_acts);
446                _XkbFree(devi);
447                return NULL;
448            }
449        }
450    }
451    return devi;
452}
453
454
455void
456XkbFreeDeviceInfo(XkbDeviceInfoPtr devi, unsigned which, Bool freeDevI)
457{
458    if (devi) {
459        if (freeDevI) {
460            which = XkbXI_AllDeviceFeaturesMask;
461            if (devi->name) {
462                _XkbFree(devi->name);
463                devi->name = NULL;
464            }
465        }
466        if ((which & XkbXI_ButtonActionsMask) && (devi->btn_acts)) {
467            _XkbFree(devi->btn_acts);
468            devi->num_btns = 0;
469            devi->btn_acts = NULL;
470        }
471        if ((which & XkbXI_IndicatorsMask) && (devi->leds)) {
472            register int i;
473
474            if ((which & XkbXI_IndicatorsMask) == XkbXI_IndicatorsMask) {
475                _XkbFree(devi->leds);
476                devi->sz_leds = devi->num_leds = 0;
477                devi->leds = NULL;
478            }
479            else {
480                XkbDeviceLedInfoPtr devli;
481
482                for (i = 0, devli = devi->leds; i < devi->num_leds;
483                     i++, devli++) {
484                    if (which & XkbXI_IndicatorMapsMask)
485                        bzero((char *) &devli->maps[0], sizeof(devli->maps));
486                    else
487                        bzero((char *) &devli->names[0], sizeof(devli->names));
488                }
489            }
490        }
491        if (freeDevI)
492            _XkbFree(devi);
493    }
494    return;
495}
496