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