Get rid of xkb_indicator
[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 XkbcCopyKeyType(const struct xkb_key_type *from, struct xkb_key_type *into)
31 {
32     int i;
33
34     if (!from || !into)
35         return BadMatch;
36
37     darray_free(into->map);
38     free(into->preserve);
39     for (i = 0; i < into->num_levels; i++)
40         free(into->level_names[i]);
41     free(into->level_names);
42
43     *into = *from;
44
45     darray_copy(into->map, from->map);
46
47     if (from->preserve && !darray_empty(into->map)) {
48         into->preserve = calloc(darray_size(into->map),
49                                 sizeof(*into->preserve));
50         if (!into->preserve)
51             return BadAlloc;
52         memcpy(into->preserve, from->preserve,
53                darray_size(into->map) * sizeof(*into->preserve));
54     }
55
56     if (from->level_names && into->num_levels > 0) {
57         into->level_names = calloc(into->num_levels,
58                                    sizeof(*into->level_names));
59         if (!into->level_names)
60             return BadAlloc;
61
62         for (i = 0; i < into->num_levels; i++)
63             into->level_names[i] = strdup(from->level_names[i]);
64     }
65
66     return Success;
67 }
68
69 bool
70 XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
71                   unsigned int needed)
72 {
73     darray_resize0(darray_item(keymap->key_sym_map, key).syms, needed);
74     return true;
75 }
76
77 union xkb_action *
78 XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
79                      uint32_t needed)
80 {
81     size_t old_ndx, old_num_acts, new_ndx;
82
83     if (needed == 0) {
84         darray_item(keymap->key_acts, key) = 0;
85         return NULL;
86     }
87
88     if (XkbKeyHasActions(keymap, key) &&
89         XkbKeyGroupsWidth(keymap, key) >= needed)
90         return XkbKeyActionsPtr(keymap, key);
91
92     /*
93      * The key may already be in the array, but without enough space.
94      * This should not happen often, so in order to avoid moving and
95      * copying stuff from acts and key_acts, we just allocate new
96      * space for the key at the end, and leave the old space alone.
97      */
98
99     old_ndx = darray_item(keymap->key_acts, key);
100     old_num_acts = XkbKeyNumActions(keymap, key);
101     new_ndx = darray_size(keymap->acts);
102
103     darray_resize0(keymap->acts, new_ndx + needed);
104     darray_item(keymap->key_acts, key) = new_ndx;
105
106     /*
107      * The key was already in the array, copy the old actions to the
108      * new space.
109      */
110     if (old_ndx != 0)
111         memcpy(darray_mem(keymap->acts, new_ndx),
112                darray_mem(keymap->acts, old_ndx),
113                old_num_acts * sizeof(union xkb_action));
114
115     return XkbKeyActionsPtr(keymap, key);
116 }
117
118 static void
119 free_types(struct xkb_keymap *keymap)
120 {
121     struct xkb_key_type *type;
122
123     darray_foreach(type, keymap->types) {
124         int j;
125         darray_free(type->map);
126         free(type->preserve);
127         for (j = 0; j < type->num_levels; j++)
128             free(type->level_names[j]);
129         free(type->level_names);
130         free(type->name);
131     }
132     darray_free(keymap->types);
133 }
134
135 static void
136 free_sym_maps(struct xkb_keymap *keymap)
137 {
138     struct xkb_sym_map *sym_map;
139
140     darray_foreach(sym_map, keymap->key_sym_map) {
141         free(sym_map->sym_index);
142         free(sym_map->num_syms);
143         darray_free(sym_map->syms);
144     }
145     darray_free(keymap->key_sym_map);
146 }
147
148 int
149 XkbcAllocNames(struct xkb_keymap *keymap, unsigned which,
150                size_t nTotalAliases)
151 {
152     if (!keymap)
153         return BadMatch;
154
155     if (!keymap->names) {
156         keymap->names = calloc(1, sizeof(*keymap->names));
157         if (!keymap->names)
158             return BadAlloc;
159
160         darray_init(keymap->names->keys);
161         darray_init(keymap->names->key_aliases);
162     }
163
164     if ((which & XkbKTLevelNamesMask) && keymap) {
165         struct xkb_key_type * type;
166
167         darray_foreach(type, keymap->types) {
168             if (!type->level_names) {
169                 type->level_names = calloc(type->num_levels,
170                                            sizeof(*type->level_names));
171                 if (!type->level_names)
172                     return BadAlloc;
173             }
174         }
175     }
176
177     if (which & XkbKeyNamesMask)
178         darray_resize0(keymap->names->keys, keymap->max_key_code + 1);
179
180     if (which & XkbKeyAliasesMask)
181         darray_resize0(keymap->names->key_aliases, nTotalAliases);
182
183     return Success;
184 }
185
186 static void
187 XkbcFreeNames(struct xkb_keymap *keymap)
188 {
189     struct xkb_names * names;
190     struct xkb_key_type *type;
191     int i;
192
193     if (!keymap || !keymap->names)
194         return;
195
196     names = keymap->names;
197
198     darray_foreach(type, keymap->types) {
199         int j;
200         for (j = 0; j < type->num_levels; j++)
201             free(type->level_names[j]);
202         free(type->level_names);
203         type->level_names = NULL;
204     }
205
206     free(names->keycodes);
207     free(names->symbols);
208     free(names->keytypes);
209     free(names->compat);
210
211     for (i = 0; i < XkbNumVirtualMods; i++)
212         free(names->vmods[i]);
213     for (i = 0; i < XkbNumIndicators; i++)
214         free(names->indicators[i]);
215     for (i = 0; i < XkbNumKbdGroups; i++)
216         free(names->groups[i]);
217
218     darray_free(names->keys);
219     darray_free(names->key_aliases);
220     free(names);
221     keymap->names = NULL;
222 }
223
224 int
225 XkbcAllocControls(struct xkb_keymap *keymap)
226 {
227     if (!keymap)
228         return BadMatch;
229
230     if (!keymap->ctrls) {
231         keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
232         if (!keymap->ctrls)
233             return BadAlloc;
234     }
235
236     keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
237                                                  unsigned char);
238     if (!keymap->ctrls->per_key_repeat)
239         return BadAlloc;
240
241     return Success;
242 }
243
244 static void
245 XkbcFreeControls(struct xkb_keymap *keymap)
246 {
247     if (keymap && keymap->ctrls) {
248         free(keymap->ctrls->per_key_repeat);
249         free(keymap->ctrls);
250         keymap->ctrls = NULL;
251     }
252 }
253
254 struct xkb_keymap *
255 XkbcAllocKeyboard(struct xkb_context *ctx)
256 {
257     struct xkb_keymap *keymap;
258
259     keymap = uTypedCalloc(1, struct xkb_keymap);
260     if (!keymap)
261         return NULL;
262
263     keymap->refcnt = 1;
264     keymap->ctx = xkb_context_ref(ctx);
265
266     return keymap;
267 }
268
269 void
270 XkbcFreeKeyboard(struct xkb_keymap *keymap)
271 {
272     if (!keymap)
273         return;
274
275     free_types(keymap);
276     free_sym_maps(keymap);
277     free(keymap->modmap);
278     free(keymap->explicit);
279     darray_free(keymap->key_acts);
280     darray_free(keymap->acts);
281     free(keymap->behaviors);
282     free(keymap->vmodmap);
283     darray_free(keymap->sym_interpret);
284     XkbcFreeNames(keymap);
285     XkbcFreeControls(keymap);
286     xkb_context_unref(keymap->ctx);
287     free(keymap);
288 }