Fix the keyboard config to match Tizen 2.0 alpha
[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     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     for (i = 0; i < XkbNumVirtualMods; i++)
356         free(names->vmods[i]);
357     for (i = 0; i < XkbNumIndicators; i++)
358         free(names->indicators[i]);
359     for (i = 0; i < XkbNumKbdGroups; i++)
360         free(names->groups[i]);
361
362     darray_free(names->keys);
363     darray_free(names->key_aliases);
364     free(names);
365     keymap->names = NULL;
366 }
367
368 int
369 XkbcAllocControls(struct xkb_keymap *keymap)
370 {
371     if (!keymap)
372         return BadMatch;
373
374     if (!keymap->ctrls) {
375         keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
376         if (!keymap->ctrls)
377             return BadAlloc;
378     }
379
380     keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
381                                                  unsigned char);
382     if (!keymap->ctrls->per_key_repeat)
383         return BadAlloc;
384
385     return Success;
386 }
387
388 static void
389 XkbcFreeControls(struct xkb_keymap *keymap)
390 {
391     if (keymap && keymap->ctrls) {
392         free(keymap->ctrls->per_key_repeat);
393         free(keymap->ctrls);
394         keymap->ctrls = NULL;
395     }
396 }
397
398 int
399 XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
400 {
401     if (!keymap)
402         return BadMatch;
403
404     if (!keymap->indicators) {
405         keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
406         if (!keymap->indicators)
407             return BadAlloc;
408     }
409
410     return Success;
411 }
412
413 static void
414 XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
415 {
416     if (keymap) {
417         free(keymap->indicators);
418         keymap->indicators = NULL;
419     }
420 }
421
422 struct xkb_keymap *
423 XkbcAllocKeyboard(struct xkb_context *ctx)
424 {
425     struct xkb_keymap *keymap;
426
427     keymap = uTypedCalloc(1, struct xkb_keymap);
428     if (!keymap)
429         return NULL;
430
431     keymap->refcnt = 1;
432     keymap->ctx = xkb_context_ref(ctx);
433
434     return keymap;
435 }
436
437 void
438 XkbcFreeKeyboard(struct xkb_keymap *keymap)
439 {
440     if (!keymap)
441         return;
442
443     XkbcFreeClientMap(keymap);
444     XkbcFreeServerMap(keymap);
445     XkbcFreeCompatMap(keymap);
446     XkbcFreeIndicatorMaps(keymap);
447     XkbcFreeNames(keymap);
448     XkbcFreeControls(keymap);
449     xkb_context_unref(keymap->ctx);
450     free(keymap);
451 }