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