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