XKBGAlloc.c revision e9fcaa8a
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#include "Xlibint.h"
37#include "XKBlibint.h"
38#include <X11/extensions/XKBgeom.h>
39#include <X11/extensions/XKBproto.h>
40
41#else
42
43#include <stdio.h>
44#include <X11/X.h>
45#include <X11/Xproto.h>
46#include "misc.h"
47#include "inputstr.h"
48#include <X11/extensions/XKBsrv.h>
49#include <X11/extensions/XKBgeom.h>
50
51#endif /* XKB_IN_SERVER */
52
53#ifdef X_NOT_POSIX
54#define Size_t unsigned int
55#else
56#define Size_t size_t
57#endif
58
59/***====================================================================***/
60
61static void
62_XkbFreeGeomLeafElems(	Bool			freeAll,
63			int			first,
64			int 			count,
65			unsigned short *	num_inout,
66			unsigned short *	sz_inout,
67			char **			elems,
68			unsigned int		elem_sz)
69{
70    if ((freeAll)||(*elems==NULL)) {
71	*num_inout= *sz_inout= 0;
72	if (*elems!=NULL) {
73	    _XkbFree(*elems);
74	    *elems= NULL;
75	}
76	return;
77    }
78
79    if ((first>=(*num_inout))||(first<0)||(count<1))
80	return;
81
82    if (first+count>=(*num_inout)) {
83	/* truncating the array is easy */
84	(*num_inout)= first;
85    }
86    else {
87	char *	ptr;
88	int 	extra;
89	ptr= *elems;
90	extra= ((*num_inout)-(first+count))*elem_sz;
91	if (extra>0)
92	    memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra);
93	(*num_inout)-= count;
94    }
95    return;
96}
97
98typedef void (*ContentsClearFunc)(
99		char *		/* priv */
100);
101
102static void
103_XkbFreeGeomNonLeafElems(	Bool			freeAll,
104				int			first,
105				int 			count,
106				unsigned short *	num_inout,
107				unsigned short *	sz_inout,
108				char **			elems,
109				unsigned int		elem_sz,
110				ContentsClearFunc	freeFunc)
111{
112register int i;
113register char *ptr;
114
115    if (freeAll) {
116	first= 0;
117	count= (*num_inout);
118    }
119    else if ((first>=(*num_inout))||(first<0)||(count<1))
120	return;
121    else if (first+count>(*num_inout))
122	count= (*num_inout)-first;
123    if (*elems==NULL)
124	return;
125
126    if (freeFunc) {
127	ptr= *elems;
128	ptr+= first*elem_sz;
129	for (i=0;i<count;i++) {
130	    (*freeFunc)(ptr);
131	    ptr+= elem_sz;
132	}
133    }
134    if (freeAll) {
135	(*num_inout)= (*sz_inout)= 0;
136	if (*elems) {
137	    _XkbFree(*elems);
138	    *elems= NULL;
139	}
140    }
141    else if (first+count>=(*num_inout))
142	*num_inout= first;
143    else {
144	i= ((*num_inout)-(first+count))*elem_sz;
145	ptr= *elems;
146	memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i);
147	(*num_inout)-= count;
148    }
149    return;
150}
151
152/***====================================================================***/
153
154static void
155_XkbClearProperty(char *prop_in)
156{
157XkbPropertyPtr	prop= (XkbPropertyPtr)prop_in;
158
159    if (prop->name) {
160	_XkbFree(prop->name);
161	prop->name= NULL;
162    }
163    if (prop->value) {
164	_XkbFree(prop->value);
165	prop->value= NULL;
166    }
167    return;
168}
169
170void
171XkbFreeGeomProperties(	XkbGeometryPtr	geom,
172			int		first,
173			int		count,
174			Bool		freeAll)
175{
176    _XkbFreeGeomNonLeafElems(freeAll,first,count,
177				&geom->num_properties,&geom->sz_properties,
178				(char **)&geom->properties,
179				sizeof(XkbPropertyRec),_XkbClearProperty);
180    return;
181}
182
183/***====================================================================***/
184
185void
186XkbFreeGeomKeyAliases(	XkbGeometryPtr	geom,
187			int		first,
188			int		count,
189			Bool		freeAll)
190{
191    _XkbFreeGeomLeafElems(freeAll,first,count,
192				&geom->num_key_aliases,&geom->sz_key_aliases,
193				(char **)&geom->key_aliases,
194				sizeof(XkbKeyAliasRec));
195    return;
196}
197
198/***====================================================================***/
199
200static void
201_XkbClearColor(char *color_in)
202{
203XkbColorPtr	color= (XkbColorPtr)color_in;
204
205    if (color->spec)
206	_XkbFree(color->spec);
207    return;
208}
209
210void
211XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)
212{
213    _XkbFreeGeomNonLeafElems(freeAll,first,count,
214				&geom->num_colors,&geom->sz_colors,
215				(char **)&geom->colors,
216				sizeof(XkbColorRec),_XkbClearColor);
217    return;
218}
219
220/***====================================================================***/
221
222void
223XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)
224{
225    _XkbFreeGeomLeafElems(freeAll,first,count,
226				&outline->num_points,&outline->sz_points,
227				(char **)&outline->points,
228				sizeof(XkbPointRec));
229    return;
230}
231
232/***====================================================================***/
233
234static void
235_XkbClearOutline(char *outline_in)
236{
237XkbOutlinePtr	outline= (XkbOutlinePtr)outline_in;
238
239    if (outline->points!=NULL)
240	XkbFreeGeomPoints(outline,0,outline->num_points,True);
241    return;
242}
243
244void
245XkbFreeGeomOutlines(XkbShapePtr	shape,int first,int count,Bool freeAll)
246{
247    _XkbFreeGeomNonLeafElems(freeAll,first,count,
248				&shape->num_outlines,&shape->sz_outlines,
249				(char **)&shape->outlines,
250				sizeof(XkbOutlineRec),_XkbClearOutline);
251
252    return;
253}
254
255/***====================================================================***/
256
257static void
258_XkbClearShape(char *shape_in)
259{
260XkbShapePtr	shape= (XkbShapePtr)shape_in;
261
262    if (shape->outlines)
263	XkbFreeGeomOutlines(shape,0,shape->num_outlines,True);
264    return;
265}
266
267void
268XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)
269{
270    _XkbFreeGeomNonLeafElems(freeAll,first,count,
271				&geom->num_shapes,&geom->sz_shapes,
272				(char **)&geom->shapes,
273				sizeof(XkbShapeRec),_XkbClearShape);
274    return;
275}
276
277/***====================================================================***/
278
279void
280XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)
281{
282    _XkbFreeGeomLeafElems(freeAll,first,count,
283				&row->num_keys,&row->sz_keys,
284				(char **)&row->keys,
285				sizeof(XkbOverlayKeyRec));
286    return;
287}
288
289/***====================================================================***/
290
291static void
292_XkbClearOverlayRow(char *row_in)
293{
294XkbOverlayRowPtr	row= (XkbOverlayRowPtr)row_in;
295
296    if (row->keys!=NULL)
297	XkbFreeGeomOverlayKeys(row,0,row->num_keys,True);
298    return;
299}
300
301void
302XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll)
303{
304    _XkbFreeGeomNonLeafElems(freeAll,first,count,
305				&overlay->num_rows,&overlay->sz_rows,
306				(char **)&overlay->rows,
307				sizeof(XkbOverlayRowRec),_XkbClearOverlayRow);
308    return;
309}
310
311/***====================================================================***/
312
313static void
314_XkbClearOverlay(char *overlay_in)
315{
316XkbOverlayPtr	overlay= (XkbOverlayPtr)overlay_in;
317
318    if (overlay->rows!=NULL)
319	XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True);
320    return;
321}
322
323void
324XkbFreeGeomOverlays(XkbSectionPtr section,int first,int	count,Bool freeAll)
325{
326    _XkbFreeGeomNonLeafElems(freeAll,first,count,
327				&section->num_overlays,&section->sz_overlays,
328				(char **)&section->overlays,
329				sizeof(XkbOverlayRec),_XkbClearOverlay);
330    return;
331}
332
333/***====================================================================***/
334
335void
336XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)
337{
338    _XkbFreeGeomLeafElems(freeAll,first,count,
339				&row->num_keys,&row->sz_keys,
340				(char **)&row->keys,
341				sizeof(XkbKeyRec));
342    return;
343}
344
345/***====================================================================***/
346
347static void
348_XkbClearRow(char *row_in)
349{
350XkbRowPtr	row= (XkbRowPtr)row_in;
351
352    if (row->keys!=NULL)
353	XkbFreeGeomKeys(row,0,row->num_keys,True);
354    return;
355}
356
357void
358XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)
359{
360    _XkbFreeGeomNonLeafElems(freeAll,first,count,
361				&section->num_rows,&section->sz_rows,
362				(char **)&section->rows,
363				sizeof(XkbRowRec),_XkbClearRow);
364}
365
366/***====================================================================***/
367
368static void
369_XkbClearSection(char *section_in)
370{
371XkbSectionPtr	section= (XkbSectionPtr)section_in;
372
373    if (section->rows!=NULL)
374	XkbFreeGeomRows(section,0,section->num_rows,True);
375    if (section->doodads!=NULL) {
376	XkbFreeGeomDoodads(section->doodads,section->num_doodads,True);
377	section->doodads= NULL;
378    }
379    return;
380}
381
382void
383XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)
384{
385    _XkbFreeGeomNonLeafElems(freeAll,first,count,
386				&geom->num_sections,&geom->sz_sections,
387				(char **)&geom->sections,
388				sizeof(XkbSectionRec),_XkbClearSection);
389    return;
390}
391
392/***====================================================================***/
393
394static void
395_XkbClearDoodad(char *doodad_in)
396{
397XkbDoodadPtr	doodad= (XkbDoodadPtr)doodad_in;
398
399    switch (doodad->any.type) {
400   	case XkbTextDoodad:
401	    {
402		if (doodad->text.text!=NULL) {
403		    _XkbFree(doodad->text.text);
404		    doodad->text.text= NULL;
405		}
406		if (doodad->text.font!=NULL) {
407		    _XkbFree(doodad->text.font);
408		    doodad->text.font= NULL;
409		}
410	    }
411	    break;
412   	case XkbLogoDoodad:
413	    {
414		if (doodad->logo.logo_name!=NULL) {
415		    _XkbFree(doodad->logo.logo_name);
416		    doodad->logo.logo_name= NULL;
417		}
418	    }
419	    break;
420    }
421    return;
422}
423
424void
425XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)
426{
427register int 		i;
428register XkbDoodadPtr	doodad;
429
430    if (doodads) {
431	for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) {
432	    _XkbClearDoodad((char *)doodad);
433	}
434	if (freeAll)
435	    _XkbFree(doodads);
436    }
437    return;
438}
439
440void
441XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)
442{
443    if (geom==NULL)
444	return;
445    if (freeMap)
446	which= XkbGeomAllMask;
447    if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL))
448	XkbFreeGeomProperties(geom,0,geom->num_properties,True);
449    if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL))
450	XkbFreeGeomColors(geom,0,geom->num_colors,True);
451    if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL))
452	XkbFreeGeomShapes(geom,0,geom->num_shapes,True);
453    if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL))
454	XkbFreeGeomSections(geom,0,geom->num_sections,True);
455    if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) {
456	XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True);
457	geom->doodads= NULL;
458	geom->num_doodads= geom->sz_doodads= 0;
459    }
460    if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL))
461	XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True);
462    if (freeMap) {
463	if (geom->label_font!=NULL) {
464	    _XkbFree(geom->label_font);
465	    geom->label_font= NULL;
466	}
467	_XkbFree(geom);
468    }
469    return;
470}
471
472/***====================================================================***/
473
474static Status
475_XkbGeomAlloc(	XPointer *		old,
476		unsigned short *	num,
477		unsigned short *	total,
478		int			num_new,
479		Size_t			sz_elem)
480{
481    if (num_new<1)
482	return Success;
483    if ((*old)==NULL)
484	*num= *total= 0;
485
486    if ((*num)+num_new<=(*total))
487	return Success;
488
489    *total= (*num)+num_new;
490    if ((*old)!=NULL)
491	 (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem);
492    else (*old)= (XPointer)_XkbCalloc((*total),sz_elem);
493    if ((*old)==NULL) {
494	*total= *num= 0;
495	return BadAlloc;
496    }
497
498    if (*num>0) {
499	char *tmp= (char *)(*old);
500	bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem));
501    }
502    return Success;
503}
504
505#define	_XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\
506				&(g)->num_properties,&(g)->sz_properties,\
507				(n),sizeof(XkbPropertyRec))
508#define	_XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\
509				&(g)->num_colors,&(g)->sz_colors,\
510				(n),sizeof(XkbColorRec))
511#define	_XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\
512				&(g)->num_shapes,&(g)->sz_shapes,\
513				(n),sizeof(XkbShapeRec))
514#define	_XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\
515				&(g)->num_sections,&(g)->sz_sections,\
516				(n),sizeof(XkbSectionRec))
517#define	_XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\
518				&(g)->num_doodads,&(g)->sz_doodads,\
519				(n),sizeof(XkbDoodadRec))
520#define	_XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\
521				&(g)->num_key_aliases,&(g)->sz_key_aliases,\
522				(n),sizeof(XkbKeyAliasRec))
523
524#define	_XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\
525				&(s)->num_outlines,&(s)->sz_outlines,\
526				(n),sizeof(XkbOutlineRec))
527#define	_XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\
528				&(s)->num_rows,&(s)->sz_rows,\
529				(n),sizeof(XkbRowRec))
530#define	_XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\
531				&(o)->num_points,&(o)->sz_points,\
532				(n),sizeof(XkbPointRec))
533#define	_XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
534				&(r)->num_keys,&(r)->sz_keys,\
535				(n),sizeof(XkbKeyRec))
536#define	_XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\
537				&(s)->num_overlays,&(s)->sz_overlays,\
538				(n),sizeof(XkbOverlayRec))
539#define	_XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\
540				&(o)->num_rows,&(o)->sz_rows,\
541				(n),sizeof(XkbOverlayRowRec))
542#define	_XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
543				&(r)->num_keys,&(r)->sz_keys,\
544				(n),sizeof(XkbOverlayKeyRec))
545
546Status
547XkbAllocGeomProps(XkbGeometryPtr geom,int nProps)
548{
549    return _XkbAllocProps(geom,nProps);
550}
551
552Status
553XkbAllocGeomColors(XkbGeometryPtr geom,int nColors)
554{
555    return _XkbAllocColors(geom,nColors);
556}
557
558Status
559XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases)
560{
561    return _XkbAllocKeyAliases(geom,nKeyAliases);
562}
563
564Status
565XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes)
566{
567    return _XkbAllocShapes(geom,nShapes);
568}
569
570Status
571XkbAllocGeomSections(XkbGeometryPtr geom,int nSections)
572{
573    return _XkbAllocSections(geom,nSections);
574}
575
576Status
577XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays)
578{
579    return _XkbAllocOverlays(section,nOverlays);
580}
581
582Status
583XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows)
584{
585    return _XkbAllocOverlayRows(overlay,nRows);
586}
587
588Status
589XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys)
590{
591    return _XkbAllocOverlayKeys(row,nKeys);
592}
593
594Status
595XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads)
596{
597    return _XkbAllocDoodads(geom,nDoodads);
598}
599
600Status
601XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads)
602{
603    return _XkbAllocDoodads(section,nDoodads);
604}
605
606Status
607XkbAllocGeomOutlines(XkbShapePtr shape,int nOL)
608{
609    return _XkbAllocOutlines(shape,nOL);
610}
611
612Status
613XkbAllocGeomRows(XkbSectionPtr section,int nRows)
614{
615    return _XkbAllocRows(section,nRows);
616}
617
618Status
619XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts)
620{
621    return _XkbAllocPoints(ol,nPts);
622}
623
624Status
625XkbAllocGeomKeys(XkbRowPtr row,int nKeys)
626{
627    return _XkbAllocKeys(row,nKeys);
628}
629
630Status
631XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)
632{
633XkbGeometryPtr	geom;
634Status		rtrn;
635
636    if (xkb->geom==NULL) {
637	xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec);
638	if (!xkb->geom)
639	    return BadAlloc;
640    }
641    geom= xkb->geom;
642    if ((sizes->which&XkbGeomPropertiesMask)&&
643	((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) {
644	goto BAIL;
645    }
646    if ((sizes->which&XkbGeomColorsMask)&&
647	((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) {
648	goto BAIL;
649    }
650    if ((sizes->which&XkbGeomShapesMask)&&
651	((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) {
652	goto BAIL;
653    }
654    if ((sizes->which&XkbGeomSectionsMask)&&
655	((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) {
656	goto BAIL;
657    }
658    if ((sizes->which&XkbGeomDoodadsMask)&&
659	((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) {
660	goto BAIL;
661    }
662    if ((sizes->which&XkbGeomKeyAliasesMask)&&
663	((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) {
664	goto BAIL;
665    }
666    return Success;
667BAIL:
668    XkbFreeGeometry(geom,XkbGeomAllMask,True);
669    xkb->geom= NULL;
670    return rtrn;
671}
672
673/***====================================================================***/
674
675XkbPropertyPtr
676XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value)
677{
678register int i;
679register XkbPropertyPtr prop;
680
681    if ((!geom)||(!name)||(!value))
682	return NULL;
683    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
684	if ((prop->name)&&(strcmp(name,prop->name)==0)) {
685	    if (prop->value)
686		_XkbFree(prop->value);
687	    prop->value= (char *)_XkbAlloc(strlen(value)+1);
688	    if (prop->value)
689		strcpy(prop->value,value);
690	    return prop;
691	}
692    }
693    if ((geom->num_properties>=geom->sz_properties)&&
694					(_XkbAllocProps(geom,1)!=Success)) {
695	return NULL;
696    }
697    prop= &geom->properties[geom->num_properties];
698    prop->name= (char *)_XkbAlloc(strlen(name)+1);
699    if (!name)
700	return NULL;
701    strcpy(prop->name,name);
702    prop->value= (char *)_XkbAlloc(strlen(value)+1);
703    if (!value) {
704	_XkbFree(prop->name);
705	prop->name= NULL;
706	return NULL;
707    }
708    strcpy(prop->value,value);
709    geom->num_properties++;
710    return prop;
711}
712
713XkbKeyAliasPtr
714XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
715{
716register int i;
717register XkbKeyAliasPtr alias;
718
719    if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
720	return NULL;
721    for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
722	if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
723	    bzero(alias->real,XkbKeyNameLength);
724	    strncpy(alias->real,realStr,XkbKeyNameLength);
725	    return alias;
726	}
727    }
728    if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
729				(_XkbAllocKeyAliases(geom,1)!=Success)) {
730	return NULL;
731    }
732    alias= &geom->key_aliases[geom->num_key_aliases];
733    bzero(alias,sizeof(XkbKeyAliasRec));
734    strncpy(alias->alias,aliasStr,XkbKeyNameLength);
735    strncpy(alias->real,realStr,XkbKeyNameLength);
736    geom->num_key_aliases++;
737    return alias;
738}
739
740XkbColorPtr
741XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
742{
743register int i;
744register XkbColorPtr color;
745
746    if ((!geom)||(!spec))
747	return NULL;
748    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
749	if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
750	    color->pixel= pixel;
751	    return color;
752	}
753    }
754    if ((geom->num_colors>=geom->sz_colors)&&
755					(_XkbAllocColors(geom,1)!=Success)) {
756	return NULL;
757    }
758    color= &geom->colors[geom->num_colors];
759    color->pixel= pixel;
760    color->spec= (char *)_XkbAlloc(strlen(spec)+1);
761    if (!color->spec)
762	return NULL;
763    strcpy(color->spec,spec);
764    geom->num_colors++;
765    return color;
766}
767
768XkbOutlinePtr
769XkbAddGeomOutline(XkbShapePtr shape,int sz_points)
770{
771XkbOutlinePtr	outline;
772
773    if ((!shape)||(sz_points<0))
774	return NULL;
775    if ((shape->num_outlines>=shape->sz_outlines)&&
776					(_XkbAllocOutlines(shape,1)!=Success)) {
777	return NULL;
778    }
779    outline= &shape->outlines[shape->num_outlines];
780    bzero(outline,sizeof(XkbOutlineRec));
781    if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
782	return NULL;
783    shape->num_outlines++;
784    return outline;
785}
786
787XkbShapePtr
788XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
789{
790XkbShapePtr	shape;
791register int	i;
792
793    if ((!geom)||(!name)||(sz_outlines<0))
794	return NULL;
795    if (geom->num_shapes>0) {
796	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
797	    if (name==shape->name)
798		return shape;
799	}
800    }
801    if ((geom->num_shapes>=geom->sz_shapes)&&
802					(_XkbAllocShapes(geom,1)!=Success))
803	return NULL;
804    shape= &geom->shapes[geom->num_shapes];
805    bzero(shape,sizeof(XkbShapeRec));
806    if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
807	return NULL;
808    shape->name= name;
809    shape->primary= shape->approx= NULL;
810    geom->num_shapes++;
811    return shape;
812}
813
814XkbKeyPtr
815XkbAddGeomKey(XkbRowPtr row)
816{
817XkbKeyPtr	key;
818    if (!row)
819	return NULL;
820    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
821	return NULL;
822    key= &row->keys[row->num_keys++];
823    bzero(key,sizeof(XkbKeyRec));
824    return key;
825}
826
827XkbRowPtr
828XkbAddGeomRow(XkbSectionPtr section,int sz_keys)
829{
830XkbRowPtr	row;
831
832    if ((!section)||(sz_keys<0))
833	return NULL;
834    if ((section->num_rows>=section->sz_rows)&&
835    					(_XkbAllocRows(section,1)!=Success))
836	return NULL;
837    row= &section->rows[section->num_rows];
838    bzero(row,sizeof(XkbRowRec));
839    if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
840	return NULL;
841    section->num_rows++;
842    return row;
843}
844
845XkbSectionPtr
846XkbAddGeomSection(	XkbGeometryPtr	geom,
847			Atom		name,
848			int		sz_rows,
849			int		sz_doodads,
850			int		sz_over)
851{
852register int	i;
853XkbSectionPtr	section;
854
855    if ((!geom)||(name==None)||(sz_rows<0))
856	return NULL;
857    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
858	if (section->name!=name)
859	    continue;
860	if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
861	    ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
862	    ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
863	    return NULL;
864	return section;
865    }
866    if ((geom->num_sections>=geom->sz_sections)&&
867					(_XkbAllocSections(geom,1)!=Success))
868	return NULL;
869    section= &geom->sections[geom->num_sections];
870    if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
871	return NULL;
872    if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
873	if (section->rows) {
874	    _XkbFree(section->rows);
875	    section->rows= NULL;
876	    section->sz_rows= section->num_rows= 0;
877	}
878	return NULL;
879    }
880    section->name= name;
881    geom->num_sections++;
882    return section;
883}
884
885XkbDoodadPtr
886XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
887{
888XkbDoodadPtr	old,doodad;
889register int	i,nDoodads;
890
891    if ((!geom)||(name==None))
892	return NULL;
893    if ((section!=NULL)&&(section->num_doodads>0)) {
894	old= section->doodads;
895	nDoodads= section->num_doodads;
896    }
897    else {
898	old= geom->doodads;
899	nDoodads= geom->num_doodads;
900    }
901    for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
902	if (doodad->any.name==name)
903	    return doodad;
904    }
905    if (section) {
906	if ((section->num_doodads>=geom->sz_doodads)&&
907	    (_XkbAllocDoodads(section,1)!=Success)) {
908	    return NULL;
909	}
910	doodad= &section->doodads[section->num_doodads++];
911    }
912    else {
913	if ((geom->num_doodads>=geom->sz_doodads)&&
914					(_XkbAllocDoodads(geom,1)!=Success))
915	    return NULL;
916	doodad= &geom->doodads[geom->num_doodads++];
917    }
918    bzero(doodad,sizeof(XkbDoodadRec));
919    doodad->any.name= name;
920    return doodad;
921}
922
923XkbOverlayKeyPtr
924XkbAddGeomOverlayKey(	XkbOverlayPtr		overlay,
925			XkbOverlayRowPtr 	row,
926			char *			over,
927			char *			under)
928{
929register int	i;
930XkbOverlayKeyPtr key;
931XkbSectionPtr	section;
932XkbRowPtr	row_under;
933Bool		found;
934
935    if ((!overlay)||(!row)||(!over)||(!under))
936	return NULL;
937    section= overlay->section_under;
938    if (row->row_under>=section->num_rows)
939	return NULL;
940    row_under= &section->rows[row->row_under];
941    for (i=0,found=False;i<row_under->num_keys;i++) {
942	if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
943	    found= True;
944	    break;
945	}
946    }
947    if (!found)
948   	return NULL;
949    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
950	return NULL;
951    key= &row->keys[row->num_keys];
952    strncpy(key->under.name,under,XkbKeyNameLength);
953    strncpy(key->over.name,over,XkbKeyNameLength);
954    row->num_keys++;
955    return key;
956}
957
958XkbOverlayRowPtr
959XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
960{
961register int		i;
962XkbOverlayRowPtr	row;
963
964    if ((!overlay)||(sz_keys<0))
965	return NULL;
966    if (row_under>=overlay->section_under->num_rows)
967	return NULL;
968    for (i=0;i<overlay->num_rows;i++) {
969	if (overlay->rows[i].row_under==row_under) {
970	    row= &overlay->rows[i];
971	    if ((row->sz_keys<sz_keys)&&
972				(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
973		return NULL;
974	    }
975	    return &overlay->rows[i];
976	}
977    }
978    if ((overlay->num_rows>=overlay->sz_rows)&&
979				(_XkbAllocOverlayRows(overlay,1)!=Success))
980	return NULL;
981    row= &overlay->rows[overlay->num_rows];
982    bzero(row,sizeof(XkbOverlayRowRec));
983    if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
984	return NULL;
985    row->row_under= row_under;
986    overlay->num_rows++;
987    return row;
988}
989
990XkbOverlayPtr
991XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
992{
993register int	i;
994XkbOverlayPtr	overlay;
995
996    if ((!section)||(name==None)||(sz_rows==0))
997	return NULL;
998
999    for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
1000	if (overlay->name==name) {
1001	    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
1002		return NULL;
1003	    return overlay;
1004	}
1005    }
1006    if ((section->num_overlays>=section->sz_overlays)&&
1007				(_XkbAllocOverlays(section,1)!=Success))
1008	return NULL;
1009    overlay= &section->overlays[section->num_overlays];
1010    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
1011	return NULL;
1012    overlay->name= name;
1013    overlay->section_under= section;
1014    section->num_overlays++;
1015    return overlay;
1016}
1017