Add XkbDescRec initializers and destructors
[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 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "X11/XkbCommon.h"
30 #include "XkbCommonInt.h"
31 #include <X11/X.h>
32 #include <X11/Xdefs.h>
33 #include <X11/extensions/XKB.h>
34
35 int
36 XkbcAllocCompatMap(XkbcDescPtr xkb,unsigned which,unsigned nSI)
37 {
38 XkbCompatMapPtr compat;
39 XkbSymInterpretRec *prev_interpret;
40
41     if (!xkb)
42         return BadMatch;
43     if (xkb->compat) {
44         if (xkb->compat->size_si>=nSI)
45             return Success;
46         compat= xkb->compat;
47         compat->size_si= nSI;
48         if (compat->sym_interpret==NULL)
49             compat->num_si= 0;
50         prev_interpret = compat->sym_interpret;
51         compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
52                                                      nSI,XkbSymInterpretRec);
53         if (compat->sym_interpret==NULL) {
54             _XkbFree(prev_interpret);
55             compat->size_si= compat->num_si= 0;
56             return BadAlloc;
57         }
58         if (compat->num_si!=0) {
59             _XkbClearElems(compat->sym_interpret,compat->num_si,
60                                         compat->size_si-1,XkbSymInterpretRec);
61         }
62         return Success;
63     }
64     compat= _XkbTypedCalloc(1,XkbCompatMapRec);
65     if (compat==NULL)
66         return BadAlloc;
67     if (nSI>0) {
68         compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec);
69         if (!compat->sym_interpret) {
70             _XkbFree(compat);
71             return BadAlloc;
72         }
73     }
74     compat->size_si= nSI;
75     compat->num_si= 0;
76     bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
77     xkb->compat= compat;
78     return Success;
79 }
80
81
82 void
83 XkbcFreeCompatMap(XkbcDescPtr xkb,unsigned which,Bool freeMap)
84 {
85 register XkbCompatMapPtr compat;
86
87     if ((xkb==NULL)||(xkb->compat==NULL))
88         return;
89     compat= xkb->compat;
90     if (freeMap)
91         which= XkbAllCompatMask;
92     if (which&XkbGroupCompatMask)
93         bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
94     if (which&XkbSymInterpMask) {
95         if ((compat->sym_interpret)&&(compat->size_si>0))
96             _XkbFree(compat->sym_interpret);
97         compat->size_si= compat->num_si= 0;
98         compat->sym_interpret= NULL;
99     }
100     if (freeMap) {
101         _XkbFree(compat);
102         xkb->compat= NULL;
103     }
104     return;
105 }
106
107 int
108 XkbcAllocNames(XkbcDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases)
109 {
110 XkbNamesPtr     names;
111
112     if (xkb==NULL)
113         return BadMatch;
114     if (xkb->names==NULL) {
115         xkb->names = _XkbTypedCalloc(1,XkbNamesRec);
116         if (xkb->names==NULL)
117             return BadAlloc;
118     }
119     names= xkb->names;
120     if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){
121         register int    i;
122         XkbKeyTypePtr   type;
123
124         type= xkb->map->types;
125         for (i=0;i<xkb->map->num_types;i++,type++) {
126             if (type->level_names==NULL) {
127                 type->level_names= _XkbTypedCalloc(type->num_levels,Atom);
128                 if (type->level_names==NULL)
129                     return BadAlloc;
130             }
131         }
132     }
133     if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) {
134         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
135             (!XkbIsLegalKeycode(xkb->max_key_code))||
136             (xkb->max_key_code<xkb->min_key_code))
137             return BadValue;
138         names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec);
139         if (names->keys==NULL)
140             return BadAlloc;
141     }
142     if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) {
143         if (names->key_aliases==NULL) {
144             names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec);
145         }
146         else if (nTotalAliases>names->num_key_aliases) {
147             XkbKeyAliasRec *prev_aliases = names->key_aliases;
148
149             names->key_aliases= _XkbTypedRealloc(names->key_aliases,
150                                                 nTotalAliases,XkbKeyAliasRec);
151             if (names->key_aliases!=NULL) {
152                 _XkbClearElems(names->key_aliases,names->num_key_aliases,
153                                                 nTotalAliases-1,XkbKeyAliasRec);
154             } else {
155                 _XkbFree(prev_aliases);
156             }
157         }
158         if (names->key_aliases==NULL) {
159             names->num_key_aliases= 0;
160             return BadAlloc;
161         }
162         names->num_key_aliases= nTotalAliases;
163     }
164     if ((which&XkbRGNamesMask)&&(nTotalRG>0)) {
165         if (names->radio_groups==NULL) {
166             names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom);
167         }
168         else if (nTotalRG>names->num_rg) {
169             Atom *prev_radio_groups = names->radio_groups;
170
171             names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG,
172                                                                         Atom);
173             if (names->radio_groups!=NULL) {
174                 _XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1,
175                                                                         Atom);
176             } else {
177                 _XkbFree(prev_radio_groups);
178             }
179         }
180         if (names->radio_groups==NULL)
181             return BadAlloc;
182         names->num_rg= nTotalRG;
183     }
184     return Success;
185 }
186
187 void
188 XkbcFreeNames(XkbcDescPtr xkb,unsigned which,Bool freeMap)
189 {
190 XkbNamesPtr     names;
191
192     if ((xkb==NULL)||(xkb->names==NULL))
193         return;
194     names= xkb->names;
195     if (freeMap)
196         which= XkbAllNamesMask;
197     if (which&XkbKTLevelNamesMask) {
198         XkbClientMapPtr map= xkb->map;
199         if ((map!=NULL)&&(map->types!=NULL)) {
200             register int                i;
201             register XkbKeyTypePtr      type;
202             type= map->types;
203             for (i=0;i<map->num_types;i++,type++) {
204                 if (type->level_names!=NULL) {
205                     _XkbFree(type->level_names);
206                     type->level_names= NULL;
207                 }
208             }
209         }
210     }
211     if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
212         _XkbFree(names->keys);
213         names->keys= NULL;
214         names->num_keys= 0;
215     }
216     if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){
217         _XkbFree(names->key_aliases);
218         names->key_aliases=NULL;
219         names->num_key_aliases=0;
220     }
221     if ((which&XkbRGNamesMask)&&(names->radio_groups)) {
222         _XkbFree(names->radio_groups);
223         names->radio_groups= NULL;
224         names->num_rg= 0;
225     }
226     if (freeMap) {
227         _XkbFree(names);
228         xkb->names= NULL;
229     }
230     return;
231 }
232
233 int
234 XkbcAllocControls(XkbcDescPtr xkb,unsigned which)
235 {
236     if (xkb==NULL)
237         return BadMatch;
238
239     if (xkb->ctrls==NULL) {
240         xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec);
241         if (!xkb->ctrls)
242             return BadAlloc;
243     }
244     return Success;
245 }
246
247 void
248 XkbcFreeControls(XkbcDescPtr xkb,unsigned which,Bool freeMap)
249 {
250     if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) {
251         _XkbFree(xkb->ctrls);
252         xkb->ctrls= NULL;
253     }
254     return;
255 }
256
257 int
258 XkbcAllocIndicatorMaps(XkbcDescPtr xkb)
259 {
260     if (xkb==NULL)
261         return BadMatch;
262     if (xkb->indicators==NULL) {
263         xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec);
264         if (!xkb->indicators)
265             return BadAlloc;
266     }
267     return Success;
268 }
269
270 void
271 XkbcFreeIndicatorMaps(XkbcDescPtr xkb)
272 {
273     if ((xkb!=NULL)&&(xkb->indicators!=NULL)) {
274         _XkbFree(xkb->indicators);
275         xkb->indicators= NULL;
276     }
277     return;
278 }
279
280 XkbcDescRec     *
281 XkbcAllocKeyboard(void)
282 {
283 XkbcDescRec *xkb;
284
285     xkb = _XkbTypedCalloc(1,XkbcDescRec);
286     if (xkb)
287         xkb->device_spec= XkbUseCoreKbd;
288     return xkb;
289 }
290
291 void
292 XkbcFreeKeyboard(XkbcDescPtr xkb,unsigned which,Bool freeAll)
293 {
294     if (xkb==NULL)
295         return;
296     if (freeAll)
297         which= XkbAllComponentsMask;
298     if (which&XkbClientMapMask)
299         XkbcFreeClientMap(xkb,XkbAllClientInfoMask,True);
300     if (which&XkbServerMapMask)
301         XkbcFreeServerMap(xkb,XkbAllServerInfoMask,True);
302     if (which&XkbCompatMapMask)
303         XkbcFreeCompatMap(xkb,XkbAllCompatMask,True);
304     if (which&XkbIndicatorMapMask)
305         XkbcFreeIndicatorMaps(xkb);
306     if (which&XkbNamesMask)
307         XkbcFreeNames(xkb,XkbAllNamesMask,True);
308     if ((which&XkbGeometryMask) && (xkb->geom!=NULL))
309         XkbcFreeGeometry(xkb->geom,XkbGeomAllMask,True);
310     if (which&XkbControlsMask)
311         XkbcFreeControls(xkb,XkbAllControlsMask,True);
312     if (freeAll)
313         _XkbFree(xkb);
314     return;
315 }
316
317 int
318 XkbcAllocClientMap(XkbcDescPtr xkb,unsigned which,unsigned nTotalTypes)
319 {
320 register int    i;
321 XkbClientMapPtr map;
322
323     if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
324         return BadValue;
325     if ((which&XkbKeySymsMask)&&
326         ((!XkbIsLegalKeycode(xkb->min_key_code))||
327          (!XkbIsLegalKeycode(xkb->max_key_code))||
328          (xkb->max_key_code<xkb->min_key_code))) {
329 #ifdef DEBUG
330 fprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n",
331                                 xkb->min_key_code,xkb->max_key_code);
332 #endif
333         return BadValue;
334     }
335
336     if (xkb->map==NULL) {
337         map= _XkbTypedCalloc(1,XkbClientMapRec);
338         if (map==NULL)
339             return BadAlloc;
340         xkb->map= map;
341     }
342     else map= xkb->map;
343
344     if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
345         if (map->types==NULL) {
346             map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec);
347             if (map->types==NULL)
348                 return BadAlloc;
349             map->num_types= 0;
350             map->size_types= nTotalTypes;
351         }
352         else if (map->size_types<nTotalTypes) {
353             XkbKeyTypeRec *prev_types = map->types;
354
355             map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec);
356             if (map->types==NULL) {
357                 _XkbFree(prev_types);
358                 map->num_types= map->size_types= 0;
359                 return BadAlloc;
360             }
361             map->size_types= nTotalTypes;
362             bzero(&map->types[map->num_types],
363                   ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
364         }
365     }
366     if (which&XkbKeySymsMask) {
367         int nKeys= XkbNumKeys(xkb);
368         if (map->syms==NULL) {
369             map->size_syms= (nKeys*15)/10;
370             map->syms= _XkbTypedCalloc(map->size_syms,KeySym);
371             if (!map->syms) {
372                 map->size_syms= 0;
373                 return BadAlloc;
374             }
375             map->num_syms= 1;
376             map->syms[0]= NoSymbol;
377         }
378         if (map->key_sym_map==NULL) {
379             i= xkb->max_key_code+1;
380             map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec);
381             if (map->key_sym_map==NULL)
382                 return BadAlloc;
383         }
384     }
385     if (which&XkbModifierMapMask) {
386         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
387             (!XkbIsLegalKeycode(xkb->max_key_code))||
388             (xkb->max_key_code<xkb->min_key_code))
389             return BadMatch;
390         if (map->modmap==NULL) {
391             i= xkb->max_key_code+1;
392             map->modmap= _XkbTypedCalloc(i,unsigned char);
393             if (map->modmap==NULL)
394                 return BadAlloc;
395         }
396     }
397     return Success;
398 }
399
400 int
401 XkbcAllocServerMap(XkbcDescPtr xkb,unsigned which,unsigned nNewActions)
402 {
403 register int    i;
404 XkbServerMapPtr map;
405
406     if (xkb==NULL)
407         return BadMatch;
408     if (xkb->server==NULL) {
409         map= _XkbTypedCalloc(1,XkbServerMapRec);
410         if (map==NULL)
411             return BadAlloc;
412         for (i=0;i<XkbNumVirtualMods;i++) {
413             map->vmods[i]= XkbNoModifierMask;
414         }
415         xkb->server= map;
416     }
417     else map= xkb->server;
418     if (which&XkbExplicitComponentsMask) {
419         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
420             (!XkbIsLegalKeycode(xkb->max_key_code))||
421             (xkb->max_key_code<xkb->min_key_code))
422             return BadMatch;
423         if (map->explicit==NULL) {
424             i= xkb->max_key_code+1;
425             map->explicit= _XkbTypedCalloc(i,unsigned char);
426             if (map->explicit==NULL)
427                 return BadAlloc;
428         }
429     }
430     if (which&XkbKeyActionsMask) {
431         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
432             (!XkbIsLegalKeycode(xkb->max_key_code))||
433             (xkb->max_key_code<xkb->min_key_code))
434             return BadMatch;
435         if (nNewActions<1)
436             nNewActions= 1;
437         if (map->acts==NULL) {
438             map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction);
439             if (map->acts==NULL)
440                 return BadAlloc;
441             map->num_acts= 1;
442             map->size_acts= nNewActions+1;
443         }
444         else if ((map->size_acts-map->num_acts)<nNewActions) {
445             unsigned need;
446             XkbAction *prev_acts = map->acts;
447             need= map->num_acts+nNewActions;
448             map->acts= _XkbTypedRealloc(map->acts,need,XkbAction);
449             if (map->acts==NULL) {
450                 _XkbFree(prev_acts);
451                 map->num_acts= map->size_acts= 0;
452                 return BadAlloc;
453             }
454             map->size_acts= need;
455             bzero(&map->acts[map->num_acts],
456                     ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
457         }
458         if (map->key_acts==NULL) {
459             i= xkb->max_key_code+1;
460             map->key_acts= _XkbTypedCalloc(i,unsigned short);
461             if (map->key_acts==NULL)
462                 return BadAlloc;
463         }
464     }
465     if (which&XkbKeyBehaviorsMask) {
466         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
467             (!XkbIsLegalKeycode(xkb->max_key_code))||
468             (xkb->max_key_code<xkb->min_key_code))
469             return BadMatch;
470         if (map->behaviors==NULL) {
471             i= xkb->max_key_code+1;
472             map->behaviors= _XkbTypedCalloc(i,XkbBehavior);
473             if (map->behaviors==NULL)
474                 return BadAlloc;
475         }
476     }
477     if (which&XkbVirtualModMapMask) {
478         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
479             (!XkbIsLegalKeycode(xkb->max_key_code))||
480             (xkb->max_key_code<xkb->min_key_code))
481             return BadMatch;
482         if (map->vmodmap==NULL) {
483             i= xkb->max_key_code+1;
484             map->vmodmap= _XkbTypedCalloc(i,unsigned short);
485             if (map->vmodmap==NULL)
486                 return BadAlloc;
487         }
488     }
489     return Success;
490 }
491
492 void
493 XkbcFreeClientMap(XkbcDescPtr xkb,unsigned what,Bool freeMap)
494 {
495 XkbClientMapPtr map;
496
497     if ((xkb==NULL)||(xkb->map==NULL))
498         return;
499     if (freeMap)
500         what= XkbAllClientInfoMask;
501     map= xkb->map;
502     if (what&XkbKeyTypesMask) {
503         if (map->types!=NULL) {
504             if (map->num_types>0) {
505                 register int    i;
506                 XkbKeyTypePtr   type;
507                 for (i=0,type=map->types;i<map->num_types;i++,type++) {
508                     if (type->map!=NULL) {
509                         _XkbFree(type->map);
510                         type->map= NULL;
511                     }
512                     if (type->preserve!=NULL) {
513                         _XkbFree(type->preserve);
514                         type->preserve= NULL;
515                     }
516                     type->map_count= 0;
517                     if (type->level_names!=NULL) {
518                         _XkbFree(type->level_names);
519                         type->level_names= NULL;
520                     }
521                 }
522             }
523             _XkbFree(map->types);
524             map->num_types= map->size_types= 0;
525             map->types= NULL;
526         }
527     }
528     if (what&XkbKeySymsMask) {
529         if (map->key_sym_map!=NULL) {
530             _XkbFree(map->key_sym_map);
531             map->key_sym_map= NULL;
532         }
533         if (map->syms!=NULL) {
534             _XkbFree(map->syms);
535             map->size_syms= map->num_syms= 0;
536             map->syms= NULL;
537         }
538     }
539     if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
540         _XkbFree(map->modmap);
541         map->modmap= NULL;
542     }
543     if (freeMap) {
544         _XkbFree(xkb->map);
545         xkb->map= NULL;
546     }
547     return;
548 }
549
550 void
551 XkbcFreeServerMap(XkbcDescPtr xkb,unsigned what,Bool freeMap)
552 {
553 XkbServerMapPtr map;
554
555     if ((xkb==NULL)||(xkb->server==NULL))
556         return;
557     if (freeMap)
558         what= XkbAllServerInfoMask;
559     map= xkb->server;
560     if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
561         _XkbFree(map->explicit);
562         map->explicit= NULL;
563     }
564     if (what&XkbKeyActionsMask) {
565         if (map->key_acts!=NULL) {
566             _XkbFree(map->key_acts);
567             map->key_acts= NULL;
568         }
569         if (map->acts!=NULL) {
570             _XkbFree(map->acts);
571             map->num_acts= map->size_acts= 0;
572             map->acts= NULL;
573         }
574     }
575     if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
576         _XkbFree(map->behaviors);
577         map->behaviors= NULL;
578     }
579     if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
580         _XkbFree(map->vmodmap);
581         map->vmodmap= NULL;
582     }
583
584     if (freeMap) {
585         _XkbFree(xkb->server);
586         xkb->server= NULL;
587     }
588     return;
589 }