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