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