darray: some changes for convenience
[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_copy(into->map, from->map);
134
135     if (from->preserve && !darray_empty(into->map)) {
136         into->preserve = calloc(darray_size(into->map),
137                                 sizeof(*into->preserve));
138         if (!into->preserve)
139             return BadAlloc;
140         memcpy(into->preserve, from->preserve,
141                darray_size(into->map) * sizeof(*into->preserve));
142     }
143
144     if (from->level_names && into->num_levels > 0) {
145         into->level_names = calloc(into->num_levels,
146                                    sizeof(*into->level_names));
147         if (!into->level_names)
148             return BadAlloc;
149
150         for (i = 0; i < into->num_levels; i++)
151             into->level_names[i] = strdup(from->level_names[i]);
152     }
153
154     return Success;
155 }
156
157 bool
158 XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
159                   unsigned int needed)
160 {
161     struct xkb_sym_map *sym_map = &darray_item(keymap->map->key_sym_map, key);
162
163     if (sym_map->size_syms >= needed)
164         return true;
165
166     sym_map->syms = uTypedRecalloc(sym_map->syms, sym_map->size_syms,
167                                    needed, xkb_keysym_t);
168     if (!sym_map->syms) {
169         sym_map->size_syms = 0;
170         return false;
171     }
172
173     sym_map->size_syms = needed;
174     return true;
175 }
176
177 union xkb_action *
178 XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
179                      uint32_t needed)
180 {
181     size_t old_ndx, old_num_acts, new_ndx;
182
183     if (needed == 0) {
184         darray_item(keymap->server->key_acts, key) = 0;
185         return NULL;
186     }
187
188     if (XkbKeyHasActions(keymap, key) &&
189         XkbKeyGroupsWidth(keymap, key) >= needed)
190         return XkbKeyActionsPtr(keymap, key);
191
192     /*
193      * The key may already be in the array, but without enough space.
194      * This should not happen often, so in order to avoid moving and
195      * copying stuff from acts and key_acts, we just allocate new
196      * space for the key at the end, and leave the old space alone.
197      */
198
199     old_ndx = darray_item(keymap->server->key_acts, key);
200     old_num_acts = XkbKeyNumActions(keymap, key);
201     new_ndx = darray_size(keymap->server->acts);
202
203     darray_resize0(keymap->server->acts, new_ndx + needed);
204     darray_item(keymap->server->key_acts, key) = new_ndx;
205
206     /*
207      * The key was already in the array, copy the old actions to the
208      * new space.
209      */
210     if (old_ndx != 0)
211         memcpy(darray_mem(keymap->server->acts, new_ndx),
212                darray_mem(keymap->server->acts, old_ndx),
213                old_num_acts * sizeof(union xkb_action));
214
215     return XkbKeyActionsPtr(keymap, key);
216 }
217
218 void
219 XkbcFreeClientMap(struct xkb_keymap *keymap)
220 {
221     struct xkb_client_map * map;
222     struct xkb_key_type * type;
223     struct xkb_sym_map *sym_map;
224
225     if (!keymap || !keymap->map)
226         return;
227
228     map = keymap->map;
229
230     darray_foreach(type, map->types) {
231         int j;
232         darray_free(type->map);
233         free(type->preserve);
234         for (j = 0; j < type->num_levels; j++)
235             free(type->level_names[j]);
236         free(type->level_names);
237         free(type->name);
238     }
239     darray_free(map->types);
240
241     darray_foreach(sym_map, map->key_sym_map) {
242         free(sym_map->sym_index);
243         free(sym_map->num_syms);
244         free(sym_map->syms);
245     }
246     darray_free(map->key_sym_map);
247
248     free(map->modmap);
249     free(keymap->map);
250     keymap->map = NULL;
251 }
252
253 void
254 XkbcFreeServerMap(struct xkb_keymap *keymap)
255 {
256     struct xkb_server_map * map;
257
258     if (!keymap || !keymap->server)
259         return;
260
261     map = keymap->server;
262
263     free(map->explicit);
264     darray_free(map->key_acts);
265     darray_free(map->acts);
266     free(map->behaviors);
267     free(map->vmodmap);
268     free(keymap->server);
269     keymap->server = NULL;
270 }
271
272 int
273 XkbcAllocCompatMap(struct xkb_keymap *keymap, unsigned nSI)
274 {
275     if (!keymap)
276         return BadMatch;
277
278     if (!keymap->compat) {
279         keymap->compat = calloc(1, sizeof(*keymap->compat));
280         if (!keymap->compat)
281             return BadAlloc;
282         darray_init(keymap->compat->sym_interpret);
283     }
284
285     darray_growalloc(keymap->compat->sym_interpret, nSI);
286     darray_resize(keymap->compat->sym_interpret, 0);
287
288     memset(keymap->compat->groups, 0,
289            XkbNumKbdGroups * sizeof(*keymap->compat->groups));
290
291     return Success;
292 }
293
294
295 static void
296 XkbcFreeCompatMap(struct xkb_keymap *keymap)
297 {
298     if (!keymap || !keymap->compat)
299         return;
300
301     darray_free(keymap->compat->sym_interpret);
302     free(keymap->compat);
303     keymap->compat = NULL;
304 }
305
306 int
307 XkbcAllocNames(struct xkb_keymap *keymap, unsigned which, size_t nTotalAliases)
308 {
309     if (!keymap)
310         return BadMatch;
311
312     if (!keymap->names) {
313         keymap->names = calloc(1, sizeof(*keymap->names));
314         if (!keymap->names)
315             return BadAlloc;
316
317         darray_init(keymap->names->keys);
318         darray_init(keymap->names->key_aliases);
319     }
320
321     if ((which & XkbKTLevelNamesMask) && keymap->map) {
322         struct xkb_key_type * type;
323
324         darray_foreach(type, keymap->map->types) {
325             if (!type->level_names) {
326                 type->level_names = calloc(type->num_levels,
327                                            sizeof(*type->level_names));
328                 if (!type->level_names)
329                     return BadAlloc;
330             }
331         }
332     }
333
334     if (which & XkbKeyNamesMask)
335         darray_resize0(keymap->names->keys, keymap->max_key_code + 1);
336
337     if (which & XkbKeyAliasesMask)
338         darray_resize0(keymap->names->key_aliases, nTotalAliases);
339
340     return Success;
341 }
342
343 static void
344 XkbcFreeNames(struct xkb_keymap *keymap)
345 {
346     struct xkb_names * names;
347     struct xkb_client_map * map;
348     struct xkb_key_type *type;
349     int i;
350
351     if (!keymap || !keymap->names)
352         return;
353
354     names = keymap->names;
355     map = keymap->map;
356
357     if (map) {
358         darray_foreach(type, map->types) {
359             int j;
360             for (j = 0; j < type->num_levels; j++)
361                 free(type->level_names[j]);
362             free(type->level_names);
363             type->level_names = NULL;
364         }
365     }
366
367     for (i = 0; i < XkbNumVirtualMods; i++)
368         free(names->vmods[i]);
369     for (i = 0; i < XkbNumIndicators; i++)
370         free(names->indicators[i]);
371     for (i = 0; i < XkbNumKbdGroups; i++)
372         free(names->groups[i]);
373
374     darray_free(names->keys);
375     darray_free(names->key_aliases);
376     free(names);
377     keymap->names = NULL;
378 }
379
380 int
381 XkbcAllocControls(struct xkb_keymap *keymap)
382 {
383     if (!keymap)
384         return BadMatch;
385
386     if (!keymap->ctrls) {
387         keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
388         if (!keymap->ctrls)
389             return BadAlloc;
390     }
391
392     keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
393                                                  unsigned char);
394     if (!keymap->ctrls->per_key_repeat)
395         return BadAlloc;
396
397     return Success;
398 }
399
400 static void
401 XkbcFreeControls(struct xkb_keymap *keymap)
402 {
403     if (keymap && keymap->ctrls) {
404         free(keymap->ctrls->per_key_repeat);
405         free(keymap->ctrls);
406         keymap->ctrls = NULL;
407     }
408 }
409
410 int
411 XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
412 {
413     if (!keymap)
414         return BadMatch;
415
416     if (!keymap->indicators) {
417         keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
418         if (!keymap->indicators)
419             return BadAlloc;
420     }
421
422     return Success;
423 }
424
425 static void
426 XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
427 {
428     if (keymap) {
429         free(keymap->indicators);
430         keymap->indicators = NULL;
431     }
432 }
433
434 struct xkb_keymap *
435 XkbcAllocKeyboard(struct xkb_context *ctx)
436 {
437     struct xkb_keymap *keymap;
438
439     keymap = uTypedCalloc(1, struct xkb_keymap);
440     if (!keymap)
441         return NULL;
442
443     keymap->refcnt = 1;
444     keymap->ctx = xkb_context_ref(ctx);
445
446     return keymap;
447 }
448
449 void
450 XkbcFreeKeyboard(struct xkb_keymap *keymap)
451 {
452     if (!keymap)
453         return;
454
455     XkbcFreeClientMap(keymap);
456     XkbcFreeServerMap(keymap);
457     XkbcFreeCompatMap(keymap);
458     XkbcFreeIndicatorMaps(keymap);
459     XkbcFreeNames(keymap);
460     XkbcFreeControls(keymap);
461     xkb_context_unref(keymap->ctx);
462     free(keymap);
463 }