Still more memory leak fixes
[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->per_key_repeat);
283         free(xkb->ctrls);
284         xkb->ctrls = NULL;
285     }
286 }
287
288 int
289 XkbcAllocIndicatorMaps(struct xkb_desc * xkb)
290 {
291     if (!xkb)
292         return BadMatch;
293
294     if (!xkb->indicators) {
295         xkb->indicators = _XkbTypedCalloc(1, struct xkb_indicator);
296         if (!xkb->indicators)
297             return BadAlloc;
298     }
299
300     return Success;
301 }
302
303 static void
304 XkbcFreeIndicatorMaps(struct xkb_desc * xkb)
305 {
306     if (xkb && xkb->indicators) {
307         free(xkb->indicators);
308         xkb->indicators = NULL;
309     }
310 }
311
312 struct xkb_desc *
313 XkbcAllocKeyboard(void)
314 {
315     struct xkb_desc *xkb;
316
317     xkb = _XkbTypedCalloc(1, struct xkb_desc);
318     if (xkb)
319         xkb->device_spec = XkbUseCoreKbd;
320     return xkb;
321 }
322
323 void
324 XkbcFreeKeyboard(struct xkb_desc * xkb, unsigned which, Bool freeAll)
325 {
326     if (!xkb)
327         return;
328
329     if (freeAll)
330         which = XkbAllComponentsMask;
331
332     if (which & XkbClientMapMask)
333         XkbcFreeClientMap(xkb, XkbAllClientInfoMask, True);
334     if (which & XkbServerMapMask)
335         XkbcFreeServerMap(xkb, XkbAllServerInfoMask, True);
336     if (which & XkbCompatMapMask)
337         XkbcFreeCompatMap(xkb, XkbAllCompatMask, True);
338     if (which & XkbIndicatorMapMask)
339         XkbcFreeIndicatorMaps(xkb);
340     if (which & XkbNamesMask)
341         XkbcFreeNames(xkb, XkbAllNamesMask, True);
342     if ((which & XkbGeometryMask) && xkb->geom)
343         XkbcFreeGeometry(xkb->geom, XkbGeomAllMask, True);
344     if (which & XkbControlsMask)
345         XkbcFreeControls(xkb, XkbAllControlsMask, True);
346     if (freeAll)
347         free(xkb);
348 }