XKBGAlloc.c revision 6cc2b21f
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= strdup(value);
688	    return prop;
689	}
690    }
691    if ((geom->num_properties>=geom->sz_properties)&&
692					(_XkbAllocProps(geom,1)!=Success)) {
693	return NULL;
694    }
695    prop= &geom->properties[geom->num_properties];
696    prop->name= strdup(name);
697    if (!prop->name)
698	return NULL;
699    prop->value= strdup(value);
700    if (!prop->value) {
701	_XkbFree(prop->name);
702	prop->name= NULL;
703	return NULL;
704    }
705    geom->num_properties++;
706    return prop;
707}
708
709XkbKeyAliasPtr
710XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
711{
712register int i;
713register XkbKeyAliasPtr alias;
714
715    if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
716	return NULL;
717    for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
718	if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
719	    bzero(alias->real,XkbKeyNameLength);
720	    strncpy(alias->real,realStr,XkbKeyNameLength);
721	    return alias;
722	}
723    }
724    if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
725				(_XkbAllocKeyAliases(geom,1)!=Success)) {
726	return NULL;
727    }
728    alias= &geom->key_aliases[geom->num_key_aliases];
729    bzero(alias,sizeof(XkbKeyAliasRec));
730    strncpy(alias->alias,aliasStr,XkbKeyNameLength);
731    strncpy(alias->real,realStr,XkbKeyNameLength);
732    geom->num_key_aliases++;
733    return alias;
734}
735
736XkbColorPtr
737XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
738{
739register int i;
740register XkbColorPtr color;
741
742    if ((!geom)||(!spec))
743	return NULL;
744    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
745	if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
746	    color->pixel= pixel;
747	    return color;
748	}
749    }
750    if ((geom->num_colors>=geom->sz_colors)&&
751					(_XkbAllocColors(geom,1)!=Success)) {
752	return NULL;
753    }
754    color= &geom->colors[geom->num_colors];
755    color->pixel= pixel;
756    color->spec= strdup(spec);
757    if (!color->spec)
758	return NULL;
759    geom->num_colors++;
760    return color;
761}
762
763XkbOutlinePtr
764XkbAddGeomOutline(XkbShapePtr shape,int sz_points)
765{
766XkbOutlinePtr	outline;
767
768    if ((!shape)||(sz_points<0))
769	return NULL;
770    if ((shape->num_outlines>=shape->sz_outlines)&&
771					(_XkbAllocOutlines(shape,1)!=Success)) {
772	return NULL;
773    }
774    outline= &shape->outlines[shape->num_outlines];
775    bzero(outline,sizeof(XkbOutlineRec));
776    if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
777	return NULL;
778    shape->num_outlines++;
779    return outline;
780}
781
782XkbShapePtr
783XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
784{
785XkbShapePtr	shape;
786register int	i;
787
788    if ((!geom)||(!name)||(sz_outlines<0))
789	return NULL;
790    if (geom->num_shapes>0) {
791	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
792	    if (name==shape->name)
793		return shape;
794	}
795    }
796    if ((geom->num_shapes>=geom->sz_shapes)&&
797					(_XkbAllocShapes(geom,1)!=Success))
798	return NULL;
799    shape= &geom->shapes[geom->num_shapes];
800    bzero(shape,sizeof(XkbShapeRec));
801    if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
802	return NULL;
803    shape->name= name;
804    shape->primary= shape->approx= NULL;
805    geom->num_shapes++;
806    return shape;
807}
808
809XkbKeyPtr
810XkbAddGeomKey(XkbRowPtr row)
811{
812XkbKeyPtr	key;
813    if (!row)
814	return NULL;
815    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
816	return NULL;
817    key= &row->keys[row->num_keys++];
818    bzero(key,sizeof(XkbKeyRec));
819    return key;
820}
821
822XkbRowPtr
823XkbAddGeomRow(XkbSectionPtr section,int sz_keys)
824{
825XkbRowPtr	row;
826
827    if ((!section)||(sz_keys<0))
828	return NULL;
829    if ((section->num_rows>=section->sz_rows)&&
830    					(_XkbAllocRows(section,1)!=Success))
831	return NULL;
832    row= &section->rows[section->num_rows];
833    bzero(row,sizeof(XkbRowRec));
834    if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
835	return NULL;
836    section->num_rows++;
837    return row;
838}
839
840XkbSectionPtr
841XkbAddGeomSection(	XkbGeometryPtr	geom,
842			Atom		name,
843			int		sz_rows,
844			int		sz_doodads,
845			int		sz_over)
846{
847register int	i;
848XkbSectionPtr	section;
849
850    if ((!geom)||(name==None)||(sz_rows<0))
851	return NULL;
852    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
853	if (section->name!=name)
854	    continue;
855	if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
856	    ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
857	    ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
858	    return NULL;
859	return section;
860    }
861    if ((geom->num_sections>=geom->sz_sections)&&
862					(_XkbAllocSections(geom,1)!=Success))
863	return NULL;
864    section= &geom->sections[geom->num_sections];
865    if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
866	return NULL;
867    if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
868	if (section->rows) {
869	    _XkbFree(section->rows);
870	    section->rows= NULL;
871	    section->sz_rows= section->num_rows= 0;
872	}
873	return NULL;
874    }
875    section->name= name;
876    geom->num_sections++;
877    return section;
878}
879
880XkbDoodadPtr
881XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
882{
883XkbDoodadPtr	old,doodad;
884register int	i,nDoodads;
885
886    if ((!geom)||(name==None))
887	return NULL;
888    if ((section!=NULL)&&(section->num_doodads>0)) {
889	old= section->doodads;
890	nDoodads= section->num_doodads;
891    }
892    else {
893	old= geom->doodads;
894	nDoodads= geom->num_doodads;
895    }
896    for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
897	if (doodad->any.name==name)
898	    return doodad;
899    }
900    if (section) {
901	if ((section->num_doodads>=geom->sz_doodads)&&
902	    (_XkbAllocDoodads(section,1)!=Success)) {
903	    return NULL;
904	}
905	doodad= &section->doodads[section->num_doodads++];
906    }
907    else {
908	if ((geom->num_doodads>=geom->sz_doodads)&&
909					(_XkbAllocDoodads(geom,1)!=Success))
910	    return NULL;
911	doodad= &geom->doodads[geom->num_doodads++];
912    }
913    bzero(doodad,sizeof(XkbDoodadRec));
914    doodad->any.name= name;
915    return doodad;
916}
917
918XkbOverlayKeyPtr
919XkbAddGeomOverlayKey(	XkbOverlayPtr		overlay,
920			XkbOverlayRowPtr 	row,
921			char *			over,
922			char *			under)
923{
924register int	i;
925XkbOverlayKeyPtr key;
926XkbSectionPtr	section;
927XkbRowPtr	row_under;
928Bool		found;
929
930    if ((!overlay)||(!row)||(!over)||(!under))
931	return NULL;
932    section= overlay->section_under;
933    if (row->row_under>=section->num_rows)
934	return NULL;
935    row_under= &section->rows[row->row_under];
936    for (i=0,found=False;i<row_under->num_keys;i++) {
937	if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
938	    found= True;
939	    break;
940	}
941    }
942    if (!found)
943   	return NULL;
944    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
945	return NULL;
946    key= &row->keys[row->num_keys];
947    strncpy(key->under.name,under,XkbKeyNameLength);
948    strncpy(key->over.name,over,XkbKeyNameLength);
949    row->num_keys++;
950    return key;
951}
952
953XkbOverlayRowPtr
954XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
955{
956register int		i;
957XkbOverlayRowPtr	row;
958
959    if ((!overlay)||(sz_keys<0))
960	return NULL;
961    if (row_under>=overlay->section_under->num_rows)
962	return NULL;
963    for (i=0;i<overlay->num_rows;i++) {
964	if (overlay->rows[i].row_under==row_under) {
965	    row= &overlay->rows[i];
966	    if ((row->sz_keys<sz_keys)&&
967				(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
968		return NULL;
969	    }
970	    return &overlay->rows[i];
971	}
972    }
973    if ((overlay->num_rows>=overlay->sz_rows)&&
974				(_XkbAllocOverlayRows(overlay,1)!=Success))
975	return NULL;
976    row= &overlay->rows[overlay->num_rows];
977    bzero(row,sizeof(XkbOverlayRowRec));
978    if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
979	return NULL;
980    row->row_under= row_under;
981    overlay->num_rows++;
982    return row;
983}
984
985XkbOverlayPtr
986XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
987{
988register int	i;
989XkbOverlayPtr	overlay;
990
991    if ((!section)||(name==None)||(sz_rows==0))
992	return NULL;
993
994    for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
995	if (overlay->name==name) {
996	    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
997		return NULL;
998	    return overlay;
999	}
1000    }
1001    if ((section->num_overlays>=section->sz_overlays)&&
1002				(_XkbAllocOverlays(section,1)!=Success))
1003	return NULL;
1004    overlay= &section->overlays[section->num_overlays];
1005    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
1006	return NULL;
1007    overlay->name= name;
1008    overlay->section_under= section;
1009    section->num_overlays++;
1010    return overlay;
1011}
1012