XKBAlloc.c revision eb411b4b
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
34#include <stdio.h>
35#include "Xlibint.h"
36#include "XKBlibint.h"
37#include <X11/extensions/XKBgeom.h>
38#include <X11/extensions/XKBproto.h>
39#include "XKBlibint.h"
40
41
42/***===================================================================***/
43
44/*ARGSUSED*/
45Status
46XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI)
47{
48XkbCompatMapPtr	compat;
49XkbSymInterpretRec *prev_interpret;
50
51    if (!xkb)
52	return BadMatch;
53    if (xkb->compat) {
54	if (xkb->compat->size_si>=nSI)
55	    return Success;
56	compat= xkb->compat;
57	compat->size_si= nSI;
58	if (compat->sym_interpret==NULL)
59	    compat->num_si= 0;
60	prev_interpret = compat->sym_interpret;
61	compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
62						     nSI,XkbSymInterpretRec);
63	if (compat->sym_interpret==NULL) {
64	    _XkbFree(prev_interpret);
65	    compat->size_si= compat->num_si= 0;
66	    return BadAlloc;
67	}
68	if (compat->num_si!=0) {
69	    _XkbClearElems(compat->sym_interpret,compat->num_si,
70					compat->size_si-1,XkbSymInterpretRec);
71	}
72	return Success;
73    }
74    compat= _XkbTypedCalloc(1,XkbCompatMapRec);
75    if (compat==NULL)
76	return BadAlloc;
77    if (nSI>0) {
78	compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec);
79	if (!compat->sym_interpret) {
80	    _XkbFree(compat);
81	    return BadAlloc;
82	}
83    }
84    compat->size_si= nSI;
85    compat->num_si= 0;
86    bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
87    xkb->compat= compat;
88    return Success;
89}
90
91
92void
93XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap)
94{
95register XkbCompatMapPtr compat;
96
97    if ((xkb==NULL)||(xkb->compat==NULL))
98	return;
99    compat= xkb->compat;
100    if (freeMap)
101	which= XkbAllCompatMask;
102    if (which&XkbGroupCompatMask)
103	bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
104    if (which&XkbSymInterpMask) {
105	if ((compat->sym_interpret)&&(compat->size_si>0))
106	    _XkbFree(compat->sym_interpret);
107	compat->size_si= compat->num_si= 0;
108	compat->sym_interpret= NULL;
109    }
110    if (freeMap) {
111	_XkbFree(compat);
112	xkb->compat= NULL;
113    }
114    return;
115}
116
117/***===================================================================***/
118
119Status
120XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases)
121{
122XkbNamesPtr	names;
123
124    if (xkb==NULL)
125	return BadMatch;
126    if (xkb->names==NULL) {
127	xkb->names = _XkbTypedCalloc(1,XkbNamesRec);
128	if (xkb->names==NULL)
129	    return BadAlloc;
130    }
131    names= xkb->names;
132    if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){
133	register int	i;
134	XkbKeyTypePtr	type;
135
136	type= xkb->map->types;
137	for (i=0;i<xkb->map->num_types;i++,type++) {
138	    if (type->level_names==NULL) {
139		type->level_names= _XkbTypedCalloc(type->num_levels,Atom);
140		if (type->level_names==NULL)
141		    return BadAlloc;
142	    }
143	}
144    }
145    if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) {
146	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
147	    (!XkbIsLegalKeycode(xkb->max_key_code))||
148	    (xkb->max_key_code<xkb->min_key_code))
149	    return BadValue;
150	names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec);
151	if (names->keys==NULL)
152	    return BadAlloc;
153    }
154    if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) {
155	if (names->key_aliases==NULL) {
156	    names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec);
157	}
158	else if (nTotalAliases>names->num_key_aliases) {
159	    XkbKeyAliasRec *prev_aliases = names->key_aliases;
160
161	    names->key_aliases= _XkbTypedRealloc(names->key_aliases,
162						nTotalAliases,XkbKeyAliasRec);
163	    if (names->key_aliases!=NULL) {
164		_XkbClearElems(names->key_aliases,names->num_key_aliases,
165						nTotalAliases-1,XkbKeyAliasRec);
166	    } else {
167		_XkbFree(prev_aliases);
168	    }
169	}
170	if (names->key_aliases==NULL) {
171	    names->num_key_aliases= 0;
172	    return BadAlloc;
173	}
174	names->num_key_aliases= nTotalAliases;
175    }
176    if ((which&XkbRGNamesMask)&&(nTotalRG>0)) {
177	if (names->radio_groups==NULL) {
178	    names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom);
179	}
180	else if (nTotalRG>names->num_rg) {
181	    Atom *prev_radio_groups = names->radio_groups;
182
183	    names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG,
184									Atom);
185	    if (names->radio_groups!=NULL) {
186		_XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1,
187									Atom);
188	    } else {
189		_XkbFree(prev_radio_groups);
190	    }
191	}
192	if (names->radio_groups==NULL)
193	    return BadAlloc;
194	names->num_rg= nTotalRG;
195    }
196    return Success;
197}
198
199void
200XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap)
201{
202XkbNamesPtr	names;
203
204    if ((xkb==NULL)||(xkb->names==NULL))
205	return;
206    names= xkb->names;
207    if (freeMap)
208	which= XkbAllNamesMask;
209    if (which&XkbKTLevelNamesMask) {
210	XkbClientMapPtr	map= xkb->map;
211	if ((map!=NULL)&&(map->types!=NULL)) {
212	    register int 		i;
213	    register XkbKeyTypePtr	type;
214	    type= map->types;
215	    for (i=0;i<map->num_types;i++,type++) {
216		if (type->level_names!=NULL) {
217		    _XkbFree(type->level_names);
218		    type->level_names= NULL;
219		}
220	    }
221	}
222    }
223    if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
224	_XkbFree(names->keys);
225	names->keys= NULL;
226	names->num_keys= 0;
227    }
228    if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){
229	_XkbFree(names->key_aliases);
230	names->key_aliases=NULL;
231	names->num_key_aliases=0;
232    }
233    if ((which&XkbRGNamesMask)&&(names->radio_groups)) {
234	_XkbFree(names->radio_groups);
235	names->radio_groups= NULL;
236	names->num_rg= 0;
237    }
238    if (freeMap) {
239	_XkbFree(names);
240	xkb->names= NULL;
241    }
242    return;
243}
244
245/***===================================================================***/
246
247/*ARGSUSED*/
248Status
249XkbAllocControls(XkbDescPtr xkb,unsigned which)
250{
251    if (xkb==NULL)
252	return BadMatch;
253
254    if (xkb->ctrls==NULL) {
255	xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec);
256	if (!xkb->ctrls)
257	    return BadAlloc;
258    }
259    return Success;
260}
261
262/*ARGSUSED*/
263void
264XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap)
265{
266    if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) {
267	_XkbFree(xkb->ctrls);
268	xkb->ctrls= NULL;
269    }
270    return;
271}
272
273/***===================================================================***/
274
275Status
276XkbAllocIndicatorMaps(XkbDescPtr xkb)
277{
278    if (xkb==NULL)
279	return BadMatch;
280    if (xkb->indicators==NULL) {
281	xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec);
282	if (!xkb->indicators)
283	    return BadAlloc;
284    }
285    return Success;
286}
287
288void
289XkbFreeIndicatorMaps(XkbDescPtr xkb)
290{
291    if ((xkb!=NULL)&&(xkb->indicators!=NULL)) {
292	_XkbFree(xkb->indicators);
293	xkb->indicators= NULL;
294    }
295    return;
296}
297
298/***====================================================================***/
299
300XkbDescRec	*
301XkbAllocKeyboard(void)
302{
303XkbDescRec *xkb;
304
305    xkb = _XkbTypedCalloc(1,XkbDescRec);
306    if (xkb)
307	xkb->device_spec= XkbUseCoreKbd;
308    return xkb;
309}
310
311void
312XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll)
313{
314    if (xkb==NULL)
315	return;
316    if (freeAll)
317	which= XkbAllComponentsMask;
318    if (which&XkbClientMapMask)
319	XkbFreeClientMap(xkb,XkbAllClientInfoMask,True);
320    if (which&XkbServerMapMask)
321	XkbFreeServerMap(xkb,XkbAllServerInfoMask,True);
322    if (which&XkbCompatMapMask)
323	XkbFreeCompatMap(xkb,XkbAllCompatMask,True);
324    if (which&XkbIndicatorMapMask)
325	XkbFreeIndicatorMaps(xkb);
326    if (which&XkbNamesMask)
327	XkbFreeNames(xkb,XkbAllNamesMask,True);
328    if ((which&XkbGeometryMask) && (xkb->geom!=NULL))
329	XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True);
330    if (which&XkbControlsMask)
331	XkbFreeControls(xkb,XkbAllControlsMask,True);
332    if (freeAll)
333	_XkbFree(xkb);
334    return;
335}
336
337/***====================================================================***/
338
339XkbDeviceLedInfoPtr
340XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi,unsigned ledClass,unsigned ledId)
341{
342XkbDeviceLedInfoPtr	devli;
343register int		i;
344
345    if ((!devi)||(!XkbSingleXIClass(ledClass))||(!XkbSingleXIId(ledId)))
346	return NULL;
347    for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
348	if ((devli->led_class==ledClass)&&(devli->led_id==ledId))
349	    return devli;
350    }
351    if (devi->num_leds>=devi->sz_leds) {
352	XkbDeviceLedInfoRec *prev_leds = devi->leds;
353
354	if (devi->sz_leds>0)	devi->sz_leds*= 2;
355	else			devi->sz_leds= 1;
356	devi->leds= _XkbTypedRealloc(devi->leds,devi->sz_leds,
357							XkbDeviceLedInfoRec);
358	if (!devi->leds) {
359	    _XkbFree(prev_leds);
360	    devi->sz_leds= devi->num_leds= 0;
361	    return NULL;
362	}
363	i= devi->num_leds;
364	for (devli=&devi->leds[i];i<devi->sz_leds;i++,devli++) {
365	    bzero(devli,sizeof(XkbDeviceLedInfoRec));
366	    devli->led_class= XkbXINone;
367	    devli->led_id= XkbXINone;
368	}
369    }
370    devli= &devi->leds[devi->num_leds++];
371    bzero(devli,sizeof(XkbDeviceLedInfoRec));
372    devli->led_class= ledClass;
373    devli->led_id= ledId;
374    return devli;
375}
376
377Status
378XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi,unsigned newTotal)
379{
380    XkbAction *prev_btn_acts;
381
382    if ((!devi)||(newTotal>255))
383	return BadValue;
384    if ((devi->btn_acts!=NULL)&&(newTotal==devi->num_btns))
385	return Success;
386    if (newTotal==0) {
387	if (devi->btn_acts!=NULL) {
388	    _XkbFree(devi->btn_acts);
389	    devi->btn_acts= NULL;
390	}
391	devi->num_btns= 0;
392	return Success;
393    }
394    prev_btn_acts = devi->btn_acts;
395    devi->btn_acts= _XkbTypedRealloc(devi->btn_acts,newTotal,XkbAction);
396    if (devi->btn_acts==NULL) {
397	_XkbFree(prev_btn_acts);
398	devi->num_btns= 0;
399	return BadAlloc;
400    }
401    if (newTotal>devi->num_btns) {
402	XkbAction *act;
403	act= &devi->btn_acts[devi->num_btns];
404	bzero((char *)act,(newTotal-devi->num_btns)*sizeof(XkbAction));
405    }
406    devi->num_btns= newTotal;
407    return Success;
408}
409
410/*ARGSUSED*/
411XkbDeviceInfoPtr
412XkbAllocDeviceInfo(unsigned deviceSpec,unsigned nButtons,unsigned szLeds)
413{
414XkbDeviceInfoPtr	devi;
415
416    devi= _XkbTypedCalloc(1,XkbDeviceInfoRec);
417    if (devi!=NULL) {
418	devi->device_spec= deviceSpec;
419	devi->has_own_state= False;
420	devi->num_btns= 0;
421	devi->btn_acts= NULL;
422	if (nButtons>0) {
423	    devi->num_btns= nButtons;
424	    devi->btn_acts= _XkbTypedCalloc(nButtons,XkbAction);
425	    if (!devi->btn_acts) {
426		_XkbFree(devi);
427		return NULL;
428	    }
429	}
430	devi->dflt_kbd_fb= XkbXINone;
431	devi->dflt_led_fb= XkbXINone;
432	devi->num_leds= 0;
433	devi->sz_leds= 0;
434	devi->leds= NULL;
435	if (szLeds>0) {
436	    devi->sz_leds= szLeds;
437	    devi->leds= _XkbTypedCalloc(szLeds,XkbDeviceLedInfoRec);
438	    if (!devi->leds) {
439		if (devi->btn_acts)
440		    _XkbFree(devi->btn_acts);
441		_XkbFree(devi);
442		return NULL;
443	    }
444	}
445    }
446    return devi;
447}
448
449
450void
451XkbFreeDeviceInfo(XkbDeviceInfoPtr devi,unsigned which,Bool freeDevI)
452{
453    if (devi) {
454	if (freeDevI) {
455	    which= XkbXI_AllDeviceFeaturesMask;
456	    if (devi->name) {
457		_XkbFree(devi->name);
458		devi->name= NULL;
459	    }
460	}
461	if ((which&XkbXI_ButtonActionsMask)&&(devi->btn_acts)) {
462	    _XkbFree(devi->btn_acts);
463	    devi->num_btns= 0;
464	    devi->btn_acts= NULL;
465	}
466	if ((which&XkbXI_IndicatorsMask)&&(devi->leds)) {
467	    register int i;
468	    if ((which&XkbXI_IndicatorsMask)==XkbXI_IndicatorsMask) {
469		_XkbFree(devi->leds);
470		devi->sz_leds= devi->num_leds= 0;
471		devi->leds= NULL;
472	    }
473	    else {
474		XkbDeviceLedInfoPtr	devli;
475		for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
476		    if (which&XkbXI_IndicatorMapsMask)
477			 bzero((char *)&devli->maps[0],sizeof(devli->maps));
478		    else bzero((char *)&devli->names[0],sizeof(devli->names));
479		}
480	    }
481	}
482	if (freeDevI)
483	    _XkbFree(devi);
484    }
485    return;
486}
487