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#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include "misc.h"
35#include "inputstr.h"
36#include <xkbsrv.h>
37#include "xkbgeom.h"
38#include <os.h>
39#include <string.h>
40
41/***===================================================================***/
42
43/*ARGSUSED*/
44Status
45XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI)
46{
47XkbCompatMapPtr	compat;
48XkbSymInterpretRec *prev_interpret;
49
50    if (!xkb)
51	return BadMatch;
52    if (xkb->compat) {
53	if (xkb->compat->size_si>=nSI)
54	    return Success;
55	compat= xkb->compat;
56	compat->size_si= nSI;
57	if (compat->sym_interpret==NULL)
58	    compat->num_si= 0;
59	prev_interpret = compat->sym_interpret;
60	compat->sym_interpret= realloc(compat->sym_interpret,
61					nSI * sizeof(XkbSymInterpretRec));
62	if (compat->sym_interpret==NULL) {
63	    free(prev_interpret);
64	    compat->size_si= compat->num_si= 0;
65	    return BadAlloc;
66	}
67	if (compat->num_si!=0) {
68	    memset(&compat->sym_interpret[compat->num_si], 0,
69		   (compat->size_si - compat->num_si) * sizeof(XkbSymInterpretRec));
70	}
71	return Success;
72    }
73   compat= calloc(1, sizeof(XkbCompatMapRec));
74    if (compat==NULL)
75	return BadAlloc;
76    if (nSI>0) {
77	compat->sym_interpret= calloc(nSI, sizeof(XkbSymInterpretRec));
78	if (!compat->sym_interpret) {
79	    free(compat);
80	    return BadAlloc;
81	}
82    }
83    compat->size_si= nSI;
84    compat->num_si= 0;
85    memset((char *)&compat->groups[0], 0, XkbNumKbdGroups*sizeof(XkbModsRec));
86    xkb->compat= compat;
87    return Success;
88}
89
90
91void
92XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap)
93{
94register XkbCompatMapPtr compat;
95
96    if ((xkb==NULL)||(xkb->compat==NULL))
97	return;
98    compat= xkb->compat;
99    if (freeMap)
100	which= XkbAllCompatMask;
101    if (which&XkbGroupCompatMask)
102	memset((char *)&compat->groups[0], 0, XkbNumKbdGroups*sizeof(XkbModsRec));
103    if (which&XkbSymInterpMask) {
104	if ((compat->sym_interpret)&&(compat->size_si>0))
105	    free(compat->sym_interpret);
106	compat->size_si= compat->num_si= 0;
107	compat->sym_interpret= NULL;
108    }
109    if (freeMap) {
110	free(compat);
111	xkb->compat= NULL;
112    }
113    return;
114}
115
116/***===================================================================***/
117
118Status
119XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases)
120{
121XkbNamesPtr	names;
122
123    if (xkb==NULL)
124	return BadMatch;
125    if (xkb->names==NULL) {
126	xkb->names = calloc(1, sizeof(XkbNamesRec));
127	if (xkb->names==NULL)
128	    return BadAlloc;
129    }
130    names= xkb->names;
131    if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){
132	register int	i;
133	XkbKeyTypePtr	type;
134
135	type= xkb->map->types;
136	for (i=0;i<xkb->map->num_types;i++,type++) {
137	    if (type->level_names==NULL) {
138		type->level_names= calloc(type->num_levels, sizeof(Atom));
139		if (type->level_names==NULL)
140		    return BadAlloc;
141	    }
142	}
143    }
144    if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) {
145	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
146	    (!XkbIsLegalKeycode(xkb->max_key_code))||
147	    (xkb->max_key_code<xkb->min_key_code))
148	    return BadValue;
149	names->keys= calloc((xkb->max_key_code+1), sizeof(XkbKeyNameRec));
150	if (names->keys==NULL)
151	    return BadAlloc;
152    }
153    if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) {
154	if (names->key_aliases==NULL) {
155	    names->key_aliases= calloc(nTotalAliases, sizeof(XkbKeyAliasRec));
156	}
157	else if (nTotalAliases>names->num_key_aliases) {
158	    XkbKeyAliasRec *prev_aliases = names->key_aliases;
159
160	    names->key_aliases= realloc(names->key_aliases,
161					 nTotalAliases * sizeof(XkbKeyAliasRec));
162	    if (names->key_aliases!=NULL) {
163		memset(&names->key_aliases[names->num_key_aliases], 0,
164			(nTotalAliases - names->num_key_aliases) * sizeof(XkbKeyAliasRec));
165	    } else {
166		free(prev_aliases);
167	    }
168	}
169	if (names->key_aliases==NULL) {
170	    names->num_key_aliases= 0;
171	    return BadAlloc;
172	}
173	names->num_key_aliases= nTotalAliases;
174    }
175    if ((which&XkbRGNamesMask)&&(nTotalRG>0)) {
176	if (names->radio_groups==NULL) {
177	    names->radio_groups= calloc(nTotalRG, sizeof(Atom));
178	}
179	else if (nTotalRG>names->num_rg) {
180	    Atom *prev_radio_groups = names->radio_groups;
181
182	    names->radio_groups= realloc(names->radio_groups,
183					  nTotalRG * sizeof(Atom));
184	    if (names->radio_groups!=NULL) {
185		memset(&names->radio_groups[names->num_rg], 0,
186			(nTotalRG - names->num_rg) * sizeof(Atom));
187	    } else {
188		free(prev_radio_groups);
189	    }
190	}
191	if (names->radio_groups==NULL)
192	    return BadAlloc;
193	names->num_rg= nTotalRG;
194    }
195    return Success;
196}
197
198void
199XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap)
200{
201XkbNamesPtr	names;
202
203    if ((xkb==NULL)||(xkb->names==NULL))
204	return;
205    names= xkb->names;
206    if (freeMap)
207	which= XkbAllNamesMask;
208    if (which&XkbKTLevelNamesMask) {
209	XkbClientMapPtr	map= xkb->map;
210	if ((map!=NULL)&&(map->types!=NULL)) {
211	    register int 		i;
212	    register XkbKeyTypePtr	type;
213	    type= map->types;
214	    for (i=0;i<map->num_types;i++,type++) {
215		free(type->level_names);
216		type->level_names = NULL;
217	    }
218	}
219    }
220    if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
221	free(names->keys);
222	names->keys= NULL;
223	names->num_keys= 0;
224    }
225    if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){
226	free(names->key_aliases);
227	names->key_aliases=NULL;
228	names->num_key_aliases=0;
229    }
230    if ((which&XkbRGNamesMask)&&(names->radio_groups)) {
231	free(names->radio_groups);
232	names->radio_groups= NULL;
233	names->num_rg= 0;
234    }
235    if (freeMap) {
236	free(names);
237	xkb->names= NULL;
238    }
239    return;
240}
241
242/***===================================================================***/
243
244/*ARGSUSED*/
245Status
246XkbAllocControls(XkbDescPtr xkb,unsigned which)
247{
248    if (xkb==NULL)
249	return BadMatch;
250
251    if (xkb->ctrls==NULL) {
252	xkb->ctrls= calloc(1, sizeof(XkbControlsRec));
253	if (!xkb->ctrls)
254	    return BadAlloc;
255    }
256    return Success;
257}
258
259/*ARGSUSED*/
260static void
261XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap)
262{
263    if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) {
264	free(xkb->ctrls);
265	xkb->ctrls= NULL;
266    }
267    return;
268}
269
270/***===================================================================***/
271
272Status
273XkbAllocIndicatorMaps(XkbDescPtr xkb)
274{
275    if (xkb==NULL)
276	return BadMatch;
277    if (xkb->indicators==NULL) {
278	xkb->indicators= calloc(1, sizeof(XkbIndicatorRec));
279	if (!xkb->indicators)
280	    return BadAlloc;
281    }
282    return Success;
283}
284
285static void
286XkbFreeIndicatorMaps(XkbDescPtr xkb)
287{
288    if ((xkb!=NULL)&&(xkb->indicators!=NULL)) {
289	free(xkb->indicators);
290	xkb->indicators= NULL;
291    }
292    return;
293}
294
295/***====================================================================***/
296
297XkbDescRec	*
298XkbAllocKeyboard(void)
299{
300XkbDescRec *xkb;
301
302    xkb = calloc(1, sizeof(XkbDescRec));
303    if (xkb)
304	xkb->device_spec= XkbUseCoreKbd;
305    return xkb;
306}
307
308void
309XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll)
310{
311    if (xkb==NULL)
312	return;
313    if (freeAll)
314	which= XkbAllComponentsMask;
315    if (which&XkbClientMapMask)
316	XkbFreeClientMap(xkb,XkbAllClientInfoMask,TRUE);
317    if (which&XkbServerMapMask)
318	XkbFreeServerMap(xkb,XkbAllServerInfoMask,TRUE);
319    if (which&XkbCompatMapMask)
320	XkbFreeCompatMap(xkb,XkbAllCompatMask,TRUE);
321    if (which&XkbIndicatorMapMask)
322	XkbFreeIndicatorMaps(xkb);
323    if (which&XkbNamesMask)
324	XkbFreeNames(xkb,XkbAllNamesMask,TRUE);
325    if ((which&XkbGeometryMask) && (xkb->geom!=NULL)) {
326	XkbFreeGeometry(xkb->geom,XkbGeomAllMask,TRUE);
327        /* PERHAPS BONGHITS etc */
328        xkb->geom = NULL;
329    }
330    if (which&XkbControlsMask)
331	XkbFreeControls(xkb,XkbAllControlsMask,TRUE);
332    if (freeAll)
333	free(xkb);
334    return;
335}
336
337
338/***====================================================================***/
339
340void
341XkbFreeComponentNames(XkbComponentNamesPtr names, Bool freeNames)
342{
343    if (names)
344    {
345        free(names->keycodes);
346        free(names->types);
347        free(names->compat);
348        free(names->symbols);
349        free(names->geometry);
350        memset(names, 0, sizeof(XkbComponentNamesRec));
351    }
352    if (freeNames)
353        free(names);
354}
355