b4668ff13026e38c71d1a905ba3167e7f9ca5643
[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                    unsigned nTotalTypes)
32 {
33     struct xkb_client_map * map;
34
35     if (!keymap || ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
36         return BadValue;
37
38     if (!keymap->map) {
39         map = uTypedCalloc(1, struct xkb_client_map);
40         if (!map)
41             return BadAlloc;
42         keymap->map = map;
43     }
44     else
45         map = keymap->map;
46
47     if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
48         if (!map->types) {
49             map->types = uTypedCalloc(nTotalTypes, struct xkb_key_type);
50             if (!map->types)
51                 return BadAlloc;
52
53             map->num_types = 0;
54             map->size_types = nTotalTypes;
55         }
56         else if (map->size_types < nTotalTypes) {
57             struct xkb_key_type *prev_types = map->types;
58
59             map->types = uTypedRealloc(map->types, nTotalTypes,
60                                           struct xkb_key_type);
61             if (!map->types) {
62                 free(prev_types);
63                 map->num_types = map->size_types = 0;
64                 return BadAlloc;
65             }
66
67             map->size_types = nTotalTypes;
68             memset(&map->types[map->num_types], 0,
69                    (map->size_types - map->num_types) * sizeof(struct xkb_key_type));
70         }
71     }
72
73     if (which & XkbKeySymsMask) {
74         if (!map->key_sym_map) {
75             map->key_sym_map = uTypedCalloc(keymap->max_key_code + 1,
76                                             struct xkb_sym_map);
77             if (!map->key_sym_map)
78                 return BadAlloc;
79         }
80     }
81
82     if (which & XkbModifierMapMask) {
83         if (!map->modmap) {
84             map->modmap = uTypedCalloc(keymap->max_key_code + 1,
85                                        unsigned char);
86             if (!map->modmap)
87                 return BadAlloc;
88         }
89     }
90
91     return Success;
92 }
93
94 int
95 XkbcAllocServerMap(struct xkb_keymap *keymap, unsigned which,
96                    unsigned nNewActions)
97 {
98     unsigned i;
99     struct xkb_server_map * map;
100
101     if (!keymap)
102         return BadMatch;
103
104     if (!keymap->server) {
105         map = uTypedCalloc(1, struct xkb_server_map);
106         if (!map)
107             return BadAlloc;
108
109         for (i = 0; i < XkbNumVirtualMods; i++)
110             map->vmods[i] = XkbNoModifierMask;
111
112         keymap->server = map;
113     }
114     else
115         map = keymap->server;
116
117     if (!which)
118         return Success;
119
120     if (!map->explicit) {
121         i = keymap->max_key_code + 1;
122         map->explicit = uTypedCalloc(i, unsigned char);
123         if (!map->explicit)
124             return BadAlloc;
125     }
126
127     if (nNewActions < 1)
128         nNewActions = 1;
129
130     if (!map->acts) {
131         map->acts = uTypedCalloc(nNewActions + 1, union xkb_action);
132         if (!map->acts)
133             return BadAlloc;
134         map->num_acts = 1;
135         map->size_acts = nNewActions + 1;
136     }
137     else if ((map->size_acts - map->num_acts) < (int)nNewActions) {
138         unsigned need;
139         union xkb_action *prev_acts = map->acts;
140
141         need = map->num_acts + nNewActions;
142         map->acts = uTypedRealloc(map->acts, need, union xkb_action);
143         if (!map->acts) {
144             free(prev_acts);
145             map->num_acts = map->size_acts = 0;
146             return BadAlloc;
147         }
148
149         map->size_acts = need;
150         memset(&map->acts[map->num_acts], 0,
151                (map->size_acts - map->num_acts) * sizeof(union xkb_action));
152     }
153
154     if (!map->key_acts) {
155         i = keymap->max_key_code + 1;
156         map->key_acts = uTypedCalloc(i, unsigned short);
157         if (!map->key_acts)
158             return BadAlloc;
159     }
160
161     if (!map->behaviors) {
162         i = keymap->max_key_code + 1;
163         map->behaviors = uTypedCalloc(i, struct xkb_behavior);
164         if (!map->behaviors)
165             return BadAlloc;
166     }
167
168     if (!map->vmodmap) {
169         i = keymap->max_key_code + 1;
170         map->vmodmap = uTypedCalloc(i, uint32_t);
171         if (!map->vmodmap)
172             return BadAlloc;
173     }
174
175     return Success;
176 }
177
178 int
179 XkbcCopyKeyType(struct xkb_key_type * from, struct xkb_key_type * into)
180 {
181     int i;
182
183     if (!from || !into)
184         return BadMatch;
185
186     free(into->map);
187     into->map = NULL;
188     free(into->preserve);
189     into->preserve= NULL;
190     for (i = 0; i < into->num_levels; i++)
191         free(UNCONSTIFY(into->level_names[i]));
192     free(into->level_names);
193     into->level_names = NULL;
194
195     *into = *from;
196
197     if (from->map && (into->map_count > 0)) {
198         into->map = uTypedCalloc(into->map_count, struct xkb_kt_map_entry);
199         if (!into->map)
200             return BadAlloc;
201         memcpy(into->map, from->map,
202                into->map_count * sizeof(struct xkb_kt_map_entry));
203     }
204
205     if (from->preserve && (into->map_count > 0)) {
206         into->preserve = uTypedCalloc(into->map_count, struct xkb_mods);
207         if (!into->preserve)
208             return BadAlloc;
209         memcpy(into->preserve, from->preserve,
210                into->map_count * sizeof(struct xkb_mods));
211     }
212
213     if (from->level_names && (into->num_levels > 0)) {
214         into->level_names = uTypedCalloc(into->num_levels, const char *);
215         if (!into->level_names)
216             return BadAlloc;
217         for (i = 0; i < into->num_levels; i++)
218             into->level_names[i] = strdup(from->level_names[i]);
219     }
220
221     return Success;
222 }
223
224 bool
225 XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
226                   unsigned int needed)
227 {
228     if (keymap->map->key_sym_map[key].size_syms >= needed)
229         return true;
230
231     keymap->map->key_sym_map[key].syms =
232         uTypedRecalloc(keymap->map->key_sym_map[key].syms,
233                        keymap->map->key_sym_map[key].size_syms,
234                        needed,
235                        xkb_keysym_t);
236     if (!keymap->map->key_sym_map[key].syms) {
237         keymap->map->key_sym_map[key].size_syms = 0;
238         return false;
239     }
240     keymap->map->key_sym_map[key].size_syms = needed;
241
242     return true;
243 }
244
245 union xkb_action *
246 XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
247                      uint32_t needed)
248 {
249     xkb_keycode_t i, nActs;
250     union xkb_action *newActs;
251
252     if (needed == 0) {
253         keymap->server->key_acts[key] = 0;
254         return NULL;
255     }
256
257     if (XkbKeyHasActions(keymap, key) &&
258         (XkbKeyGroupsWidth(keymap, key) >= needed))
259         return XkbKeyActionsPtr(keymap, key);
260
261     if (keymap->server->size_acts - keymap->server->num_acts >= (int)needed) {
262         keymap->server->key_acts[key] = keymap->server->num_acts;
263         keymap->server->num_acts += needed;
264
265         return &keymap->server->acts[keymap->server->key_acts[key]];
266     }
267
268     keymap->server->size_acts = keymap->server->num_acts + needed + 8;
269     newActs = uTypedCalloc(keymap->server->size_acts, union xkb_action);
270     if (!newActs)
271         return NULL;
272     newActs[0].type = XkbSA_NoAction;
273     nActs = 1;
274
275     for (i = keymap->min_key_code; i <= keymap->max_key_code; i++) {
276         xkb_keycode_t nKeyActs, nCopy;
277
278         if ((keymap->server->key_acts[i] == 0) && (i != key))
279             continue;
280
281         nCopy = nKeyActs = XkbKeyNumActions(keymap, i);
282         if (i == key) {
283             nKeyActs= needed;
284             if (needed < nCopy)
285                 nCopy = needed;
286         }
287
288         if (nCopy > 0)
289             memcpy(&newActs[nActs], XkbKeyActionsPtr(keymap, i),
290                    nCopy * sizeof(union xkb_action));
291         if (nCopy < nKeyActs)
292             memset(&newActs[nActs + nCopy], 0,
293                    (nKeyActs - nCopy) * sizeof(union xkb_action));
294
295         keymap->server->key_acts[i] = nActs;
296         nActs += nKeyActs;
297     }
298
299     free(keymap->server->acts);
300     keymap->server->acts = newActs;
301     keymap->server->num_acts = nActs;
302
303     return &keymap->server->acts[keymap->server->key_acts[key]];
304 }
305
306 void
307 XkbcFreeClientMap(struct xkb_keymap *keymap)
308 {
309     struct xkb_client_map * map;
310     struct xkb_key_type * type;
311     xkb_keycode_t key;
312     int i;
313
314     if (!keymap || !keymap->map)
315         return;
316
317     map = keymap->map;
318
319     for (i = 0, type = map->types; i < map->num_types && type; i++, type++) {
320         int j;
321         free(type->map);
322         free(type->preserve);
323         for (j = 0; j < type->num_levels; j++)
324             free(UNCONSTIFY(type->level_names[j]));
325         free(type->level_names);
326         free(UNCONSTIFY(type->name));
327     }
328     free(map->types);
329
330     if (map->key_sym_map) {
331         for (key = keymap->min_key_code; key < keymap->max_key_code; key++) {
332             free(map->key_sym_map[key].sym_index);
333             free(map->key_sym_map[key].num_syms);
334             free(map->key_sym_map[key].syms);
335         }
336     }
337     free(map->key_sym_map);
338
339     free(map->modmap);
340     free(keymap->map);
341     keymap->map = NULL;
342 }
343
344 void
345 XkbcFreeServerMap(struct xkb_keymap *keymap)
346 {
347     struct xkb_server_map * map;
348
349     if (keymap || keymap->server)
350         return;
351
352     map = keymap->server;
353
354     free(map->explicit);
355     free(map->key_acts);
356     free(map->acts);
357     free(map->behaviors);
358     free(map->vmodmap);
359     free(keymap->server);
360     keymap->server = NULL;
361 }
362
363 int
364 XkbcAllocCompatMap(struct xkb_keymap *keymap, unsigned nSI)
365 {
366     struct xkb_compat_map * compat;
367     struct xkb_sym_interpret *prev_interpret;
368
369     if (!keymap)
370         return BadMatch;
371
372     if (keymap->compat) {
373         if (keymap->compat->size_si >= nSI)
374             return Success;
375
376         compat = keymap->compat;
377         compat->size_si = nSI;
378         if (!compat->sym_interpret)
379             compat->num_si = 0;
380
381         prev_interpret = compat->sym_interpret;
382         compat->sym_interpret = uTypedRecalloc(compat->sym_interpret,
383                                                compat->num_si, nSI,
384                                                struct xkb_sym_interpret);
385         if (!compat->sym_interpret) {
386             free(prev_interpret);
387             compat->size_si = compat->num_si = 0;
388             return BadAlloc;
389         }
390
391         return Success;
392     }
393
394     compat = uTypedCalloc(1, struct xkb_compat_map);
395     if (!compat)
396         return BadAlloc;
397
398     if (nSI > 0) {
399         compat->sym_interpret = uTypedCalloc(nSI, struct xkb_sym_interpret);
400         if (!compat->sym_interpret) {
401             free(compat);
402             return BadAlloc;
403         }
404     }
405     compat->size_si = nSI;
406     compat->num_si = 0;
407     memset(&compat->groups[0], 0, XkbNumKbdGroups * sizeof(struct xkb_mods));
408     keymap->compat = compat;
409
410     return Success;
411 }
412
413
414 static void
415 XkbcFreeCompatMap(struct xkb_keymap *keymap)
416 {
417     struct xkb_compat_map * compat;
418
419     if (!keymap || !keymap->compat)
420         return;
421
422     compat = keymap->compat;
423
424     free(compat->sym_interpret);
425     free(compat);
426     keymap->compat = NULL;
427 }
428
429 int
430 XkbcAllocNames(struct xkb_keymap *keymap, unsigned which,
431                unsigned nTotalAliases)
432 {
433     struct xkb_names * names;
434
435     if (!keymap)
436         return BadMatch;
437
438     if (!keymap->names) {
439         keymap->names = uTypedCalloc(1, struct xkb_names);
440         if (!keymap->names)
441             return BadAlloc;
442     }
443     names = keymap->names;
444
445     if ((which & XkbKTLevelNamesMask) && keymap->map && keymap->map->types) {
446         int i;
447         struct xkb_key_type * type;
448
449         type = keymap->map->types;
450         for (i = 0; i < keymap->map->num_types; i++, type++) {
451             if (!type->level_names) {
452                 type->level_names = uTypedCalloc(type->num_levels, const char *);
453                 if (!type->level_names)
454                     return BadAlloc;
455             }
456         }
457     }
458
459     if ((which & XkbKeyNamesMask) && !names->keys) {
460         names->keys = uTypedCalloc(keymap->max_key_code + 1,
461                                    struct xkb_key_name);
462         if (!names->keys)
463             return BadAlloc;
464     }
465
466     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
467         if (!names->key_aliases)
468             names->key_aliases = uTypedCalloc(nTotalAliases,
469                                                  struct xkb_key_alias);
470         else if (nTotalAliases > names->num_key_aliases) {
471             struct xkb_key_alias *prev_aliases = names->key_aliases;
472
473             names->key_aliases = uTypedRecalloc(names->key_aliases,
474                                                 names->num_key_aliases,
475                                                 nTotalAliases,
476                                                 struct xkb_key_alias);
477             if (!names->key_aliases)
478                 free(prev_aliases);
479         }
480
481         if (!names->key_aliases) {
482             names->num_key_aliases = 0;
483             return BadAlloc;
484         }
485
486         names->num_key_aliases = nTotalAliases;
487     }
488
489     return Success;
490 }
491
492 static void
493 XkbcFreeNames(struct xkb_keymap *keymap)
494 {
495     struct xkb_names * names;
496     struct xkb_client_map * map;
497     int i;
498
499     if (!keymap || !keymap->names)
500         return;
501
502     names = keymap->names;
503     map = keymap->map;
504
505     if (map && map->types) {
506         struct xkb_key_type * type = map->types;
507
508         for (i = 0; i < map->num_types; i++, type++) {
509             int j;
510             for (j = 0; j < type->num_levels; j++)
511                 free(UNCONSTIFY(type->level_names[i]));
512             free(type->level_names);
513             type->level_names = NULL;
514         }
515     }
516
517     for (i = 0; i < XkbNumVirtualMods; i++)
518         free(UNCONSTIFY(names->vmods[i]));
519     for (i = 0; i < XkbNumIndicators; i++)
520         free(UNCONSTIFY(names->indicators[i]));
521     for (i = 0; i < XkbNumKbdGroups; i++)
522         free(UNCONSTIFY(names->groups[i]));
523
524     free(names->keys);
525     free(names->key_aliases);
526     free(names);
527     keymap->names = NULL;
528 }
529
530 int
531 XkbcAllocControls(struct xkb_keymap *keymap)
532 {
533     if (!keymap)
534         return BadMatch;
535
536     if (!keymap->ctrls) {
537         keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
538         if (!keymap->ctrls)
539             return BadAlloc;
540     }
541
542     keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
543                                                  unsigned char);
544     if (!keymap->ctrls->per_key_repeat)
545         return BadAlloc;
546
547     return Success;
548 }
549
550 static void
551 XkbcFreeControls(struct xkb_keymap *keymap)
552 {
553     if (keymap && keymap->ctrls) {
554         free(keymap->ctrls->per_key_repeat);
555         free(keymap->ctrls);
556         keymap->ctrls = NULL;
557     }
558 }
559
560 int
561 XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
562 {
563     if (!keymap)
564         return BadMatch;
565
566     if (!keymap->indicators) {
567         keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
568         if (!keymap->indicators)
569             return BadAlloc;
570     }
571
572     return Success;
573 }
574
575 static void
576 XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
577 {
578     if (keymap) {
579         free(keymap->indicators);
580         keymap->indicators = NULL;
581     }
582 }
583
584 struct xkb_keymap *
585 XkbcAllocKeyboard(struct xkb_ctx *ctx)
586 {
587     struct xkb_keymap *keymap;
588
589     keymap = uTypedCalloc(1, struct xkb_keymap);
590     if (!keymap)
591         return NULL;
592
593     keymap->refcnt = 1;
594     keymap->ctx = xkb_ctx_ref(ctx);
595
596     return keymap;
597 }
598
599 void
600 XkbcFreeKeyboard(struct xkb_keymap *keymap)
601 {
602     if (!keymap)
603         return;
604
605     XkbcFreeClientMap(keymap);
606     XkbcFreeServerMap(keymap);
607     XkbcFreeCompatMap(keymap);
608     XkbcFreeIndicatorMaps(keymap);
609     XkbcFreeNames(keymap);
610     XkbcFreeControls(keymap);
611     xkb_ctx_unref(keymap->ctx);
612     free(keymap);
613 }