45a9114bb4ed8cb11886cc47e0c3e3a108b71292
[profile/ivi/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 #include "xkb-priv.h"
27 #include "alloc.h"
28
29 int
30 XkbcAllocClientMap(struct xkb_keymap *keymap, unsigned which,
31                    size_t nTotalTypes)
32 {
33     if (!keymap || ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
34         return BadValue;
35
36     if (!keymap->map) {
37         keymap->map = calloc(1, sizeof(*keymap->map));
38         if (!keymap->map)
39             return BadAlloc;
40         darray_init(keymap->map->types);
41     }
42
43     if (which & XkbKeyTypesMask)
44         darray_growalloc(keymap->map->types, nTotalTypes);
45
46     if (which & XkbKeySymsMask)
47         darray_resize0(keymap->map->key_sym_map, keymap->max_key_code + 1);
48
49     if (which & XkbModifierMapMask) {
50         if (!keymap->map->modmap) {
51             keymap->map->modmap = uTypedCalloc(keymap->max_key_code + 1,
52                                                unsigned char);
53             if (!keymap->map->modmap)
54                 return BadAlloc;
55         }
56     }
57
58     return Success;
59 }
60
61 int
62 XkbcAllocServerMap(struct xkb_keymap *keymap, unsigned which,
63                    unsigned nNewActions)
64 {
65     unsigned i;
66     struct xkb_server_map * map;
67
68     if (!keymap)
69         return BadMatch;
70
71     if (!keymap->server) {
72         map = uTypedCalloc(1, struct xkb_server_map);
73         if (!map)
74             return BadAlloc;
75
76         for (i = 0; i < XkbNumVirtualMods; i++)
77             map->vmods[i] = XkbNoModifierMask;
78
79         keymap->server = map;
80     }
81     else
82         map = keymap->server;
83
84     if (!which)
85         return Success;
86
87     if (!map->explicit) {
88         i = keymap->max_key_code + 1;
89         map->explicit = uTypedCalloc(i, unsigned char);
90         if (!map->explicit)
91             return BadAlloc;
92     }
93
94     if (nNewActions < 1)
95         nNewActions = 1;
96
97     darray_resize0(map->acts, darray_size(map->acts) + nNewActions + 1);
98     darray_resize0(map->key_acts, keymap->max_key_code + 1);
99
100     if (!map->behaviors) {
101         i = keymap->max_key_code + 1;
102         map->behaviors = uTypedCalloc(i, struct xkb_behavior);
103         if (!map->behaviors)
104             return BadAlloc;
105     }
106
107     if (!map->vmodmap) {
108         i = keymap->max_key_code + 1;
109         map->vmodmap = uTypedCalloc(i, uint32_t);
110         if (!map->vmodmap)
111             return BadAlloc;
112     }
113
114     return Success;
115 }
116
117 int
118 XkbcCopyKeyType(const struct xkb_key_type *from, struct xkb_key_type *into)
119 {
120     int i;
121
122     if (!from || !into)
123         return BadMatch;
124
125     darray_free(into->map);
126     free(into->preserve);
127     for (i = 0; i < into->num_levels; i++)
128         free(into->level_names[i]);
129     free(into->level_names);
130
131     *into = *from;
132
133     darray_init(into->map);
134     darray_from_items(into->map,
135                       &darray_item(from->map, 0),
136                       darray_size(from->map));
137
138     if (from->preserve && !darray_empty(into->map)) {
139         into->preserve = calloc(darray_size(into->map),
140                                 sizeof(*into->preserve));
141         if (!into->preserve)
142             return BadAlloc;
143         memcpy(into->preserve, from->preserve,
144                darray_size(into->map) * sizeof(*into->preserve));
145     }
146
147     if (from->level_names && into->num_levels > 0) {
148         into->level_names = calloc(into->num_levels,
149                                    sizeof(*into->level_names));
150         if (!into->level_names)
151             return BadAlloc;
152
153         for (i = 0; i < into->num_levels; i++)
154             into->level_names[i] = strdup(from->level_names[i]);
155     }
156
157     return Success;
158 }
159
160 bool
161 XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
162                   unsigned int needed)
163 {
164     struct xkb_sym_map *sym_map =
165         &darray_item(keymap->map->key_sym_map, key);
166
167     if (sym_map->size_syms >= needed)
168         return true;
169
170     sym_map->syms = uTypedRecalloc(sym_map->syms, sym_map->size_syms,
171                                    needed, xkb_keysym_t);
172     if (!sym_map->syms) {
173         sym_map->size_syms = 0;
174         return false;
175     }
176
177     sym_map->size_syms = needed;
178     return true;
179 }
180
181 union xkb_action *
182 XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
183                      uint32_t needed)
184 {
185     size_t old_ndx, old_num_acts, new_ndx;
186
187     if (needed == 0) {
188         darray_item(keymap->server->key_acts, key) = 0;
189         return NULL;
190     }
191
192     if (XkbKeyHasActions(keymap, key) &&
193         XkbKeyGroupsWidth(keymap, key) >= needed)
194         return XkbKeyActionsPtr(keymap, key);
195
196     /*
197      * The key may already be in the array, but without enough space.
198      * This should not happen often, so in order to avoid moving and
199      * copying stuff from acts and key_acts, we just allocate new
200      * space for the key at the end, and leave the old space alone.
201      */
202
203     old_ndx = darray_item(keymap->server->key_acts, key);
204     old_num_acts = XkbKeyNumActions(keymap, key);
205     new_ndx = darray_size(keymap->server->acts);
206
207     darray_resize0(keymap->server->acts, new_ndx + needed);
208     darray_item(keymap->server->key_acts, key) = new_ndx;
209
210     /*
211      * The key was already in the array, copy the old actions to the
212      * new space.
213      */
214     if (old_ndx != 0)
215         memcpy(&darray_item(keymap->server->acts, new_ndx),
216                &darray_item(keymap->server->acts, old_ndx),
217                old_num_acts * sizeof(union xkb_action));
218
219     return XkbKeyActionsPtr(keymap, key);
220 }
221
222 void
223 XkbcFreeClientMap(struct xkb_keymap *keymap)
224 {
225     struct xkb_client_map * map;
226     struct xkb_key_type * type;
227     struct xkb_sym_map *sym_map;
228
229     if (!keymap || !keymap->map)
230         return;
231
232     map = keymap->map;
233
234     darray_foreach(type, map->types) {
235         int j;
236         darray_free(type->map);
237         free(type->preserve);
238         for (j = 0; j < type->num_levels; j++)
239             free(type->level_names[j]);
240         free(type->level_names);
241         free(type->name);
242     }
243     darray_free(map->types);
244
245     darray_foreach(sym_map, map->key_sym_map) {
246         free(sym_map->sym_index);
247         free(sym_map->num_syms);
248         free(sym_map->syms);
249     }
250     darray_free(map->key_sym_map);
251
252     free(map->modmap);
253     free(keymap->map);
254     keymap->map = NULL;
255 }
256
257 void
258 XkbcFreeServerMap(struct xkb_keymap *keymap)
259 {
260     struct xkb_server_map * map;
261
262     if (!keymap || !keymap->server)
263         return;
264
265     map = keymap->server;
266
267     free(map->explicit);
268     darray_free(map->key_acts);
269     darray_free(map->acts);
270     free(map->behaviors);
271     free(map->vmodmap);
272     free(keymap->server);
273     keymap->server = NULL;
274 }
275
276 int
277 XkbcAllocCompatMap(struct xkb_keymap *keymap, unsigned nSI)
278 {
279     if (!keymap)
280         return BadMatch;
281
282     if (!keymap->compat) {
283         keymap->compat = calloc(1, sizeof(*keymap->compat));
284         if (!keymap->compat)
285             return BadAlloc;
286         darray_init(keymap->compat->sym_interpret);
287     }
288
289     darray_growalloc(keymap->compat->sym_interpret, nSI);
290     darray_resize(keymap->compat->sym_interpret, 0);
291
292     memset(keymap->compat->groups, 0,
293            XkbNumKbdGroups * sizeof(*keymap->compat->groups));
294
295     return Success;
296 }
297
298
299 static void
300 XkbcFreeCompatMap(struct xkb_keymap *keymap)
301 {
302     if (!keymap || !keymap->compat)
303         return;
304
305     darray_free(keymap->compat->sym_interpret);
306     free(keymap->compat);
307     keymap->compat = NULL;
308 }
309
310 int
311 XkbcAllocNames(struct xkb_keymap *keymap, unsigned which, size_t nTotalAliases)
312 {
313     if (!keymap)
314         return BadMatch;
315
316     if (!keymap->names) {
317         keymap->names = calloc(1, sizeof(*keymap->names));
318         if (!keymap->names)
319             return BadAlloc;
320
321         darray_init(keymap->names->keys);
322         darray_init(keymap->names->key_aliases);
323     }
324
325     if ((which & XkbKTLevelNamesMask) && keymap->map) {
326         struct xkb_key_type * type;
327
328         darray_foreach(type, keymap->map->types) {
329             if (!type->level_names) {
330                 type->level_names = calloc(type->num_levels,
331                                            sizeof(*type->level_names));
332                 if (!type->level_names)
333                     return BadAlloc;
334             }
335         }
336     }
337
338     if (which & XkbKeyNamesMask)
339         darray_resize0(keymap->names->keys, keymap->max_key_code + 1);
340
341     if (which & XkbKeyAliasesMask)
342         darray_resize0(keymap->names->key_aliases, nTotalAliases);
343
344     return Success;
345 }
346
347 static void
348 XkbcFreeNames(struct xkb_keymap *keymap)
349 {
350     struct xkb_names * names;
351     struct xkb_client_map * map;
352     struct xkb_key_type *type;
353     int i;
354
355     if (!keymap || !keymap->names)
356         return;
357
358     names = keymap->names;
359     map = keymap->map;
360
361     if (map) {
362         darray_foreach(type, map->types) {
363             int j;
364             for (j = 0; j < type->num_levels; j++)
365                 free(type->level_names[j]);
366             free(type->level_names);
367             type->level_names = NULL;
368         }
369     }
370
371     for (i = 0; i < XkbNumVirtualMods; i++)
372         free(names->vmods[i]);
373     for (i = 0; i < XkbNumIndicators; i++)
374         free(names->indicators[i]);
375     for (i = 0; i < XkbNumKbdGroups; i++)
376         free(names->groups[i]);
377
378     darray_free(names->keys);
379     darray_free(names->key_aliases);
380     free(names);
381     keymap->names = NULL;
382 }
383
384 int
385 XkbcAllocControls(struct xkb_keymap *keymap)
386 {
387     if (!keymap)
388         return BadMatch;
389
390     if (!keymap->ctrls) {
391         keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
392         if (!keymap->ctrls)
393             return BadAlloc;
394     }
395
396     keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
397                                                  unsigned char);
398     if (!keymap->ctrls->per_key_repeat)
399         return BadAlloc;
400
401     return Success;
402 }
403
404 static void
405 XkbcFreeControls(struct xkb_keymap *keymap)
406 {
407     if (keymap && keymap->ctrls) {
408         free(keymap->ctrls->per_key_repeat);
409         free(keymap->ctrls);
410         keymap->ctrls = NULL;
411     }
412 }
413
414 int
415 XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
416 {
417     if (!keymap)
418         return BadMatch;
419
420     if (!keymap->indicators) {
421         keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
422         if (!keymap->indicators)
423             return BadAlloc;
424     }
425
426     return Success;
427 }
428
429 static void
430 XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
431 {
432     if (keymap) {
433         free(keymap->indicators);
434         keymap->indicators = NULL;
435     }
436 }
437
438 struct xkb_keymap *
439 XkbcAllocKeyboard(struct xkb_context *ctx)
440 {
441     struct xkb_keymap *keymap;
442
443     keymap = uTypedCalloc(1, struct xkb_keymap);
444     if (!keymap)
445         return NULL;
446
447     keymap->refcnt = 1;
448     keymap->ctx = xkb_context_ref(ctx);
449
450     return keymap;
451 }
452
453 void
454 XkbcFreeKeyboard(struct xkb_keymap *keymap)
455 {
456     if (!keymap)
457         return;
458
459     XkbcFreeClientMap(keymap);
460     XkbcFreeServerMap(keymap);
461     XkbcFreeCompatMap(keymap);
462     XkbcFreeIndicatorMaps(keymap);
463     XkbcFreeNames(keymap);
464     XkbcFreeControls(keymap);
465     xkb_context_unref(keymap->ctx);
466     free(keymap);
467 }