965821c11fd011d8239b28ebbcb389346b1fd40c
[platform/upstream/libxkbcommon.git] / src / malloc.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
27 #include "xkballoc.h"
28 #include "xkbcommon/xkbcommon.h"
29 #include "XKBcommonint.h"
30
31 int
32 XkbcAllocClientMap(struct xkb_desc * xkb, unsigned which, unsigned nTotalTypes)
33 {
34     int i;
35     struct xkb_client_map * map;
36
37     if (!xkb || ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
38         return BadValue;
39
40     if ((which & XkbKeySymsMask) && !xkb_keymap_keycode_range_is_legal(xkb)) {
41 #ifdef DEBUG
42         fprintf(stderr, "bad keycode (%d,%d) in XkbAllocClientMap\n",
43                 xkb->min_key_code, xkb->max_key_code);
44 #endif
45         return BadValue;
46     }
47
48     if (!xkb->map) {
49         map = _XkbTypedCalloc(1, struct xkb_client_map);
50         if (!map)
51             return BadAlloc;
52         xkb->map = map;
53     }
54     else
55         map = xkb->map;
56
57     if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
58         if (!map->types) {
59             map->types = _XkbTypedCalloc(nTotalTypes, struct xkb_key_type);
60             if (!map->types)
61                 return BadAlloc;
62
63             map->num_types = 0;
64             map->size_types = nTotalTypes;
65         }
66         else if (map->size_types < nTotalTypes) {
67             struct xkb_key_type *prev_types = map->types;
68
69             map->types = _XkbTypedRealloc(map->types, nTotalTypes,
70                                           struct xkb_key_type);
71             if (!map->types) {
72                 free(prev_types);
73                 map->num_types = map->size_types = 0;
74                 return BadAlloc;
75             }
76
77             map->size_types = nTotalTypes;
78             bzero(&map->types[map->num_types],
79                   (map->size_types - map->num_types) * sizeof(struct xkb_key_type));
80         }
81     }
82
83     if (which & XkbKeySymsMask) {
84         int nKeys = XkbNumKeys(xkb);
85
86         if (!map->syms) {
87             map->size_syms = (nKeys * 15) / 10;
88             map->syms = _XkbTypedCalloc(map->size_syms, uint32_t);
89             if (!map->syms) {
90                 map->size_syms = 0;
91                 return BadAlloc;
92             }
93             map->num_syms = 1;
94             map->syms[0] = NoSymbol;
95         }
96
97         if (!map->key_sym_map) {
98             i = xkb->max_key_code + 1;
99             map->key_sym_map = _XkbTypedCalloc(i, struct xkb_sym_map);
100             if (!map->key_sym_map)
101                 return BadAlloc;
102         }
103     }
104
105     if (which & XkbModifierMapMask) {
106         if (!xkb_keymap_keycode_range_is_legal(xkb))
107             return BadMatch;
108
109         if (!map->modmap) {
110             i = xkb->max_key_code + 1;
111             map->modmap = _XkbTypedCalloc(i, unsigned char);
112             if (!map->modmap)
113                 return BadAlloc;
114         }
115     }
116
117     return Success;
118 }
119
120 int
121 XkbcAllocServerMap(struct xkb_desc * xkb, unsigned which, unsigned nNewActions)
122 {
123     int i;
124     struct xkb_server_map * map;
125
126     if (!xkb)
127         return BadMatch;
128
129     if (!xkb->server) {
130         map = _XkbTypedCalloc(1, struct xkb_server_map);
131         if (!map)
132             return BadAlloc;
133
134         for (i = 0; i < XkbNumVirtualMods; i++)
135             map->vmods[i] = XkbNoModifierMask;
136
137         xkb->server = map;
138     }
139     else
140         map = xkb->server;
141
142     if (!which)
143         return Success;
144
145     if (!xkb_keymap_keycode_range_is_legal(xkb))
146         return BadMatch;
147
148     if (which & XkbExplicitComponentsMask) {
149         if (!map->explicit) {
150             i = xkb->max_key_code + 1;
151             map->explicit = _XkbTypedCalloc(i, unsigned char);
152             if (!map->explicit)
153                 return BadAlloc;
154         }
155     }
156
157     if (which&XkbKeyActionsMask) {
158         if (nNewActions < 1)
159             nNewActions = 1;
160
161         if (!map->acts) {
162             map->acts = _XkbTypedCalloc(nNewActions + 1, union xkb_action);
163             if (!map->acts)
164                 return BadAlloc;
165             map->num_acts = 1;
166             map->size_acts = nNewActions + 1;
167         }
168         else if ((map->size_acts - map->num_acts) < nNewActions) {
169             unsigned need;
170             union xkb_action *prev_acts = map->acts;
171
172             need = map->num_acts + nNewActions;
173             map->acts = _XkbTypedRealloc(map->acts, need, union xkb_action);
174             if (!map->acts) {
175                 free(prev_acts);
176                 map->num_acts = map->size_acts = 0;
177                 return BadAlloc;
178             }
179
180             map->size_acts = need;
181             bzero(&map->acts[map->num_acts],
182                   (map->size_acts - map->num_acts) * sizeof(union xkb_action));
183         }
184
185         if (!map->key_acts) {
186             i = xkb->max_key_code + 1;
187             map->key_acts = _XkbTypedCalloc(i, unsigned short);
188             if (!map->key_acts)
189                 return BadAlloc;
190         }
191     }
192
193     if (which & XkbKeyBehaviorsMask) {
194         if (!map->behaviors) {
195             i = xkb->max_key_code + 1;
196             map->behaviors = _XkbTypedCalloc(i, struct xkb_behavior);
197             if (!map->behaviors)
198                 return BadAlloc;
199         }
200     }
201
202     if (which & XkbVirtualModMapMask) {
203         if (!map->vmodmap) {
204             i = xkb->max_key_code + 1;
205             map->vmodmap = _XkbTypedCalloc(i, uint32_t);
206             if (!map->vmodmap)
207                 return BadAlloc;
208         }
209     }
210
211     return Success;
212 }
213
214 int
215 XkbcCopyKeyType(struct xkb_key_type * from, struct xkb_key_type * into)
216 {
217     if (!from || !into)
218         return BadMatch;
219
220     free(into->map);
221     into->map = NULL;
222     free(into->preserve);
223     into->preserve= NULL;
224     free(into->level_names);
225     into->level_names = NULL;
226
227     *into = *from;
228
229     if (from->map && (into->map_count > 0)) {
230         into->map = _XkbTypedCalloc(into->map_count, struct xkb_kt_map_entry);
231         if (!into->map)
232             return BadAlloc;
233         memcpy(into->map, from->map,
234                into->map_count * sizeof(struct xkb_kt_map_entry));
235     }
236
237     if (from->preserve && (into->map_count > 0)) {
238         into->preserve = _XkbTypedCalloc(into->map_count, struct xkb_mods);
239         if (!into->preserve)
240             return BadAlloc;
241         memcpy(into->preserve, from->preserve,
242                into->map_count * sizeof(struct xkb_mods));
243     }
244
245     if (from->level_names && (into->num_levels > 0)) {
246         into->level_names = _XkbTypedCalloc(into->num_levels, uint32_t);
247         if (!into->level_names)
248             return BadAlloc;
249         memcpy(into->level_names, from->level_names,
250                into->num_levels * sizeof(uint32_t));
251     }
252
253     return Success;
254 }
255
256 uint32_t *
257 XkbcResizeKeySyms(struct xkb_desc * xkb, xkb_keycode_t key,
258                   unsigned int needed)
259 {
260     uint32_t i, nSyms, nKeySyms;
261     uint32_t nOldSyms;
262     uint32_t *newSyms;
263
264     if (needed == 0) {
265         xkb->map->key_sym_map[key].offset = 0;
266         return xkb->map->syms;
267     }
268
269     nOldSyms = XkbKeyNumSyms(xkb, key);
270     if (nOldSyms >= needed)
271         return XkbKeySymsPtr(xkb, key);
272
273     if (xkb->map->size_syms - xkb->map->num_syms >= needed) {
274         if (nOldSyms > 0)
275             memcpy(&xkb->map->syms[xkb->map->num_syms],
276                    XkbKeySymsPtr(xkb, key), nOldSyms * sizeof(uint32_t));
277
278         if ((needed - nOldSyms) > 0)
279             bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)],
280                   (needed - nOldSyms) * sizeof(uint32_t));
281
282         xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
283         xkb->map->num_syms += needed;
284
285         return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
286     }
287
288     xkb->map->size_syms += (needed > 32 ? needed : 32);
289     newSyms = _XkbTypedCalloc(xkb->map->size_syms, uint32_t);
290     if (!newSyms)
291         return NULL;
292
293     newSyms[0] = NoSymbol;
294     nSyms = 1;
295     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
296         int nCopy;
297
298         nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
299         if ((nKeySyms == 0) && (i != key))
300             continue;
301
302         if (i == key)
303             nKeySyms = needed;
304         if (nCopy != 0)
305            memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
306                   nCopy * sizeof(uint32_t));
307         if (nKeySyms > nCopy)
308             bzero(&newSyms[nSyms+nCopy], (nKeySyms - nCopy) * sizeof(uint32_t));
309
310         xkb->map->key_sym_map[i].offset = nSyms;
311         nSyms += nKeySyms;
312     }
313
314     free(xkb->map->syms);
315     xkb->map->syms = newSyms;
316     xkb->map->num_syms = nSyms;
317
318     return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
319 }
320
321 union xkb_action *
322 XkbcResizeKeyActions(struct xkb_desc * xkb, xkb_keycode_t key, int needed)
323 {
324     xkb_keycode_t i, nActs;
325     union xkb_action *newActs;
326
327     if (needed == 0) {
328         xkb->server->key_acts[key] = 0;
329         return NULL;
330     }
331
332     if (XkbKeyHasActions(xkb, key) &&
333         (XkbKeyNumSyms(xkb, key) >= (unsigned)needed))
334         return XkbKeyActionsPtr(xkb, key);
335
336     if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned)needed) {
337         xkb->server->key_acts[key] = xkb->server->num_acts;
338         xkb->server->num_acts += needed;
339
340         return &xkb->server->acts[xkb->server->key_acts[key]];
341     }
342
343     xkb->server->size_acts = xkb->server->num_acts + needed + 8;
344     newActs = _XkbTypedCalloc(xkb->server->size_acts, union xkb_action);
345     if (!newActs)
346         return NULL;
347     newActs[0].type = XkbSA_NoAction;
348     nActs = 1;
349
350     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
351         xkb_keycode_t nKeyActs, nCopy;
352
353         if ((xkb->server->key_acts[i] == 0) && (i != key))
354             continue;
355
356         nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
357         if (i == key) {
358             nKeyActs= needed;
359             if (needed < nCopy)
360                 nCopy = needed;
361         }
362
363         if (nCopy > 0)
364             memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
365                    nCopy * sizeof(union xkb_action));
366         if (nCopy < nKeyActs)
367             bzero(&newActs[nActs + nCopy],
368                   (nKeyActs - nCopy) * sizeof(union xkb_action));
369
370         xkb->server->key_acts[i] = nActs;
371         nActs += nKeyActs;
372     }
373
374     free(xkb->server->acts);
375     xkb->server->acts = newActs;
376     xkb->server->num_acts = nActs;
377
378     return &xkb->server->acts[xkb->server->key_acts[key]];
379 }
380
381 void
382 XkbcFreeClientMap(struct xkb_desc * xkb, unsigned what, Bool freeMap)
383 {
384     struct xkb_client_map * map;
385
386     if (!xkb || !xkb->map)
387         return;
388
389     if (freeMap)
390         what = XkbAllClientInfoMask;
391     map = xkb->map;
392
393     if (what & XkbKeyTypesMask) {
394         int i;
395         struct xkb_key_type * type;
396
397         for (i = 0, type = map->types; i < map->num_types && type; i++, type++) {
398             free(type->map);
399             type->map = NULL;
400             free(type->preserve);
401             type->preserve = NULL;
402             type->map_count = 0;
403             free(type->level_names);
404             type->level_names = NULL;
405         }
406         free(map->types);
407         map->num_types = map->size_types = 0;
408         map->types = NULL;
409     }
410
411     if (what & XkbKeySymsMask) {
412         free(map->key_sym_map);
413         map->key_sym_map = NULL;
414         free(map->syms);
415         map->size_syms = map->num_syms = 0;
416         map->syms = NULL;
417     }
418
419     if (what & XkbModifierMapMask) {
420         free(map->modmap);
421         map->modmap = NULL;
422     }
423
424     if (freeMap) {
425         free(xkb->map);
426         xkb->map = NULL;
427     }
428 }
429
430 void
431 XkbcFreeServerMap(struct xkb_desc * xkb, unsigned what, Bool freeMap)
432 {
433     struct xkb_server_map * map;
434
435     if (!xkb || !xkb->server)
436         return;
437
438     if (freeMap)
439         what = XkbAllServerInfoMask;
440     map = xkb->server;
441
442     if (what & XkbExplicitComponentsMask) {
443         free(map->explicit);
444         map->explicit = NULL;
445     }
446
447     if (what & XkbKeyActionsMask) {
448         free(map->key_acts);
449         map->key_acts = NULL;
450         free(map->acts);
451         map->num_acts = map->size_acts = 0;
452         map->acts = NULL;
453     }
454
455     if (what & XkbKeyBehaviorsMask) {
456         free(map->behaviors);
457         map->behaviors = NULL;
458     }
459
460     if (what & XkbVirtualModMapMask) {
461         free(map->vmodmap);
462         map->vmodmap = NULL;
463     }
464
465     if (freeMap) {
466         free(xkb->server);
467         xkb->server = NULL;
468     }
469 }