Move include path from X11/extensions/ to xkbcommon/
[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 "xkbcommon/xkbcommon.h"
32 #include "XKBcommonint.h"
33 #include <X11/extensions/XKB.h>
34
35 int
36 XkbcAllocCompatMap(struct xkb_desc * xkb, unsigned which, unsigned nSI)
37 {
38     struct xkb_compat_map * compat;
39     struct xkb_sym_interpret *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, struct xkb_sym_interpret);
56         if (!compat->sym_interpret) {
57             free(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, struct xkb_sym_interpret);
65
66         return Success;
67     }
68
69     compat = _XkbTypedCalloc(1, struct xkb_compat_map);
70     if (!compat)
71         return BadAlloc;
72
73     if (nSI > 0) {
74         compat->sym_interpret = _XkbTypedCalloc(nSI, struct xkb_sym_interpret);
75         if (!compat->sym_interpret) {
76             free(compat);
77             return BadAlloc;
78         }
79     }
80     compat->size_si = nSI;
81     compat->num_si = 0;
82     bzero(&compat->groups[0], XkbNumKbdGroups * sizeof(struct xkb_mods));
83     xkb->compat = compat;
84
85     return Success;
86 }
87
88
89 static void
90 XkbcFreeCompatMap(struct xkb_desc * xkb, unsigned which, Bool freeMap)
91 {
92     struct xkb_compat_map * 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(struct xkb_mods));
103
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
111     if (freeMap) {
112         free(compat);
113         xkb->compat = NULL;
114     }
115 }
116
117 int
118 XkbcAllocNames(struct xkb_desc * xkb, unsigned which, int nTotalRG, int nTotalAliases)
119 {
120     struct xkb_names * names;
121
122     if (!xkb)
123         return BadMatch;
124
125     if (!xkb->names) {
126         xkb->names = _XkbTypedCalloc(1, struct xkb_names);
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         struct xkb_key_type * 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, uint32_t);
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, struct xkb_key_name);
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                                                  struct xkb_key_alias);
161         else if (nTotalAliases > names->num_key_aliases) {
162             struct xkb_key_alias *prev_aliases = names->key_aliases;
163
164             names->key_aliases = _XkbTypedRealloc(names->key_aliases,
165                                                   nTotalAliases,
166                                                   struct xkb_key_alias);
167             if (names->key_aliases)
168                 _XkbClearElems(names->key_aliases, names->num_key_aliases,
169                                nTotalAliases - 1, struct xkb_key_alias);
170             else
171                 free(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, uint32_t);
185         else if (nTotalRG > names->num_rg) {
186             uint32_t *prev_radio_groups = names->radio_groups;
187
188             names->radio_groups = _XkbTypedRealloc(names->radio_groups,
189                                                    nTotalRG, uint32_t);
190             if (names->radio_groups)
191                 _XkbClearElems(names->radio_groups, names->num_rg,
192                                nTotalRG - 1, uint32_t);
193             else
194                 free(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 static void
207 XkbcFreeNames(struct xkb_desc * xkb, unsigned which, Bool freeMap)
208 {
209     struct xkb_names * 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         struct xkb_client_map * map = xkb->map;
220
221         if (map && map->types) {
222             int i;
223             struct xkb_key_type * type = map->types;
224
225             for (i = 0; i < map->num_types; i++, type++) {
226                 if (type->level_names) {
227                     free(type->level_names);
228                     type->level_names = NULL;
229                 }
230             }
231         }
232     }
233
234     if ((which & XkbKeyNamesMask) && names->keys) {
235         free(names->keys);
236         names->keys = NULL;
237         names->num_keys = 0;
238     }
239
240     if ((which & XkbKeyAliasesMask) && names->key_aliases) {
241         free(names->key_aliases);
242         names->key_aliases = NULL;
243         names->num_key_aliases = 0;
244     }
245
246     if ((which & XkbRGNamesMask) && names->radio_groups) {
247         free(names->radio_groups);
248         names->radio_groups = NULL;
249         names->num_rg = 0;
250     }
251
252     if (freeMap) {
253         free(names);
254         xkb->names = NULL;
255     }
256 }
257
258 int
259 XkbcAllocControls(struct xkb_desc * xkb, unsigned which)
260 {
261     if (!xkb)
262         return BadMatch;
263
264     if (!xkb->ctrls) {
265         xkb->ctrls = _XkbTypedCalloc(1, struct xkb_controls);
266         if (!xkb->ctrls)
267             return BadAlloc;
268     }
269
270     return Success;
271 }
272
273 static void
274 XkbcFreeControls(struct xkb_desc * xkb, unsigned which, Bool freeMap)
275 {
276     if (freeMap && xkb && xkb->ctrls) {
277         free(xkb->ctrls);
278         xkb->ctrls = NULL;
279     }
280 }
281
282 int
283 XkbcAllocIndicatorMaps(struct xkb_desc * xkb)
284 {
285     if (!xkb)
286         return BadMatch;
287
288     if (!xkb->indicators) {
289         xkb->indicators = _XkbTypedCalloc(1, struct xkb_indicator);
290         if (!xkb->indicators)
291             return BadAlloc;
292     }
293
294     return Success;
295 }
296
297 static void
298 XkbcFreeIndicatorMaps(struct xkb_desc * xkb)
299 {
300     if (xkb && xkb->indicators) {
301         free(xkb->indicators);
302         xkb->indicators = NULL;
303     }
304 }
305
306 struct xkb_desc *
307 XkbcAllocKeyboard(void)
308 {
309     struct xkb_desc *xkb;
310
311     xkb = _XkbTypedCalloc(1, struct xkb_desc);
312     if (xkb)
313         xkb->device_spec = XkbUseCoreKbd;
314     return xkb;
315 }
316
317 void
318 XkbcFreeKeyboard(struct xkb_desc * 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         free(xkb);
342 }