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