XKBAlloc.c revision e9fcaa8a
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#elif defined(HAVE_CONFIG_H)
30#include <config.h>
31#endif
32
33#ifndef XKB_IN_SERVER
34
35#include <stdio.h>
36#include "Xlibint.h"
37#include "XKBlibint.h"
38#include <X11/extensions/XKBgeom.h>
39#include <X11/extensions/XKBproto.h>
40#include "XKBlibint.h"
41
42#else
43
44#include <stdio.h>
45#include <X11/X.h>
46#include <X11/Xproto.h>
47#include "misc.h"
48#include "inputstr.h"
49#include <X11/extensions/XKBsrv.h>
50#include <X11/extensions/XKBgeom.h>
51
52#endif /* XKB_IN_SERVER */
53
54/***===================================================================***/
55
56/*ARGSUSED*/
57Status
58XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI)
59{
60XkbCompatMapPtr	compat;
61XkbSymInterpretRec *prev_interpret;
62
63    if (!xkb)
64	return BadMatch;
65    if (xkb->compat) {
66	if (xkb->compat->size_si>=nSI)
67	    return Success;
68	compat= xkb->compat;
69	compat->size_si= nSI;
70	if (compat->sym_interpret==NULL)
71	    compat->num_si= 0;
72	prev_interpret = compat->sym_interpret;
73	compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
74						     nSI,XkbSymInterpretRec);
75	if (compat->sym_interpret==NULL) {
76	    _XkbFree(prev_interpret);
77	    compat->size_si= compat->num_si= 0;
78	    return BadAlloc;
79	}
80	if (compat->num_si!=0) {
81	    _XkbClearElems(compat->sym_interpret,compat->num_si,
82					compat->size_si-1,XkbSymInterpretRec);
83	}
84	return Success;
85    }
86    compat= _XkbTypedCalloc(1,XkbCompatMapRec);
87    if (compat==NULL)
88	return BadAlloc;
89    if (nSI>0) {
90	compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec);
91	if (!compat->sym_interpret) {
92	    _XkbFree(compat);
93	    return BadAlloc;
94	}
95    }
96    compat->size_si= nSI;
97    compat->num_si= 0;
98    bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
99    xkb->compat= compat;
100    return Success;
101}
102
103
104void
105XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap)
106{
107register XkbCompatMapPtr compat;
108
109    if ((xkb==NULL)||(xkb->compat==NULL))
110	return;
111    compat= xkb->compat;
112    if (freeMap)
113	which= XkbAllCompatMask;
114    if (which&XkbGroupCompatMask)
115	bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
116    if (which&XkbSymInterpMask) {
117	if ((compat->sym_interpret)&&(compat->size_si>0))
118	    _XkbFree(compat->sym_interpret);
119	compat->size_si= compat->num_si= 0;
120	compat->sym_interpret= NULL;
121    }
122    if (freeMap) {
123	_XkbFree(compat);
124	xkb->compat= NULL;
125    }
126    return;
127}
128
129/***===================================================================***/
130
131Status
132XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases)
133{
134XkbNamesPtr	names;
135
136    if (xkb==NULL)
137	return BadMatch;
138    if (xkb->names==NULL) {
139	xkb->names = _XkbTypedCalloc(1,XkbNamesRec);
140	if (xkb->names==NULL)
141	    return BadAlloc;
142    }
143    names= xkb->names;
144    if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){
145	register int	i;
146	XkbKeyTypePtr	type;
147
148	type= xkb->map->types;
149	for (i=0;i<xkb->map->num_types;i++,type++) {
150	    if (type->level_names==NULL) {
151		type->level_names= _XkbTypedCalloc(type->num_levels,Atom);
152		if (type->level_names==NULL)
153		    return BadAlloc;
154	    }
155	}
156    }
157    if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) {
158	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
159	    (!XkbIsLegalKeycode(xkb->max_key_code))||
160	    (xkb->max_key_code<xkb->min_key_code))
161	    return BadValue;
162	names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec);
163	if (names->keys==NULL)
164	    return BadAlloc;
165    }
166    if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) {
167	if (names->key_aliases==NULL) {
168	    names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec);
169	}
170	else if (nTotalAliases>names->num_key_aliases) {
171	    XkbKeyAliasRec *prev_aliases = names->key_aliases;
172
173	    names->key_aliases= _XkbTypedRealloc(names->key_aliases,
174						nTotalAliases,XkbKeyAliasRec);
175	    if (names->key_aliases!=NULL) {
176		_XkbClearElems(names->key_aliases,names->num_key_aliases,
177						nTotalAliases-1,XkbKeyAliasRec);
178	    } else {
179		_XkbFree(prev_aliases);
180	    }
181	}
182	if (names->key_aliases==NULL) {
183	    names->num_key_aliases= 0;
184	    return BadAlloc;
185	}
186	names->num_key_aliases= nTotalAliases;
187    }
188    if ((which&XkbRGNamesMask)&&(nTotalRG>0)) {
189	if (names->radio_groups==NULL) {
190	    names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom);
191	}
192	else if (nTotalRG>names->num_rg) {
193	    Atom *prev_radio_groups = names->radio_groups;
194
195	    names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG,
196									Atom);
197	    if (names->radio_groups!=NULL) {
198		_XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1,
199									Atom);
200	    } else {
201		_XkbFree(prev_radio_groups);
202	    }
203	}
204	if (names->radio_groups==NULL)
205	    return BadAlloc;
206	names->num_rg= nTotalRG;
207    }
208    return Success;
209}
210
211void
212XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap)
213{
214XkbNamesPtr	names;
215
216    if ((xkb==NULL)||(xkb->names==NULL))
217	return;
218    names= xkb->names;
219    if (freeMap)
220	which= XkbAllNamesMask;
221    if (which&XkbKTLevelNamesMask) {
222	XkbClientMapPtr	map= xkb->map;
223	if ((map!=NULL)&&(map->types!=NULL)) {
224	    register int 		i;
225	    register XkbKeyTypePtr	type;
226	    type= map->types;
227	    for (i=0;i<map->num_types;i++,type++) {
228		if (type->level_names!=NULL) {
229		    _XkbFree(type->level_names);
230		    type->level_names= NULL;
231		}
232	    }
233	}
234    }
235    if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
236	_XkbFree(names->keys);
237	names->keys= NULL;
238	names->num_keys= 0;
239    }
240    if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){
241	_XkbFree(names->key_aliases);
242	names->key_aliases=NULL;
243	names->num_key_aliases=0;
244    }
245    if ((which&XkbRGNamesMask)&&(names->radio_groups)) {
246	_XkbFree(names->radio_groups);
247	names->radio_groups= NULL;
248	names->num_rg= 0;
249    }
250    if (freeMap) {
251	_XkbFree(names);
252	xkb->names= NULL;
253    }
254    return;
255}
256
257/***===================================================================***/
258
259/*ARGSUSED*/
260Status
261XkbAllocControls(XkbDescPtr xkb,unsigned which)
262{
263    if (xkb==NULL)
264	return BadMatch;
265
266    if (xkb->ctrls==NULL) {
267	xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec);
268	if (!xkb->ctrls)
269	    return BadAlloc;
270    }
271    return Success;
272}
273
274/*ARGSUSED*/
275void
276XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap)
277{
278    if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) {
279	_XkbFree(xkb->ctrls);
280	xkb->ctrls= NULL;
281    }
282    return;
283}
284
285/***===================================================================***/
286
287Status
288XkbAllocIndicatorMaps(XkbDescPtr xkb)
289{
290    if (xkb==NULL)
291	return BadMatch;
292    if (xkb->indicators==NULL) {
293	xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec);
294	if (!xkb->indicators)
295	    return BadAlloc;
296    }
297    return Success;
298}
299
300void
301XkbFreeIndicatorMaps(XkbDescPtr xkb)
302{
303    if ((xkb!=NULL)&&(xkb->indicators!=NULL)) {
304	_XkbFree(xkb->indicators);
305	xkb->indicators= NULL;
306    }
307    return;
308}
309
310/***====================================================================***/
311
312XkbDescRec	*
313XkbAllocKeyboard(void)
314{
315XkbDescRec *xkb;
316
317    xkb = _XkbTypedCalloc(1,XkbDescRec);
318    if (xkb)
319	xkb->device_spec= XkbUseCoreKbd;
320    return xkb;
321}
322
323void
324XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll)
325{
326    if (xkb==NULL)
327	return;
328    if (freeAll)
329	which= XkbAllComponentsMask;
330    if (which&XkbClientMapMask)
331	XkbFreeClientMap(xkb,XkbAllClientInfoMask,True);
332    if (which&XkbServerMapMask)
333	XkbFreeServerMap(xkb,XkbAllServerInfoMask,True);
334    if (which&XkbCompatMapMask)
335	XkbFreeCompatMap(xkb,XkbAllCompatMask,True);
336    if (which&XkbIndicatorMapMask)
337	XkbFreeIndicatorMaps(xkb);
338    if (which&XkbNamesMask)
339	XkbFreeNames(xkb,XkbAllNamesMask,True);
340    if ((which&XkbGeometryMask) && (xkb->geom!=NULL))
341	XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True);
342    if (which&XkbControlsMask)
343	XkbFreeControls(xkb,XkbAllControlsMask,True);
344    if (freeAll)
345	_XkbFree(xkb);
346    return;
347}
348
349/***====================================================================***/
350
351XkbDeviceLedInfoPtr
352XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi,unsigned ledClass,unsigned ledId)
353{
354XkbDeviceLedInfoPtr	devli;
355register int		i;
356
357    if ((!devi)||(!XkbSingleXIClass(ledClass))||(!XkbSingleXIId(ledId)))
358	return NULL;
359    for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
360	if ((devli->led_class==ledClass)&&(devli->led_id==ledId))
361	    return devli;
362    }
363    if (devi->num_leds>=devi->sz_leds) {
364	XkbDeviceLedInfoRec *prev_leds = devi->leds;
365
366	if (devi->sz_leds>0)	devi->sz_leds*= 2;
367	else			devi->sz_leds= 1;
368	devi->leds= _XkbTypedRealloc(devi->leds,devi->sz_leds,
369							XkbDeviceLedInfoRec);
370	if (!devi->leds) {
371	    _XkbFree(prev_leds);
372	    devi->sz_leds= devi->num_leds= 0;
373	    return NULL;
374	}
375	i= devi->num_leds;
376	for (devli=&devi->leds[i];i<devi->sz_leds;i++,devli++) {
377	    bzero(devli,sizeof(XkbDeviceLedInfoRec));
378	    devli->led_class= XkbXINone;
379	    devli->led_id= XkbXINone;
380	}
381    }
382    devli= &devi->leds[devi->num_leds++];
383    bzero(devli,sizeof(XkbDeviceLedInfoRec));
384    devli->led_class= ledClass;
385    devli->led_id= ledId;
386    return devli;
387}
388
389Status
390XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi,unsigned newTotal)
391{
392    XkbAction *prev_btn_acts;
393
394    if ((!devi)||(newTotal>255))
395	return BadValue;
396    if ((devi->btn_acts!=NULL)&&(newTotal==devi->num_btns))
397	return Success;
398    if (newTotal==0) {
399	if (devi->btn_acts!=NULL) {
400	    _XkbFree(devi->btn_acts);
401	    devi->btn_acts= NULL;
402	}
403	devi->num_btns= 0;
404	return Success;
405    }
406    prev_btn_acts = devi->btn_acts;
407    devi->btn_acts= _XkbTypedRealloc(devi->btn_acts,newTotal,XkbAction);
408    if (devi->btn_acts==NULL) {
409	_XkbFree(prev_btn_acts);
410	devi->num_btns= 0;
411	return BadAlloc;
412    }
413    if (newTotal>devi->num_btns) {
414	XkbAction *act;
415	act= &devi->btn_acts[devi->num_btns];
416	bzero((char *)act,(newTotal-devi->num_btns)*sizeof(XkbAction));
417    }
418    devi->num_btns= newTotal;
419    return Success;
420}
421
422/*ARGSUSED*/
423XkbDeviceInfoPtr
424XkbAllocDeviceInfo(unsigned deviceSpec,unsigned nButtons,unsigned szLeds)
425{
426XkbDeviceInfoPtr	devi;
427
428    devi= _XkbTypedCalloc(1,XkbDeviceInfoRec);
429    if (devi!=NULL) {
430	devi->device_spec= deviceSpec;
431	devi->has_own_state= False;
432	devi->num_btns= 0;
433	devi->btn_acts= NULL;
434	if (nButtons>0) {
435	    devi->num_btns= nButtons;
436	    devi->btn_acts= _XkbTypedCalloc(nButtons,XkbAction);
437	    if (!devi->btn_acts) {
438		_XkbFree(devi);
439		return NULL;
440	    }
441	}
442	devi->dflt_kbd_fb= XkbXINone;
443	devi->dflt_led_fb= XkbXINone;
444	devi->num_leds= 0;
445	devi->sz_leds= 0;
446	devi->leds= NULL;
447	if (szLeds>0) {
448	    devi->sz_leds= szLeds;
449	    devi->leds= _XkbTypedCalloc(szLeds,XkbDeviceLedInfoRec);
450	    if (!devi->leds) {
451		if (devi->btn_acts)
452		    _XkbFree(devi->btn_acts);
453		_XkbFree(devi);
454		return NULL;
455	    }
456	}
457    }
458    return devi;
459}
460
461
462void
463XkbFreeDeviceInfo(XkbDeviceInfoPtr devi,unsigned which,Bool freeDevI)
464{
465    if (devi) {
466	if (freeDevI) {
467	    which= XkbXI_AllDeviceFeaturesMask;
468	    if (devi->name) {
469		_XkbFree(devi->name);
470		devi->name= NULL;
471	    }
472	}
473	if ((which&XkbXI_ButtonActionsMask)&&(devi->btn_acts)) {
474	    _XkbFree(devi->btn_acts);
475	    devi->num_btns= 0;
476	    devi->btn_acts= NULL;
477	}
478	if ((which&XkbXI_IndicatorsMask)&&(devi->leds)) {
479	    register int i;
480	    if ((which&XkbXI_IndicatorsMask)==XkbXI_IndicatorsMask) {
481		_XkbFree(devi->leds);
482		devi->sz_leds= devi->num_leds= 0;
483		devi->leds= NULL;
484	    }
485	    else {
486		XkbDeviceLedInfoPtr	devli;
487		for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
488		    if (which&XkbXI_IndicatorMapsMask)
489			 bzero((char *)&devli->maps[0],sizeof(devli->maps));
490		    else bzero((char *)&devli->names[0],sizeof(devli->names));
491		}
492	    }
493	}
494	if (freeDevI)
495	    _XkbFree(devi);
496    }
497    return;
498}
499