XKBAlloc.c revision 35c4bbdf
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_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include "misc.h"
35#include "inputstr.h"
36#include <xkbsrv.h>
37#include "xkbgeom.h"
38#include <os.h>
39#include <string.h>
40
41/***===================================================================***/
42
43 /*ARGSUSED*/ Status
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 = reallocarray(compat->sym_interpret,
60                                             nSI, sizeof(XkbSymInterpretRec));
61        if (compat->sym_interpret == NULL) {
62            free(prev_interpret);
63            compat->size_si = compat->num_si = 0;
64            return BadAlloc;
65        }
66        if (compat->num_si != 0) {
67            memset(&compat->sym_interpret[compat->num_si], 0,
68                   (compat->size_si -
69                    compat->num_si) * sizeof(XkbSymInterpretRec));
70        }
71        return Success;
72    }
73    compat = calloc(1, sizeof(XkbCompatMapRec));
74    if (compat == NULL)
75        return BadAlloc;
76    if (nSI > 0) {
77        compat->sym_interpret = calloc(nSI, sizeof(XkbSymInterpretRec));
78        if (!compat->sym_interpret) {
79            free(compat);
80            return BadAlloc;
81        }
82    }
83    compat->size_si = nSI;
84    compat->num_si = 0;
85    memset((char *) &compat->groups[0], 0,
86           XkbNumKbdGroups * sizeof(XkbModsRec));
87    xkb->compat = compat;
88    return Success;
89}
90
91void
92XkbFreeCompatMap(XkbDescPtr xkb, unsigned which, Bool freeMap)
93{
94    register XkbCompatMapPtr compat;
95
96    if ((xkb == NULL) || (xkb->compat == NULL))
97        return;
98    compat = xkb->compat;
99    if (freeMap)
100        which = XkbAllCompatMask;
101    if (which & XkbGroupCompatMask)
102        memset((char *) &compat->groups[0], 0,
103               XkbNumKbdGroups * sizeof(XkbModsRec));
104    if (which & XkbSymInterpMask) {
105        if ((compat->sym_interpret) && (compat->size_si > 0))
106            free(compat->sym_interpret);
107        compat->size_si = compat->num_si = 0;
108        compat->sym_interpret = NULL;
109    }
110    if (freeMap) {
111        free(compat);
112        xkb->compat = NULL;
113    }
114    return;
115}
116
117/***===================================================================***/
118
119Status
120XkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
121{
122    XkbNamesPtr names;
123
124    if (xkb == NULL)
125        return BadMatch;
126    if (xkb->names == NULL) {
127        xkb->names = calloc(1, sizeof(XkbNamesRec));
128        if (xkb->names == NULL)
129            return BadAlloc;
130    }
131    names = xkb->names;
132    if ((which & XkbKTLevelNamesMask) && (xkb->map != NULL) &&
133        (xkb->map->types != NULL)) {
134        register int i;
135        XkbKeyTypePtr type;
136
137        type = xkb->map->types;
138        for (i = 0; i < xkb->map->num_types; i++, type++) {
139            if (type->level_names == NULL) {
140                type->level_names = calloc(type->num_levels, sizeof(Atom));
141                if (type->level_names == NULL)
142                    return BadAlloc;
143            }
144        }
145    }
146    if ((which & XkbKeyNamesMask) && (names->keys == NULL)) {
147        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
148            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
149            (xkb->max_key_code < xkb->min_key_code))
150            return BadValue;
151        names->keys = calloc((xkb->max_key_code + 1), sizeof(XkbKeyNameRec));
152        if (names->keys == NULL)
153            return BadAlloc;
154    }
155    if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
156        if (names->key_aliases == NULL) {
157            names->key_aliases = calloc(nTotalAliases, sizeof(XkbKeyAliasRec));
158        }
159        else if (nTotalAliases > names->num_key_aliases) {
160            XkbKeyAliasRec *prev_aliases = names->key_aliases;
161
162            names->key_aliases = reallocarray(names->key_aliases,
163                                              nTotalAliases,
164                                              sizeof(XkbKeyAliasRec));
165            if (names->key_aliases != NULL) {
166                memset(&names->key_aliases[names->num_key_aliases], 0,
167                       (nTotalAliases -
168                        names->num_key_aliases) * sizeof(XkbKeyAliasRec));
169            }
170            else {
171                free(prev_aliases);
172            }
173        }
174        if (names->key_aliases == NULL) {
175            names->num_key_aliases = 0;
176            return BadAlloc;
177        }
178        names->num_key_aliases = nTotalAliases;
179    }
180    if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
181        if (names->radio_groups == NULL) {
182            names->radio_groups = calloc(nTotalRG, sizeof(Atom));
183        }
184        else if (nTotalRG > names->num_rg) {
185            Atom *prev_radio_groups = names->radio_groups;
186
187            names->radio_groups = reallocarray(names->radio_groups,
188                                               nTotalRG, sizeof(Atom));
189            if (names->radio_groups != NULL) {
190                memset(&names->radio_groups[names->num_rg], 0,
191                       (nTotalRG - names->num_rg) * sizeof(Atom));
192            }
193            else {
194                free(prev_radio_groups);
195            }
196        }
197        if (names->radio_groups == NULL)
198            return BadAlloc;
199        names->num_rg = nTotalRG;
200    }
201    return Success;
202}
203
204void
205XkbFreeNames(XkbDescPtr xkb, unsigned which, Bool freeMap)
206{
207    XkbNamesPtr names;
208
209    if ((xkb == NULL) || (xkb->names == NULL))
210        return;
211    names = xkb->names;
212    if (freeMap)
213        which = XkbAllNamesMask;
214    if (which & XkbKTLevelNamesMask) {
215        XkbClientMapPtr map = xkb->map;
216
217        if ((map != NULL) && (map->types != NULL)) {
218            register int i;
219            register XkbKeyTypePtr type;
220
221            type = map->types;
222            for (i = 0; i < map->num_types; i++, type++) {
223                free(type->level_names);
224                type->level_names = NULL;
225            }
226        }
227    }
228    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
229        free(names->keys);
230        names->keys = NULL;
231        names->num_keys = 0;
232    }
233    if ((which & XkbKeyAliasesMask) && (names->key_aliases)) {
234        free(names->key_aliases);
235        names->key_aliases = NULL;
236        names->num_key_aliases = 0;
237    }
238    if ((which & XkbRGNamesMask) && (names->radio_groups)) {
239        free(names->radio_groups);
240        names->radio_groups = NULL;
241        names->num_rg = 0;
242    }
243    if (freeMap) {
244        free(names);
245        xkb->names = NULL;
246    }
247    return;
248}
249
250/***===================================================================***/
251
252 /*ARGSUSED*/ Status
253XkbAllocControls(XkbDescPtr xkb, unsigned which)
254{
255    if (xkb == NULL)
256        return BadMatch;
257
258    if (xkb->ctrls == NULL) {
259        xkb->ctrls = calloc(1, sizeof(XkbControlsRec));
260        if (!xkb->ctrls)
261            return BadAlloc;
262    }
263    return Success;
264}
265
266 /*ARGSUSED*/ static void
267XkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap)
268{
269    if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) {
270        free(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 = calloc(1, sizeof(XkbIndicatorRec));
285        if (!xkb->indicators)
286            return BadAlloc;
287    }
288    return Success;
289}
290
291static void
292XkbFreeIndicatorMaps(XkbDescPtr xkb)
293{
294    if ((xkb != NULL) && (xkb->indicators != NULL)) {
295        free(xkb->indicators);
296        xkb->indicators = NULL;
297    }
298    return;
299}
300
301/***====================================================================***/
302
303XkbDescRec *
304XkbAllocKeyboard(void)
305{
306    XkbDescRec *xkb;
307
308    xkb = calloc(1, sizeof(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        /* PERHAPS BONGHITS etc */
334        xkb->geom = NULL;
335    }
336    if (which & XkbControlsMask)
337        XkbFreeControls(xkb, XkbAllControlsMask, TRUE);
338    if (freeAll)
339        free(xkb);
340    return;
341}
342
343/***====================================================================***/
344
345void
346XkbFreeComponentNames(XkbComponentNamesPtr names, Bool freeNames)
347{
348    if (names) {
349        free(names->keycodes);
350        free(names->types);
351        free(names->compat);
352        free(names->symbols);
353        free(names->geometry);
354        memset(names, 0, sizeof(XkbComponentNamesRec));
355    }
356    if (freeNames)
357        free(names);
358}
359