Refactor XkbFindFileInPath
[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     memset(&compat->groups[0], 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)
91 {
92     struct xkb_compat_map * compat;
93
94     if (!xkb || !xkb->compat)
95         return;
96
97     compat = xkb->compat;
98
99     free(compat->sym_interpret);
100     free(compat);
101     xkb->compat = NULL;
102 }
103
104 int
105 XkbcAllocNames(struct xkb_desc * xkb, unsigned which, int nTotalRG, int nTotalAliases)
106 {
107     struct xkb_names * names;
108
109     if (!xkb)
110         return BadMatch;
111
112     if (!xkb->names) {
113         xkb->names = _XkbTypedCalloc(1, struct xkb_names);
114         if (!xkb->names)
115             return BadAlloc;
116     }
117     names = xkb->names;
118
119     if ((which & XkbKTLevelNamesMask) && xkb->map && xkb->map->types) {
120         int i;
121         struct xkb_key_type * type;
122
123         type = xkb->map->types;
124         for (i = 0; i < xkb->map->num_types; i++, type++) {
125             if (!type->level_names) {
126                 type->level_names = _XkbTypedCalloc(type->num_levels, uint32_t);
127                 if (!type->level_names)
128                     return BadAlloc;
129             }
130         }
131     }
132
133     if ((which & XkbKeyNamesMask) && !names->keys) {
134         if (!xkb_keymap_keycode_range_is_legal(xkb))
135             return BadMatch;
136
137         names->keys = _XkbTypedCalloc(xkb->max_key_code + 1, struct xkb_key_name);
138         if (!names->keys)
139             return BadAlloc;
140     }
141
142     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
143         if (!names->key_aliases)
144             names->key_aliases = _XkbTypedCalloc(nTotalAliases,
145                                                  struct xkb_key_alias);
146         else if (nTotalAliases > names->num_key_aliases) {
147             struct xkb_key_alias *prev_aliases = names->key_aliases;
148
149             names->key_aliases = _XkbTypedRealloc(names->key_aliases,
150                                                   nTotalAliases,
151                                                   struct xkb_key_alias);
152             if (names->key_aliases)
153                 _XkbClearElems(names->key_aliases, names->num_key_aliases,
154                                nTotalAliases - 1, struct xkb_key_alias);
155             else
156                 free(prev_aliases);
157         }
158
159         if (!names->key_aliases) {
160             names->num_key_aliases = 0;
161             return BadAlloc;
162         }
163
164         names->num_key_aliases = nTotalAliases;
165     }
166
167     if ((which & XkbRGNamesMask) && (nTotalRG > 0)) {
168         if (!names->radio_groups)
169             names->radio_groups = _XkbTypedCalloc(nTotalRG, uint32_t);
170         else if (nTotalRG > names->num_rg) {
171             uint32_t *prev_radio_groups = names->radio_groups;
172
173             names->radio_groups = _XkbTypedRealloc(names->radio_groups,
174                                                    nTotalRG, uint32_t);
175             if (names->radio_groups)
176                 _XkbClearElems(names->radio_groups, names->num_rg,
177                                nTotalRG - 1, uint32_t);
178             else
179                 free(prev_radio_groups);
180         }
181
182         if (!names->radio_groups)
183             return BadAlloc;
184
185         names->num_rg = nTotalRG;
186     }
187
188     return Success;
189 }
190
191 static void
192 XkbcFreeNames(struct xkb_desc * xkb)
193 {
194     struct xkb_names * names;
195     struct xkb_client_map * map;
196
197     if (!xkb || !xkb->names)
198         return;
199
200     names = xkb->names;
201     map = xkb->map;
202
203     if (map && map->types) {
204         int i;
205         struct xkb_key_type * type = map->types;
206
207         for (i = 0; i < map->num_types; i++, type++) {
208             free(type->level_names);
209             type->level_names = NULL;
210         }
211     }
212
213     free(names->keys);
214     free(names->key_aliases);
215     free(names->radio_groups);
216     free(names);
217     xkb->names = NULL;
218 }
219
220 int
221 XkbcAllocControls(struct xkb_desc * xkb, unsigned which)
222 {
223     if (!xkb)
224         return BadMatch;
225
226     if (!xkb->ctrls) {
227         xkb->ctrls = _XkbTypedCalloc(1, struct xkb_controls);
228         if (!xkb->ctrls)
229             return BadAlloc;
230     }
231
232     if (!xkb->ctrls->per_key_repeat) {
233         xkb->ctrls->per_key_repeat = _XkbTypedCalloc(xkb->max_key_code << 3,
234                                                      unsigned char);
235         if (!xkb->ctrls->per_key_repeat)
236             return BadAlloc;
237     }
238
239     return Success;
240 }
241
242 static void
243 XkbcFreeControls(struct xkb_desc * xkb)
244 {
245     if (xkb && xkb->ctrls) {
246         free(xkb->ctrls->per_key_repeat);
247         free(xkb->ctrls);
248         xkb->ctrls = NULL;
249     }
250 }
251
252 int
253 XkbcAllocIndicatorMaps(struct xkb_desc * xkb)
254 {
255     if (!xkb)
256         return BadMatch;
257
258     if (!xkb->indicators) {
259         xkb->indicators = _XkbTypedCalloc(1, struct xkb_indicator);
260         if (!xkb->indicators)
261             return BadAlloc;
262     }
263
264     return Success;
265 }
266
267 static void
268 XkbcFreeIndicatorMaps(struct xkb_desc * xkb)
269 {
270     if (xkb) {
271         free(xkb->indicators);
272         xkb->indicators = NULL;
273     }
274 }
275
276 struct xkb_desc *
277 XkbcAllocKeyboard(void)
278 {
279     struct xkb_desc *xkb;
280
281     xkb = _XkbTypedCalloc(1, struct xkb_desc);
282     if (xkb)
283         xkb->device_spec = XkbUseCoreKbd;
284     return xkb;
285 }
286
287 void
288 XkbcFreeKeyboard(struct xkb_desc * xkb)
289 {
290     if (!xkb)
291         return;
292
293     XkbcFreeClientMap(xkb);
294     XkbcFreeServerMap(xkb);
295     XkbcFreeCompatMap(xkb);
296     XkbcFreeIndicatorMaps(xkb);
297     XkbcFreeNames(xkb);
298     XkbcFreeGeometry(xkb);
299     XkbcFreeControls(xkb);
300     free(xkb);
301 }