Copy and duplicate XkbModsRec and XkbKTMapEntryRec
[platform/upstream/libxkbcommon.git] / src / alloc.c
1 /*
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "xkballoc.h"
30 #include "xkbgeom.h"
31 #include "X11/extensions/XKBcommon.h"
32 #include "XKBcommonint.h"
33 #include <X11/extensions/XKB.h>
34
35 int
36 XkbcAllocCompatMap(XkbcDescPtr xkb, unsigned which, unsigned nSI)
37 {
38     XkbcCompatMapPtr compat;
39     XkbcSymInterpretRec *prev_interpret;
40
41     if (!xkb)
42         return BadMatch;
43
44     if (xkb->compat) {
45         if (xkb->compat->size_si >= nSI)
46             return Success;
47
48         compat = xkb->compat;
49         compat->size_si = nSI;
50         if (!compat->sym_interpret)
51             compat->num_si = 0;
52
53         prev_interpret = compat->sym_interpret;
54         compat->sym_interpret = _XkbTypedRealloc(compat->sym_interpret,
55                                                  nSI, XkbcSymInterpretRec);
56         if (!compat->sym_interpret) {
57             _XkbFree(prev_interpret);
58             compat->size_si = compat->num_si = 0;
59             return BadAlloc;
60         }
61
62         if (compat->num_si != 0)
63             _XkbClearElems(compat->sym_interpret, compat->num_si,
64                            compat->size_si - 1, XkbcSymInterpretRec);
65
66         return Success;
67     }
68
69     compat = _XkbTypedCalloc(1, XkbcCompatMapRec);
70     if (!compat)
71         return BadAlloc;
72
73     if (nSI > 0) {
74         compat->sym_interpret = _XkbTypedCalloc(nSI, XkbcSymInterpretRec);
75         if (!compat->sym_interpret) {
76             _XkbFree(compat);
77             return BadAlloc;
78         }
79     }
80     compat->size_si = nSI;
81     compat->num_si = 0;
82     bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbcModsRec));
83     xkb->compat = compat;
84
85     return Success;
86 }
87
88
89 void
90 XkbcFreeCompatMap(XkbcDescPtr xkb, unsigned which, Bool freeMap)
91 {
92     XkbcCompatMapPtr compat;
93
94     if (!xkb || !xkb->compat)
95         return;
96
97     compat = xkb->compat;
98     if (freeMap)
99         which = XkbAllCompatMask;
100
101     if (which & XkbGroupCompatMask)
102         bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(XkbcModsRec));
103
104     if (which & XkbSymInterpMask) {
105         if (compat->sym_interpret && (compat->size_si > 0))
106             _XkbFree(compat->sym_interpret);
107         compat->size_si = compat->num_si = 0;
108         compat->sym_interpret = NULL;
109     }
110
111     if (freeMap) {
112         _XkbFree(compat);
113         xkb->compat = NULL;
114     }
115 }
116
117 int
118 XkbcAllocNames(XkbcDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
119 {
120     XkbcNamesPtr names;
121
122     if (!xkb)
123         return BadMatch;
124
125     if (!xkb->names) {
126         xkb->names = _XkbTypedCalloc(1, XkbcNamesRec);
127         if (!xkb->names)
128             return BadAlloc;
129     }
130     names = xkb->names;
131
132     if ((which & XkbKTLevelNamesMask) && xkb->map && xkb->map->types) {
133         int i;
134         XkbcKeyTypePtr type;
135
136         type = xkb->map->types;
137         for (i = 0; i < xkb->map->num_types; i++, type++) {
138             if (!type->level_names) {
139                 type->level_names = _XkbTypedCalloc(type->num_levels, CARD32);
140                 if (!type->level_names)
141                     return BadAlloc;
142             }
143         }
144     }
145
146     if ((which & XkbKeyNamesMask) && !names->keys) {
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
152         names->keys = _XkbTypedCalloc(xkb->max_key_code + 1, XkbKeyNameRec);
153         if (!names->keys)
154             return BadAlloc;
155     }
156
157     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
158         if (!names->key_aliases)
159             names->key_aliases = _XkbTypedCalloc(nTotalAliases,
160                                                  XkbKeyAliasRec);
161         else if (nTotalAliases > names->num_key_aliases) {
162             XkbKeyAliasRec *prev_aliases = names->key_aliases;
163
164             names->key_aliases = _XkbTypedRealloc(names->key_aliases,
165                                                   nTotalAliases,
166                                                   XkbKeyAliasRec);
167             if (names->key_aliases)
168                 _XkbClearElems(names->key_aliases, names->num_key_aliases,
169                                nTotalAliases - 1, XkbKeyAliasRec);
170             else
171                 _XkbFree(prev_aliases);
172         }
173
174         if (!names->key_aliases) {
175             names->num_key_aliases = 0;
176             return BadAlloc;
177         }
178
179         names->num_key_aliases = nTotalAliases;
180     }
181
182     if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
183         if (!names->radio_groups)
184             names->radio_groups = _XkbTypedCalloc(nTotalRG, CARD32);
185         else if (nTotalRG > names->num_rg) {
186             CARD32 *prev_radio_groups = names->radio_groups;
187
188             names->radio_groups = _XkbTypedRealloc(names->radio_groups,
189                                                    nTotalRG, CARD32);
190             if (names->radio_groups)
191                 _XkbClearElems(names->radio_groups, names->num_rg,
192                                nTotalRG - 1, CARD32);
193             else
194                 _XkbFree(prev_radio_groups);
195         }
196
197         if (!names->radio_groups)
198             return BadAlloc;
199
200         names->num_rg = nTotalRG;
201     }
202
203     return Success;
204 }
205
206 void
207 XkbcFreeNames(XkbcDescPtr xkb, unsigned which, Bool freeMap)
208 {
209     XkbcNamesPtr names;
210
211     if (!xkb || !xkb->names)
212         return;
213
214     names = xkb->names;
215     if (freeMap)
216         which = XkbAllNamesMask;
217
218     if (which & XkbKTLevelNamesMask) {
219         XkbcClientMapPtr map = xkb->map;
220
221         if (map && map->types) {
222             int i;
223             XkbcKeyTypePtr type = map->types;
224
225             for (i = 0; i < map->num_types; i++, type++) {
226                 if (type->level_names) {
227                     _XkbFree(type->level_names);
228                     type->level_names = NULL;
229                 }
230             }
231         }
232     }
233
234     if ((which & XkbKeyNamesMask) && names->keys) {
235         _XkbFree(names->keys);
236         names->keys = NULL;
237         names->num_keys = 0;
238     }
239
240     if ((which & XkbKeyAliasesMask) && names->key_aliases) {
241         _XkbFree(names->key_aliases);
242         names->key_aliases = NULL;
243         names->num_key_aliases = 0;
244     }
245
246     if ((which & XkbRGNamesMask) && names->radio_groups) {
247         _XkbFree(names->radio_groups);
248         names->radio_groups = NULL;
249         names->num_rg = 0;
250     }
251
252     if (freeMap) {
253         _XkbFree(names);
254         xkb->names = NULL;
255     }
256 }
257
258 int
259 XkbcAllocControls(XkbcDescPtr xkb, unsigned which)
260 {
261     if (!xkb)
262         return BadMatch;
263
264     if (!xkb->ctrls) {
265         xkb->ctrls = _XkbTypedCalloc(1, XkbControlsRec);
266         if (!xkb->ctrls)
267             return BadAlloc;
268     }
269
270     return Success;
271 }
272
273 void
274 XkbcFreeControls(XkbcDescPtr xkb, unsigned which, Bool freeMap)
275 {
276     if (freeMap && xkb && xkb->ctrls) {
277         _XkbFree(xkb->ctrls);
278         xkb->ctrls = NULL;
279     }
280 }
281
282 int
283 XkbcAllocIndicatorMaps(XkbcDescPtr xkb)
284 {
285     if (!xkb)
286         return BadMatch;
287
288     if (!xkb->indicators) {
289         xkb->indicators = _XkbTypedCalloc(1, XkbIndicatorRec);
290         if (!xkb->indicators)
291             return BadAlloc;
292     }
293
294     return Success;
295 }
296
297 void
298 XkbcFreeIndicatorMaps(XkbcDescPtr xkb)
299 {
300     if (xkb && xkb->indicators) {
301         _XkbFree(xkb->indicators);
302         xkb->indicators = NULL;
303     }
304 }
305
306 XkbcDescRec *
307 XkbcAllocKeyboard(void)
308 {
309     XkbcDescRec *xkb;
310
311     xkb = _XkbTypedCalloc(1, XkbcDescRec);
312     if (xkb)
313         xkb->device_spec = XkbUseCoreKbd;
314     return xkb;
315 }
316
317 void
318 XkbcFreeKeyboard(XkbcDescPtr xkb, unsigned which, Bool freeAll)
319 {
320     if (!xkb)
321         return;
322
323     if (freeAll)
324         which = XkbAllComponentsMask;
325
326     if (which & XkbClientMapMask)
327         XkbcFreeClientMap(xkb, XkbAllClientInfoMask, True);
328     if (which & XkbServerMapMask)
329         XkbcFreeServerMap(xkb, XkbAllServerInfoMask, True);
330     if (which & XkbCompatMapMask)
331         XkbcFreeCompatMap(xkb, XkbAllCompatMask, True);
332     if (which & XkbIndicatorMapMask)
333         XkbcFreeIndicatorMaps(xkb);
334     if (which & XkbNamesMask)
335         XkbcFreeNames(xkb, XkbAllNamesMask, True);
336     if ((which & XkbGeometryMask) && xkb->geom)
337         XkbcFreeGeometry(xkb->geom, XkbGeomAllMask, True);
338     if (which & XkbControlsMask)
339         XkbcFreeControls(xkb, XkbAllControlsMask, True);
340     if (freeAll)
341         _XkbFree(xkb);
342 }