1706f2543Smrg/************************************************************
2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3706f2543Smrg
4706f2543SmrgPermission to use, copy, modify, and distribute this
5706f2543Smrgsoftware and its documentation for any purpose and without
6706f2543Smrgfee is hereby granted, provided that the above copyright
7706f2543Smrgnotice appear in all copies and that both that copyright
8706f2543Smrgnotice and this permission notice appear in supporting
9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be
10706f2543Smrgused in advertising or publicity pertaining to distribution
11706f2543Smrgof the software without specific prior written permission.
12706f2543SmrgSilicon Graphics makes no representation about the suitability
13706f2543Smrgof this software for any purpose. It is provided "as is"
14706f2543Smrgwithout any express or implied warranty.
15706f2543Smrg
16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg
25706f2543Smrg********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg
32706f2543Smrg#include <stdio.h>
33706f2543Smrg#include <X11/X.h>
34706f2543Smrg#include <X11/Xproto.h>
35706f2543Smrg#include "misc.h"
36706f2543Smrg#include "inputstr.h"
37706f2543Smrg#include <xkbsrv.h>
38706f2543Smrg#include "xkbgeom.h"
39706f2543Smrg
40706f2543Smrg/***====================================================================***/
41706f2543Smrg
42706f2543Smrgstatic void
43706f2543Smrg_XkbFreeGeomLeafElems(	Bool			freeAll,
44706f2543Smrg			int			first,
45706f2543Smrg			int 			count,
46706f2543Smrg			unsigned short *	num_inout,
47706f2543Smrg			unsigned short *	sz_inout,
48706f2543Smrg			char **			elems,
49706f2543Smrg			unsigned int		elem_sz)
50706f2543Smrg{
51706f2543Smrg    if ((freeAll)||(*elems==NULL)) {
52706f2543Smrg	*num_inout= *sz_inout= 0;
53706f2543Smrg	free(*elems);
54706f2543Smrg	*elems = NULL;
55706f2543Smrg	return;
56706f2543Smrg    }
57706f2543Smrg
58706f2543Smrg    if ((first>=(*num_inout))||(first<0)||(count<1))
59706f2543Smrg	return;
60706f2543Smrg
61706f2543Smrg    if (first+count>=(*num_inout)) {
62706f2543Smrg	/* truncating the array is easy */
63706f2543Smrg	(*num_inout)= first;
64706f2543Smrg    }
65706f2543Smrg    else {
66706f2543Smrg	char *	ptr;
67706f2543Smrg	int 	extra;
68706f2543Smrg	ptr= *elems;
69706f2543Smrg	extra= ((*num_inout)-(first+count))*elem_sz;
70706f2543Smrg	if (extra>0)
71706f2543Smrg	    memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra);
72706f2543Smrg	(*num_inout)-= count;
73706f2543Smrg    }
74706f2543Smrg    return;
75706f2543Smrg}
76706f2543Smrg
77706f2543Smrgtypedef void (*ContentsClearFunc)(
78706f2543Smrg		char *		/* priv */
79706f2543Smrg);
80706f2543Smrg
81706f2543Smrgstatic void
82706f2543Smrg_XkbFreeGeomNonLeafElems(	Bool			freeAll,
83706f2543Smrg				int			first,
84706f2543Smrg				int 			count,
85706f2543Smrg				unsigned short *	num_inout,
86706f2543Smrg				unsigned short *	sz_inout,
87706f2543Smrg				char **			elems,
88706f2543Smrg				unsigned int		elem_sz,
89706f2543Smrg				ContentsClearFunc	freeFunc)
90706f2543Smrg{
91706f2543Smrgregister int i;
92706f2543Smrgregister char *ptr;
93706f2543Smrg
94706f2543Smrg    if (freeAll) {
95706f2543Smrg	first= 0;
96706f2543Smrg	count= (*num_inout);
97706f2543Smrg    }
98706f2543Smrg    else if ((first>=(*num_inout))||(first<0)||(count<1))
99706f2543Smrg	return;
100706f2543Smrg    else if (first+count>(*num_inout))
101706f2543Smrg	count= (*num_inout)-first;
102706f2543Smrg    if (*elems==NULL)
103706f2543Smrg	return;
104706f2543Smrg
105706f2543Smrg    if (freeFunc) {
106706f2543Smrg	ptr= *elems;
107706f2543Smrg	ptr+= first*elem_sz;
108706f2543Smrg	for (i=0;i<count;i++) {
109706f2543Smrg	    (*freeFunc)(ptr);
110706f2543Smrg	    ptr+= elem_sz;
111706f2543Smrg	}
112706f2543Smrg    }
113706f2543Smrg    if (freeAll) {
114706f2543Smrg	(*num_inout)= (*sz_inout)= 0;
115706f2543Smrg	free(*elems);
116706f2543Smrg	*elems = NULL;
117706f2543Smrg    }
118706f2543Smrg    else if (first+count>=(*num_inout))
119706f2543Smrg	*num_inout= first;
120706f2543Smrg    else {
121706f2543Smrg	i= ((*num_inout)-(first+count))*elem_sz;
122706f2543Smrg	ptr= *elems;
123706f2543Smrg	memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i);
124706f2543Smrg	(*num_inout)-= count;
125706f2543Smrg    }
126706f2543Smrg    return;
127706f2543Smrg}
128706f2543Smrg
129706f2543Smrg/***====================================================================***/
130706f2543Smrg
131706f2543Smrgstatic void
132706f2543Smrg_XkbClearProperty(char *prop_in)
133706f2543Smrg{
134706f2543SmrgXkbPropertyPtr	prop= (XkbPropertyPtr)prop_in;
135706f2543Smrg
136706f2543Smrg    free(prop->name);
137706f2543Smrg    prop->name = NULL;
138706f2543Smrg    free(prop->value);
139706f2543Smrg    prop->value = NULL;
140706f2543Smrg    return;
141706f2543Smrg}
142706f2543Smrg
143706f2543Smrgvoid
144706f2543SmrgXkbFreeGeomProperties(	XkbGeometryPtr	geom,
145706f2543Smrg			int		first,
146706f2543Smrg			int		count,
147706f2543Smrg			Bool		freeAll)
148706f2543Smrg{
149706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
150706f2543Smrg				&geom->num_properties,&geom->sz_properties,
151706f2543Smrg				(char **)&geom->properties,
152706f2543Smrg				sizeof(XkbPropertyRec),_XkbClearProperty);
153706f2543Smrg    return;
154706f2543Smrg}
155706f2543Smrg
156706f2543Smrg/***====================================================================***/
157706f2543Smrg
158706f2543Smrgvoid
159706f2543SmrgXkbFreeGeomKeyAliases(	XkbGeometryPtr	geom,
160706f2543Smrg			int		first,
161706f2543Smrg			int		count,
162706f2543Smrg			Bool		freeAll)
163706f2543Smrg{
164706f2543Smrg    _XkbFreeGeomLeafElems(freeAll,first,count,
165706f2543Smrg				&geom->num_key_aliases,&geom->sz_key_aliases,
166706f2543Smrg				(char **)&geom->key_aliases,
167706f2543Smrg				sizeof(XkbKeyAliasRec));
168706f2543Smrg    return;
169706f2543Smrg}
170706f2543Smrg
171706f2543Smrg/***====================================================================***/
172706f2543Smrg
173706f2543Smrgstatic void
174706f2543Smrg_XkbClearColor(char *color_in)
175706f2543Smrg{
176706f2543SmrgXkbColorPtr	color= (XkbColorPtr)color_in;
177706f2543Smrg
178706f2543Smrg    free(color->spec);
179706f2543Smrg    return;
180706f2543Smrg}
181706f2543Smrg
182706f2543Smrgvoid
183706f2543SmrgXkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)
184706f2543Smrg{
185706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
186706f2543Smrg				&geom->num_colors,&geom->sz_colors,
187706f2543Smrg				(char **)&geom->colors,
188706f2543Smrg				sizeof(XkbColorRec),_XkbClearColor);
189706f2543Smrg    return;
190706f2543Smrg}
191706f2543Smrg
192706f2543Smrg/***====================================================================***/
193706f2543Smrg
194706f2543Smrgvoid
195706f2543SmrgXkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)
196706f2543Smrg{
197706f2543Smrg    _XkbFreeGeomLeafElems(freeAll,first,count,
198706f2543Smrg				&outline->num_points,&outline->sz_points,
199706f2543Smrg				(char **)&outline->points,
200706f2543Smrg				sizeof(XkbPointRec));
201706f2543Smrg    return;
202706f2543Smrg}
203706f2543Smrg
204706f2543Smrg/***====================================================================***/
205706f2543Smrg
206706f2543Smrgstatic void
207706f2543Smrg_XkbClearOutline(char *outline_in)
208706f2543Smrg{
209706f2543SmrgXkbOutlinePtr	outline= (XkbOutlinePtr)outline_in;
210706f2543Smrg
211706f2543Smrg    if (outline->points!=NULL)
212706f2543Smrg	XkbFreeGeomPoints(outline,0,outline->num_points,TRUE);
213706f2543Smrg    return;
214706f2543Smrg}
215706f2543Smrg
216706f2543Smrgvoid
217706f2543SmrgXkbFreeGeomOutlines(XkbShapePtr	shape,int first,int count,Bool freeAll)
218706f2543Smrg{
219706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
220706f2543Smrg				&shape->num_outlines,&shape->sz_outlines,
221706f2543Smrg				(char **)&shape->outlines,
222706f2543Smrg				sizeof(XkbOutlineRec),_XkbClearOutline);
223706f2543Smrg
224706f2543Smrg    return;
225706f2543Smrg}
226706f2543Smrg
227706f2543Smrg/***====================================================================***/
228706f2543Smrg
229706f2543Smrgstatic void
230706f2543Smrg_XkbClearShape(char *shape_in)
231706f2543Smrg{
232706f2543SmrgXkbShapePtr	shape= (XkbShapePtr)shape_in;
233706f2543Smrg
234706f2543Smrg    if (shape->outlines)
235706f2543Smrg	XkbFreeGeomOutlines(shape,0,shape->num_outlines,TRUE);
236706f2543Smrg    return;
237706f2543Smrg}
238706f2543Smrg
239706f2543Smrgvoid
240706f2543SmrgXkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)
241706f2543Smrg{
242706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
243706f2543Smrg				&geom->num_shapes,&geom->sz_shapes,
244706f2543Smrg				(char **)&geom->shapes,
245706f2543Smrg				sizeof(XkbShapeRec),_XkbClearShape);
246706f2543Smrg    return;
247706f2543Smrg}
248706f2543Smrg
249706f2543Smrg/***====================================================================***/
250706f2543Smrg
251706f2543Smrgvoid
252706f2543SmrgXkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)
253706f2543Smrg{
254706f2543Smrg    _XkbFreeGeomLeafElems(freeAll,first,count,
255706f2543Smrg				&row->num_keys,&row->sz_keys,
256706f2543Smrg				(char **)&row->keys,
257706f2543Smrg				sizeof(XkbOverlayKeyRec));
258706f2543Smrg    return;
259706f2543Smrg}
260706f2543Smrg
261706f2543Smrg/***====================================================================***/
262706f2543Smrg
263706f2543Smrgstatic void
264706f2543Smrg_XkbClearOverlayRow(char *row_in)
265706f2543Smrg{
266706f2543SmrgXkbOverlayRowPtr	row= (XkbOverlayRowPtr)row_in;
267706f2543Smrg
268706f2543Smrg    if (row->keys!=NULL)
269706f2543Smrg	XkbFreeGeomOverlayKeys(row,0,row->num_keys,TRUE);
270706f2543Smrg    return;
271706f2543Smrg}
272706f2543Smrg
273706f2543Smrgvoid
274706f2543SmrgXkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll)
275706f2543Smrg{
276706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
277706f2543Smrg				&overlay->num_rows,&overlay->sz_rows,
278706f2543Smrg				(char **)&overlay->rows,
279706f2543Smrg				sizeof(XkbOverlayRowRec),_XkbClearOverlayRow);
280706f2543Smrg    return;
281706f2543Smrg}
282706f2543Smrg
283706f2543Smrg/***====================================================================***/
284706f2543Smrg
285706f2543Smrgstatic void
286706f2543Smrg_XkbClearOverlay(char *overlay_in)
287706f2543Smrg{
288706f2543SmrgXkbOverlayPtr	overlay= (XkbOverlayPtr)overlay_in;
289706f2543Smrg
290706f2543Smrg    if (overlay->rows!=NULL)
291706f2543Smrg	XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,TRUE);
292706f2543Smrg    return;
293706f2543Smrg}
294706f2543Smrg
295706f2543Smrgvoid
296706f2543SmrgXkbFreeGeomOverlays(XkbSectionPtr section,int first,int	count,Bool freeAll)
297706f2543Smrg{
298706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
299706f2543Smrg				&section->num_overlays,&section->sz_overlays,
300706f2543Smrg				(char **)&section->overlays,
301706f2543Smrg				sizeof(XkbOverlayRec),_XkbClearOverlay);
302706f2543Smrg    return;
303706f2543Smrg}
304706f2543Smrg
305706f2543Smrg/***====================================================================***/
306706f2543Smrg
307706f2543Smrgvoid
308706f2543SmrgXkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)
309706f2543Smrg{
310706f2543Smrg    _XkbFreeGeomLeafElems(freeAll,first,count,
311706f2543Smrg				&row->num_keys,&row->sz_keys,
312706f2543Smrg				(char **)&row->keys,
313706f2543Smrg				sizeof(XkbKeyRec));
314706f2543Smrg    return;
315706f2543Smrg}
316706f2543Smrg
317706f2543Smrg/***====================================================================***/
318706f2543Smrg
319706f2543Smrgstatic void
320706f2543Smrg_XkbClearRow(char *row_in)
321706f2543Smrg{
322706f2543SmrgXkbRowPtr	row= (XkbRowPtr)row_in;
323706f2543Smrg
324706f2543Smrg    if (row->keys!=NULL)
325706f2543Smrg	XkbFreeGeomKeys(row,0,row->num_keys,TRUE);
326706f2543Smrg    return;
327706f2543Smrg}
328706f2543Smrg
329706f2543Smrgvoid
330706f2543SmrgXkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)
331706f2543Smrg{
332706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
333706f2543Smrg				&section->num_rows,&section->sz_rows,
334706f2543Smrg				(char **)&section->rows,
335706f2543Smrg				sizeof(XkbRowRec),_XkbClearRow);
336706f2543Smrg}
337706f2543Smrg
338706f2543Smrg/***====================================================================***/
339706f2543Smrg
340706f2543Smrgstatic void
341706f2543Smrg_XkbClearSection(char *section_in)
342706f2543Smrg{
343706f2543SmrgXkbSectionPtr	section= (XkbSectionPtr)section_in;
344706f2543Smrg
345706f2543Smrg    if (section->rows!=NULL)
346706f2543Smrg	XkbFreeGeomRows(section,0,section->num_rows,TRUE);
347706f2543Smrg    if (section->doodads!=NULL) {
348706f2543Smrg	XkbFreeGeomDoodads(section->doodads,section->num_doodads,TRUE);
349706f2543Smrg	section->doodads= NULL;
350706f2543Smrg    }
351706f2543Smrg    return;
352706f2543Smrg}
353706f2543Smrg
354706f2543Smrgvoid
355706f2543SmrgXkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)
356706f2543Smrg{
357706f2543Smrg    _XkbFreeGeomNonLeafElems(freeAll,first,count,
358706f2543Smrg				&geom->num_sections,&geom->sz_sections,
359706f2543Smrg				(char **)&geom->sections,
360706f2543Smrg				sizeof(XkbSectionRec),_XkbClearSection);
361706f2543Smrg    return;
362706f2543Smrg}
363706f2543Smrg
364706f2543Smrg/***====================================================================***/
365706f2543Smrg
366706f2543Smrgstatic void
367706f2543Smrg_XkbClearDoodad(char *doodad_in)
368706f2543Smrg{
369706f2543SmrgXkbDoodadPtr	doodad= (XkbDoodadPtr)doodad_in;
370706f2543Smrg
371706f2543Smrg    switch (doodad->any.type) {
372706f2543Smrg   	case XkbTextDoodad:
373706f2543Smrg	    {
374706f2543Smrg		free(doodad->text.text);
375706f2543Smrg		doodad->text.text = NULL;
376706f2543Smrg		free(doodad->text.font);
377706f2543Smrg		doodad->text.font = NULL;
378706f2543Smrg	    }
379706f2543Smrg	    break;
380706f2543Smrg   	case XkbLogoDoodad:
381706f2543Smrg	    {
382706f2543Smrg		free(doodad->logo.logo_name);
383706f2543Smrg		doodad->logo.logo_name = NULL;
384706f2543Smrg	    }
385706f2543Smrg	    break;
386706f2543Smrg    }
387706f2543Smrg    return;
388706f2543Smrg}
389706f2543Smrg
390706f2543Smrgvoid
391706f2543SmrgXkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)
392706f2543Smrg{
393706f2543Smrgregister int 		i;
394706f2543Smrgregister XkbDoodadPtr	doodad;
395706f2543Smrg
396706f2543Smrg    if (doodads) {
397706f2543Smrg	for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) {
398706f2543Smrg	    _XkbClearDoodad((char *)doodad);
399706f2543Smrg	}
400706f2543Smrg	if (freeAll)
401706f2543Smrg	    free(doodads);
402706f2543Smrg    }
403706f2543Smrg    return;
404706f2543Smrg}
405706f2543Smrg
406706f2543Smrgvoid
407706f2543SmrgXkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)
408706f2543Smrg{
409706f2543Smrg    if (geom==NULL)
410706f2543Smrg	return;
411706f2543Smrg    if (freeMap)
412706f2543Smrg	which= XkbGeomAllMask;
413706f2543Smrg    if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL))
414706f2543Smrg	XkbFreeGeomProperties(geom,0,geom->num_properties,TRUE);
415706f2543Smrg    if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL))
416706f2543Smrg	XkbFreeGeomColors(geom,0,geom->num_colors,TRUE);
417706f2543Smrg    if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL))
418706f2543Smrg	XkbFreeGeomShapes(geom,0,geom->num_shapes,TRUE);
419706f2543Smrg    if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL))
420706f2543Smrg	XkbFreeGeomSections(geom,0,geom->num_sections,TRUE);
421706f2543Smrg    if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) {
422706f2543Smrg	XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,TRUE);
423706f2543Smrg	geom->doodads= NULL;
424706f2543Smrg	geom->num_doodads= geom->sz_doodads= 0;
425706f2543Smrg    }
426706f2543Smrg    if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL))
427706f2543Smrg	XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,TRUE);
428706f2543Smrg    if (freeMap) {
429706f2543Smrg	free(geom->label_font);
430706f2543Smrg	geom->label_font = NULL;
431706f2543Smrg	free(geom);
432706f2543Smrg    }
433706f2543Smrg    return;
434706f2543Smrg}
435706f2543Smrg
436706f2543Smrg/***====================================================================***/
437706f2543Smrg
438706f2543Smrgstatic Status
439706f2543Smrg_XkbGeomAlloc(	void **		old,
440706f2543Smrg		unsigned short *	num,
441706f2543Smrg		unsigned short *	total,
442706f2543Smrg		int			num_new,
443706f2543Smrg		size_t			sz_elem)
444706f2543Smrg{
445706f2543Smrg    if (num_new<1)
446706f2543Smrg	return Success;
447706f2543Smrg    if ((*old)==NULL)
448706f2543Smrg	*num= *total= 0;
449706f2543Smrg
450706f2543Smrg    if ((*num)+num_new<=(*total))
451706f2543Smrg	return Success;
452706f2543Smrg
453706f2543Smrg    *total= (*num)+num_new;
454706f2543Smrg    if ((*old)!=NULL)
455706f2543Smrg	 (*old)= realloc((*old),(*total)*sz_elem);
456706f2543Smrg    else (*old)= calloc((*total),sz_elem);
457706f2543Smrg    if ((*old)==NULL) {
458706f2543Smrg	*total= *num= 0;
459706f2543Smrg	return BadAlloc;
460706f2543Smrg    }
461706f2543Smrg
462706f2543Smrg    if (*num>0) {
463706f2543Smrg	char *tmp= (char *)(*old);
464706f2543Smrg	memset(&tmp[sz_elem*(*num)], 0, (num_new*sz_elem));
465706f2543Smrg    }
466706f2543Smrg    return Success;
467706f2543Smrg}
468706f2543Smrg
469706f2543Smrg#define	_XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\
470706f2543Smrg				&(g)->num_properties,&(g)->sz_properties,\
471706f2543Smrg				(n),sizeof(XkbPropertyRec))
472706f2543Smrg#define	_XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\
473706f2543Smrg				&(g)->num_colors,&(g)->sz_colors,\
474706f2543Smrg				(n),sizeof(XkbColorRec))
475706f2543Smrg#define	_XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\
476706f2543Smrg				&(g)->num_shapes,&(g)->sz_shapes,\
477706f2543Smrg				(n),sizeof(XkbShapeRec))
478706f2543Smrg#define	_XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\
479706f2543Smrg				&(g)->num_sections,&(g)->sz_sections,\
480706f2543Smrg				(n),sizeof(XkbSectionRec))
481706f2543Smrg#define	_XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\
482706f2543Smrg				&(g)->num_doodads,&(g)->sz_doodads,\
483706f2543Smrg				(n),sizeof(XkbDoodadRec))
484706f2543Smrg#define	_XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\
485706f2543Smrg				&(g)->num_key_aliases,&(g)->sz_key_aliases,\
486706f2543Smrg				(n),sizeof(XkbKeyAliasRec))
487706f2543Smrg
488706f2543Smrg#define	_XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\
489706f2543Smrg				&(s)->num_outlines,&(s)->sz_outlines,\
490706f2543Smrg				(n),sizeof(XkbOutlineRec))
491706f2543Smrg#define	_XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\
492706f2543Smrg				&(s)->num_rows,&(s)->sz_rows,\
493706f2543Smrg				(n),sizeof(XkbRowRec))
494706f2543Smrg#define	_XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\
495706f2543Smrg				&(o)->num_points,&(o)->sz_points,\
496706f2543Smrg				(n),sizeof(XkbPointRec))
497706f2543Smrg#define	_XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
498706f2543Smrg				&(r)->num_keys,&(r)->sz_keys,\
499706f2543Smrg				(n),sizeof(XkbKeyRec))
500706f2543Smrg#define	_XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\
501706f2543Smrg				&(s)->num_overlays,&(s)->sz_overlays,\
502706f2543Smrg				(n),sizeof(XkbOverlayRec))
503706f2543Smrg#define	_XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\
504706f2543Smrg				&(o)->num_rows,&(o)->sz_rows,\
505706f2543Smrg				(n),sizeof(XkbOverlayRowRec))
506706f2543Smrg#define	_XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
507706f2543Smrg				&(r)->num_keys,&(r)->sz_keys,\
508706f2543Smrg				(n),sizeof(XkbOverlayKeyRec))
509706f2543Smrg
510706f2543SmrgStatus
511706f2543SmrgXkbAllocGeomProps(XkbGeometryPtr geom,int nProps)
512706f2543Smrg{
513706f2543Smrg    return _XkbAllocProps(geom,nProps);
514706f2543Smrg}
515706f2543Smrg
516706f2543SmrgStatus
517706f2543SmrgXkbAllocGeomColors(XkbGeometryPtr geom,int nColors)
518706f2543Smrg{
519706f2543Smrg    return _XkbAllocColors(geom,nColors);
520706f2543Smrg}
521706f2543Smrg
522706f2543SmrgStatus
523706f2543SmrgXkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases)
524706f2543Smrg{
525706f2543Smrg    return _XkbAllocKeyAliases(geom,nKeyAliases);
526706f2543Smrg}
527706f2543Smrg
528706f2543SmrgStatus
529706f2543SmrgXkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes)
530706f2543Smrg{
531706f2543Smrg    return _XkbAllocShapes(geom,nShapes);
532706f2543Smrg}
533706f2543Smrg
534706f2543SmrgStatus
535706f2543SmrgXkbAllocGeomSections(XkbGeometryPtr geom,int nSections)
536706f2543Smrg{
537706f2543Smrg    return _XkbAllocSections(geom,nSections);
538706f2543Smrg}
539706f2543Smrg
540706f2543SmrgStatus
541706f2543SmrgXkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays)
542706f2543Smrg{
543706f2543Smrg    return _XkbAllocOverlays(section,nOverlays);
544706f2543Smrg}
545706f2543Smrg
546706f2543SmrgStatus
547706f2543SmrgXkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows)
548706f2543Smrg{
549706f2543Smrg    return _XkbAllocOverlayRows(overlay,nRows);
550706f2543Smrg}
551706f2543Smrg
552706f2543SmrgStatus
553706f2543SmrgXkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys)
554706f2543Smrg{
555706f2543Smrg    return _XkbAllocOverlayKeys(row,nKeys);
556706f2543Smrg}
557706f2543Smrg
558706f2543SmrgStatus
559706f2543SmrgXkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads)
560706f2543Smrg{
561706f2543Smrg    return _XkbAllocDoodads(geom,nDoodads);
562706f2543Smrg}
563706f2543Smrg
564706f2543SmrgStatus
565706f2543SmrgXkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads)
566706f2543Smrg{
567706f2543Smrg    return _XkbAllocDoodads(section,nDoodads);
568706f2543Smrg}
569706f2543Smrg
570706f2543SmrgStatus
571706f2543SmrgXkbAllocGeomOutlines(XkbShapePtr shape,int nOL)
572706f2543Smrg{
573706f2543Smrg    return _XkbAllocOutlines(shape,nOL);
574706f2543Smrg}
575706f2543Smrg
576706f2543SmrgStatus
577706f2543SmrgXkbAllocGeomRows(XkbSectionPtr section,int nRows)
578706f2543Smrg{
579706f2543Smrg    return _XkbAllocRows(section,nRows);
580706f2543Smrg}
581706f2543Smrg
582706f2543SmrgStatus
583706f2543SmrgXkbAllocGeomPoints(XkbOutlinePtr ol,int nPts)
584706f2543Smrg{
585706f2543Smrg    return _XkbAllocPoints(ol,nPts);
586706f2543Smrg}
587706f2543Smrg
588706f2543SmrgStatus
589706f2543SmrgXkbAllocGeomKeys(XkbRowPtr row,int nKeys)
590706f2543Smrg{
591706f2543Smrg    return _XkbAllocKeys(row,nKeys);
592706f2543Smrg}
593706f2543Smrg
594706f2543SmrgStatus
595706f2543SmrgXkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)
596706f2543Smrg{
597706f2543SmrgXkbGeometryPtr	geom;
598706f2543SmrgStatus		rtrn;
599706f2543Smrg
600706f2543Smrg    if (xkb->geom==NULL) {
601706f2543Smrg	xkb->geom= calloc(1, sizeof(XkbGeometryRec));
602706f2543Smrg	if (!xkb->geom)
603706f2543Smrg	    return BadAlloc;
604706f2543Smrg    }
605706f2543Smrg    geom= xkb->geom;
606706f2543Smrg    if ((sizes->which&XkbGeomPropertiesMask)&&
607706f2543Smrg	((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) {
608706f2543Smrg	goto BAIL;
609706f2543Smrg    }
610706f2543Smrg    if ((sizes->which&XkbGeomColorsMask)&&
611706f2543Smrg	((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) {
612706f2543Smrg	goto BAIL;
613706f2543Smrg    }
614706f2543Smrg    if ((sizes->which&XkbGeomShapesMask)&&
615706f2543Smrg	((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) {
616706f2543Smrg	goto BAIL;
617706f2543Smrg    }
618706f2543Smrg    if ((sizes->which&XkbGeomSectionsMask)&&
619706f2543Smrg	((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) {
620706f2543Smrg	goto BAIL;
621706f2543Smrg    }
622706f2543Smrg    if ((sizes->which&XkbGeomDoodadsMask)&&
623706f2543Smrg	((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) {
624706f2543Smrg	goto BAIL;
625706f2543Smrg    }
626706f2543Smrg    if ((sizes->which&XkbGeomKeyAliasesMask)&&
627706f2543Smrg	((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) {
628706f2543Smrg	goto BAIL;
629706f2543Smrg    }
630706f2543Smrg    return Success;
631706f2543SmrgBAIL:
632706f2543Smrg    XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
633706f2543Smrg    xkb->geom= NULL;
634706f2543Smrg    return rtrn;
635706f2543Smrg}
636706f2543Smrg
637706f2543Smrg/***====================================================================***/
638706f2543Smrg
639706f2543SmrgXkbPropertyPtr
640706f2543SmrgXkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value)
641706f2543Smrg{
642706f2543Smrgregister int i;
643706f2543Smrgregister XkbPropertyPtr prop;
644706f2543Smrg
645706f2543Smrg    if ((!geom)||(!name)||(!value))
646706f2543Smrg	return NULL;
647706f2543Smrg    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
648706f2543Smrg	if ((prop->name)&&(strcmp(name,prop->name)==0)) {
649706f2543Smrg	    free(prop->value);
650706f2543Smrg	    prop->value= malloc(strlen(value)+1);
651706f2543Smrg	    if (prop->value)
652706f2543Smrg		strcpy(prop->value,value);
653706f2543Smrg	    return prop;
654706f2543Smrg	}
655706f2543Smrg    }
656706f2543Smrg    if ((geom->num_properties>=geom->sz_properties)&&
657706f2543Smrg					(_XkbAllocProps(geom,1)!=Success)) {
658706f2543Smrg	return NULL;
659706f2543Smrg    }
660706f2543Smrg    prop= &geom->properties[geom->num_properties];
661706f2543Smrg    prop->name= malloc(strlen(name)+1);
662706f2543Smrg    if (!prop->name)
663706f2543Smrg	return NULL;
664706f2543Smrg    strcpy(prop->name,name);
665706f2543Smrg    prop->value= malloc(strlen(value)+1);
666706f2543Smrg    if (!prop->value) {
667706f2543Smrg	free(prop->name);
668706f2543Smrg	prop->name= NULL;
669706f2543Smrg	return NULL;
670706f2543Smrg    }
671706f2543Smrg    strcpy(prop->value,value);
672706f2543Smrg    geom->num_properties++;
673706f2543Smrg    return prop;
674706f2543Smrg}
675706f2543Smrg
676706f2543SmrgXkbKeyAliasPtr
677706f2543SmrgXkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
678706f2543Smrg{
679706f2543Smrgregister int i;
680706f2543Smrgregister XkbKeyAliasPtr alias;
681706f2543Smrg
682706f2543Smrg    if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
683706f2543Smrg	return NULL;
684706f2543Smrg    for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
685706f2543Smrg	if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
686706f2543Smrg	    memset(alias->real, 0, XkbKeyNameLength);
687706f2543Smrg	    strncpy(alias->real,realStr,XkbKeyNameLength);
688706f2543Smrg	    return alias;
689706f2543Smrg	}
690706f2543Smrg    }
691706f2543Smrg    if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
692706f2543Smrg				(_XkbAllocKeyAliases(geom,1)!=Success)) {
693706f2543Smrg	return NULL;
694706f2543Smrg    }
695706f2543Smrg    alias= &geom->key_aliases[geom->num_key_aliases];
696706f2543Smrg    memset(alias, 0, sizeof(XkbKeyAliasRec));
697706f2543Smrg    strncpy(alias->alias,aliasStr,XkbKeyNameLength);
698706f2543Smrg    strncpy(alias->real,realStr,XkbKeyNameLength);
699706f2543Smrg    geom->num_key_aliases++;
700706f2543Smrg    return alias;
701706f2543Smrg}
702706f2543Smrg
703706f2543SmrgXkbColorPtr
704706f2543SmrgXkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
705706f2543Smrg{
706706f2543Smrgregister int i;
707706f2543Smrgregister XkbColorPtr color;
708706f2543Smrg
709706f2543Smrg    if ((!geom)||(!spec))
710706f2543Smrg	return NULL;
711706f2543Smrg    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
712706f2543Smrg	if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
713706f2543Smrg	    color->pixel= pixel;
714706f2543Smrg	    return color;
715706f2543Smrg	}
716706f2543Smrg    }
717706f2543Smrg    if ((geom->num_colors>=geom->sz_colors)&&
718706f2543Smrg					(_XkbAllocColors(geom,1)!=Success)) {
719706f2543Smrg	return NULL;
720706f2543Smrg    }
721706f2543Smrg    color= &geom->colors[geom->num_colors];
722706f2543Smrg    color->pixel= pixel;
723706f2543Smrg    color->spec= malloc(strlen(spec)+1);
724706f2543Smrg    if (!color->spec)
725706f2543Smrg	return NULL;
726706f2543Smrg    strcpy(color->spec,spec);
727706f2543Smrg    geom->num_colors++;
728706f2543Smrg    return color;
729706f2543Smrg}
730706f2543Smrg
731706f2543SmrgXkbOutlinePtr
732706f2543SmrgXkbAddGeomOutline(XkbShapePtr shape,int sz_points)
733706f2543Smrg{
734706f2543SmrgXkbOutlinePtr	outline;
735706f2543Smrg
736706f2543Smrg    if ((!shape)||(sz_points<0))
737706f2543Smrg	return NULL;
738706f2543Smrg    if ((shape->num_outlines>=shape->sz_outlines)&&
739706f2543Smrg					(_XkbAllocOutlines(shape,1)!=Success)) {
740706f2543Smrg	return NULL;
741706f2543Smrg    }
742706f2543Smrg    outline= &shape->outlines[shape->num_outlines];
743706f2543Smrg    memset(outline, 0, sizeof(XkbOutlineRec));
744706f2543Smrg    if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
745706f2543Smrg	return NULL;
746706f2543Smrg    shape->num_outlines++;
747706f2543Smrg    return outline;
748706f2543Smrg}
749706f2543Smrg
750706f2543SmrgXkbShapePtr
751706f2543SmrgXkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
752706f2543Smrg{
753706f2543SmrgXkbShapePtr	shape;
754706f2543Smrgregister int	i;
755706f2543Smrg
756706f2543Smrg    if ((!geom)||(!name)||(sz_outlines<0))
757706f2543Smrg	return NULL;
758706f2543Smrg    if (geom->num_shapes>0) {
759706f2543Smrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
760706f2543Smrg	    if (name==shape->name)
761706f2543Smrg		return shape;
762706f2543Smrg	}
763706f2543Smrg    }
764706f2543Smrg    if ((geom->num_shapes>=geom->sz_shapes)&&
765706f2543Smrg					(_XkbAllocShapes(geom,1)!=Success))
766706f2543Smrg	return NULL;
767706f2543Smrg    shape= &geom->shapes[geom->num_shapes];
768706f2543Smrg    memset(shape, 0, sizeof(XkbShapeRec));
769706f2543Smrg    if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
770706f2543Smrg	return NULL;
771706f2543Smrg    shape->name= name;
772706f2543Smrg    shape->primary= shape->approx= NULL;
773706f2543Smrg    geom->num_shapes++;
774706f2543Smrg    return shape;
775706f2543Smrg}
776706f2543Smrg
777706f2543SmrgXkbKeyPtr
778706f2543SmrgXkbAddGeomKey(XkbRowPtr row)
779706f2543Smrg{
780706f2543SmrgXkbKeyPtr	key;
781706f2543Smrg    if (!row)
782706f2543Smrg	return NULL;
783706f2543Smrg    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
784706f2543Smrg	return NULL;
785706f2543Smrg    key= &row->keys[row->num_keys++];
786706f2543Smrg    memset(key, 0, sizeof(XkbKeyRec));
787706f2543Smrg    return key;
788706f2543Smrg}
789706f2543Smrg
790706f2543SmrgXkbRowPtr
791706f2543SmrgXkbAddGeomRow(XkbSectionPtr section,int sz_keys)
792706f2543Smrg{
793706f2543SmrgXkbRowPtr	row;
794706f2543Smrg
795706f2543Smrg    if ((!section)||(sz_keys<0))
796706f2543Smrg	return NULL;
797706f2543Smrg    if ((section->num_rows>=section->sz_rows)&&
798706f2543Smrg    					(_XkbAllocRows(section,1)!=Success))
799706f2543Smrg	return NULL;
800706f2543Smrg    row= &section->rows[section->num_rows];
801706f2543Smrg    memset(row, 0, sizeof(XkbRowRec));
802706f2543Smrg    if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
803706f2543Smrg	return NULL;
804706f2543Smrg    section->num_rows++;
805706f2543Smrg    return row;
806706f2543Smrg}
807706f2543Smrg
808706f2543SmrgXkbSectionPtr
809706f2543SmrgXkbAddGeomSection(	XkbGeometryPtr	geom,
810706f2543Smrg			Atom		name,
811706f2543Smrg			int		sz_rows,
812706f2543Smrg			int		sz_doodads,
813706f2543Smrg			int		sz_over)
814706f2543Smrg{
815706f2543Smrgregister int	i;
816706f2543SmrgXkbSectionPtr	section;
817706f2543Smrg
818706f2543Smrg    if ((!geom)||(name==None)||(sz_rows<0))
819706f2543Smrg	return NULL;
820706f2543Smrg    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
821706f2543Smrg	if (section->name!=name)
822706f2543Smrg	    continue;
823706f2543Smrg	if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
824706f2543Smrg	    ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
825706f2543Smrg	    ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
826706f2543Smrg	    return NULL;
827706f2543Smrg	return section;
828706f2543Smrg    }
829706f2543Smrg    if ((geom->num_sections>=geom->sz_sections)&&
830706f2543Smrg					(_XkbAllocSections(geom,1)!=Success))
831706f2543Smrg	return NULL;
832706f2543Smrg    section= &geom->sections[geom->num_sections];
833706f2543Smrg    if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
834706f2543Smrg	return NULL;
835706f2543Smrg    if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
836706f2543Smrg	if (section->rows) {
837706f2543Smrg	    free(section->rows);
838706f2543Smrg	    section->rows= NULL;
839706f2543Smrg	    section->sz_rows= section->num_rows= 0;
840706f2543Smrg	}
841706f2543Smrg	return NULL;
842706f2543Smrg    }
843706f2543Smrg    section->name= name;
844706f2543Smrg    geom->num_sections++;
845706f2543Smrg    return section;
846706f2543Smrg}
847706f2543Smrg
848706f2543SmrgXkbDoodadPtr
849706f2543SmrgXkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
850706f2543Smrg{
851706f2543SmrgXkbDoodadPtr	old,doodad;
852706f2543Smrgregister int	i,nDoodads;
853706f2543Smrg
854706f2543Smrg    if ((!geom)||(name==None))
855706f2543Smrg	return NULL;
856706f2543Smrg    if ((section!=NULL)&&(section->num_doodads>0)) {
857706f2543Smrg	old= section->doodads;
858706f2543Smrg	nDoodads= section->num_doodads;
859706f2543Smrg    }
860706f2543Smrg    else {
861706f2543Smrg	old= geom->doodads;
862706f2543Smrg	nDoodads= geom->num_doodads;
863706f2543Smrg    }
864706f2543Smrg    for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
865706f2543Smrg	if (doodad->any.name==name)
866706f2543Smrg	    return doodad;
867706f2543Smrg    }
868706f2543Smrg    if (section) {
869706f2543Smrg	if ((section->num_doodads>=geom->sz_doodads)&&
870706f2543Smrg	    (_XkbAllocDoodads(section,1)!=Success)) {
871706f2543Smrg	    return NULL;
872706f2543Smrg	}
873706f2543Smrg	doodad= &section->doodads[section->num_doodads++];
874706f2543Smrg    }
875706f2543Smrg    else {
876706f2543Smrg	if ((geom->num_doodads>=geom->sz_doodads)&&
877706f2543Smrg					(_XkbAllocDoodads(geom,1)!=Success))
878706f2543Smrg	    return NULL;
879706f2543Smrg	doodad= &geom->doodads[geom->num_doodads++];
880706f2543Smrg    }
881706f2543Smrg    memset(doodad, 0, sizeof(XkbDoodadRec));
882706f2543Smrg    doodad->any.name= name;
883706f2543Smrg    return doodad;
884706f2543Smrg}
885706f2543Smrg
886706f2543SmrgXkbOverlayKeyPtr
887706f2543SmrgXkbAddGeomOverlayKey(	XkbOverlayPtr		overlay,
888706f2543Smrg			XkbOverlayRowPtr 	row,
889706f2543Smrg			char *			over,
890706f2543Smrg			char *			under)
891706f2543Smrg{
892706f2543Smrgregister int	i;
893706f2543SmrgXkbOverlayKeyPtr key;
894706f2543SmrgXkbSectionPtr	section;
895706f2543SmrgXkbRowPtr	row_under;
896706f2543SmrgBool		found;
897706f2543Smrg
898706f2543Smrg    if ((!overlay)||(!row)||(!over)||(!under))
899706f2543Smrg	return NULL;
900706f2543Smrg    section= overlay->section_under;
901706f2543Smrg    if (row->row_under>=section->num_rows)
902706f2543Smrg	return NULL;
903706f2543Smrg    row_under= &section->rows[row->row_under];
904706f2543Smrg    for (i=0,found=FALSE;i<row_under->num_keys;i++) {
905706f2543Smrg	if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
906706f2543Smrg	    found= TRUE;
907706f2543Smrg	    break;
908706f2543Smrg	}
909706f2543Smrg    }
910706f2543Smrg    if (!found)
911706f2543Smrg   	return NULL;
912706f2543Smrg    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
913706f2543Smrg	return NULL;
914706f2543Smrg    key= &row->keys[row->num_keys];
915706f2543Smrg    strncpy(key->under.name,under,XkbKeyNameLength);
916706f2543Smrg    strncpy(key->over.name,over,XkbKeyNameLength);
917706f2543Smrg    row->num_keys++;
918706f2543Smrg    return key;
919706f2543Smrg}
920706f2543Smrg
921706f2543SmrgXkbOverlayRowPtr
922706f2543SmrgXkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
923706f2543Smrg{
924706f2543Smrgregister int		i;
925706f2543SmrgXkbOverlayRowPtr	row;
926706f2543Smrg
927706f2543Smrg    if ((!overlay)||(sz_keys<0))
928706f2543Smrg	return NULL;
929706f2543Smrg    if (row_under>=overlay->section_under->num_rows)
930706f2543Smrg	return NULL;
931706f2543Smrg    for (i=0;i<overlay->num_rows;i++) {
932706f2543Smrg	if (overlay->rows[i].row_under==row_under) {
933706f2543Smrg	    row= &overlay->rows[i];
934706f2543Smrg	    if ((row->sz_keys<sz_keys)&&
935706f2543Smrg				(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
936706f2543Smrg		return NULL;
937706f2543Smrg	    }
938706f2543Smrg	    return &overlay->rows[i];
939706f2543Smrg	}
940706f2543Smrg    }
941706f2543Smrg    if ((overlay->num_rows>=overlay->sz_rows)&&
942706f2543Smrg				(_XkbAllocOverlayRows(overlay,1)!=Success))
943706f2543Smrg	return NULL;
944706f2543Smrg    row= &overlay->rows[overlay->num_rows];
945706f2543Smrg    memset(row, 0, sizeof(XkbOverlayRowRec));
946706f2543Smrg    if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
947706f2543Smrg	return NULL;
948706f2543Smrg    row->row_under= row_under;
949706f2543Smrg    overlay->num_rows++;
950706f2543Smrg    return row;
951706f2543Smrg}
952706f2543Smrg
953706f2543SmrgXkbOverlayPtr
954706f2543SmrgXkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
955706f2543Smrg{
956706f2543Smrgregister int	i;
957706f2543SmrgXkbOverlayPtr	overlay;
958706f2543Smrg
959706f2543Smrg    if ((!section)||(name==None)||(sz_rows==0))
960706f2543Smrg	return NULL;
961706f2543Smrg
962706f2543Smrg    for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
963706f2543Smrg	if (overlay->name==name) {
964706f2543Smrg	    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
965706f2543Smrg		return NULL;
966706f2543Smrg	    return overlay;
967706f2543Smrg	}
968706f2543Smrg    }
969706f2543Smrg    if ((section->num_overlays>=section->sz_overlays)&&
970706f2543Smrg				(_XkbAllocOverlays(section,1)!=Success))
971706f2543Smrg	return NULL;
972706f2543Smrg    overlay= &section->overlays[section->num_overlays];
973706f2543Smrg    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
974706f2543Smrg	return NULL;
975706f2543Smrg    overlay->name= name;
976706f2543Smrg    overlay->section_under= section;
977706f2543Smrg    section->num_overlays++;
978706f2543Smrg    return overlay;
979706f2543Smrg}
980