3d1c7b26beca72a7c0fa4aa08000a4281ac4d11e
[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 (!xkb_keymap_keycode_range_is_legal(xkb))
148             return BadMatch;
149
150         names->keys = _XkbTypedCalloc(xkb->max_key_code + 1, struct xkb_key_name);
151         if (!names->keys)
152             return BadAlloc;
153     }
154
155     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
156         if (!names->key_aliases)
157             names->key_aliases = _XkbTypedCalloc(nTotalAliases,
158                                                  struct xkb_key_alias);
159         else if (nTotalAliases > names->num_key_aliases) {
160             struct xkb_key_alias *prev_aliases = names->key_aliases;
161
162             names->key_aliases = _XkbTypedRealloc(names->key_aliases,
163                                                   nTotalAliases,
164                                                   struct xkb_key_alias);
165             if (names->key_aliases)
166                 _XkbClearElems(names->key_aliases, names->num_key_aliases,
167                                nTotalAliases - 1, struct xkb_key_alias);
168             else
169                 free(prev_aliases);
170         }
171
172         if (!names->key_aliases) {
173             names->num_key_aliases = 0;
174             return BadAlloc;
175         }
176
177         names->num_key_aliases = nTotalAliases;
178     }
179
180     if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
181         if (!names->radio_groups)
182             names->radio_groups = _XkbTypedCalloc(nTotalRG, uint32_t);
183         else if (nTotalRG > names->num_rg) {
184             uint32_t *prev_radio_groups = names->radio_groups;
185
186             names->radio_groups = _XkbTypedRealloc(names->radio_groups,
187                                                    nTotalRG, uint32_t);
188             if (names->radio_groups)
189                 _XkbClearElems(names->radio_groups, names->num_rg,
190                                nTotalRG - 1, uint32_t);
191             else
192                 free(prev_radio_groups);
193         }
194
195         if (!names->radio_groups)
196             return BadAlloc;
197
198         names->num_rg = nTotalRG;
199     }
200
201     return Success;
202 }
203
204 static void
205 XkbcFreeNames(struct xkb_desc * xkb, unsigned which, Bool freeMap)
206 {
207     struct xkb_names * names;
208
209     if (!xkb || !xkb->names)
210         return;
211
212     names = xkb->names;
213     if (freeMap)
214         which = XkbAllNamesMask;
215
216     if (which & XkbKTLevelNamesMask) {
217         struct xkb_client_map * map = xkb->map;
218
219         if (map && map->types) {
220             int i;
221             struct xkb_key_type * type = map->types;
222
223             for (i = 0; i < map->num_types; i++, type++) {
224                 if (type->level_names) {
225                     free(type->level_names);
226                     type->level_names = NULL;
227                 }
228             }
229         }
230     }
231
232     if ((which & XkbKeyNamesMask) && names->keys) {
233         free(names->keys);
234         names->keys = NULL;
235         names->num_keys = 0;
236     }
237
238     if ((which & XkbKeyAliasesMask) && names->key_aliases) {
239         free(names->key_aliases);
240         names->key_aliases = NULL;
241         names->num_key_aliases = 0;
242     }
243
244     if ((which & XkbRGNamesMask) && names->radio_groups) {
245         free(names->radio_groups);
246         names->radio_groups = NULL;
247         names->num_rg = 0;
248     }
249
250     if (freeMap) {
251         free(names);
252         xkb->names = NULL;
253     }
254 }
255
256 int
257 XkbcAllocControls(struct xkb_desc * xkb, unsigned which)
258 {
259     if (!xkb)
260         return BadMatch;
261
262     if (!xkb->ctrls) {
263         xkb->ctrls = _XkbTypedCalloc(1, struct xkb_controls);
264         if (!xkb->ctrls)
265             return BadAlloc;
266     }
267
268     if (!xkb->ctrls->per_key_repeat) {
269         xkb->ctrls->per_key_repeat = _XkbTypedCalloc(xkb->max_key_code << 3,
270                                                      unsigned char);
271         if (!xkb->ctrls->per_key_repeat)
272             return BadAlloc;
273     }
274
275     return Success;
276 }
277
278 static void
279 XkbcFreeControls(struct xkb_desc * xkb, unsigned which, Bool freeMap)
280 {
281     if (freeMap && xkb && xkb->ctrls) {
282         free(xkb->ctrls);
283         xkb->ctrls = NULL;
284     }
285 }
286
287 int
288 XkbcAllocIndicatorMaps(struct xkb_desc * xkb)
289 {
290     if (!xkb)
291         return BadMatch;
292
293     if (!xkb->indicators) {
294         xkb->indicators = _XkbTypedCalloc(1, struct xkb_indicator);
295         if (!xkb->indicators)
296             return BadAlloc;
297     }
298
299     return Success;
300 }
301
302 static void
303 XkbcFreeIndicatorMaps(struct xkb_desc * xkb)
304 {
305     if (xkb && xkb->indicators) {
306         free(xkb->indicators);
307         xkb->indicators = NULL;
308     }
309 }
310
311 struct xkb_desc *
312 XkbcAllocKeyboard(void)
313 {
314     struct xkb_desc *xkb;
315
316     xkb = _XkbTypedCalloc(1, struct xkb_desc);
317     if (xkb)
318         xkb->device_spec = XkbUseCoreKbd;
319     return xkb;
320 }
321
322 void
323 XkbcFreeKeyboard(struct xkb_desc * xkb, unsigned which, Bool freeAll)
324 {
325     if (!xkb)
326         return;
327
328     if (freeAll)
329         which = XkbAllComponentsMask;
330
331     if (which & XkbClientMapMask)
332         XkbcFreeClientMap(xkb, XkbAllClientInfoMask, True);
333     if (which & XkbServerMapMask)
334         XkbcFreeServerMap(xkb, XkbAllServerInfoMask, True);
335     if (which & XkbCompatMapMask)
336         XkbcFreeCompatMap(xkb, XkbAllCompatMask, True);
337     if (which & XkbIndicatorMapMask)
338         XkbcFreeIndicatorMaps(xkb);
339     if (which & XkbNamesMask)
340         XkbcFreeNames(xkb, XkbAllNamesMask, True);
341     if ((which & XkbGeometryMask) && xkb->geom)
342         XkbcFreeGeometry(xkb->geom, XkbGeomAllMask, True);
343     if (which & XkbControlsMask)
344         XkbcFreeControls(xkb, XkbAllControlsMask, True);
345     if (freeAll)
346         free(xkb);
347 }