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