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