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