88d11b46a6bd295ed64f03cc852e36ca757f4ab5
[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 "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             free(*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             free(*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     struct xkb_property * prop = (struct xkb_property *)prop_in;
119
120     if (prop->name) {
121         free(prop->name);
122         prop->name = NULL;
123     }
124     if (prop->value) {
125         free(prop->value);
126         prop->value = NULL;
127     }
128 }
129
130 void
131 XkbcFreeGeomProperties(struct xkb_geometry * 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(struct xkb_property),
137                              _XkbClearProperty);
138 }
139
140 void
141 XkbcFreeGeomKeyAliases(struct xkb_geometry * 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(struct xkb_key_alias));
147 }
148
149 static void
150 _XkbClearColor(char *color_in)
151 {
152     struct xkb_color * color = (struct xkb_color *)color_in;
153
154     if (color->spec)
155         free(color->spec);
156 }
157
158 void
159 XkbcFreeGeomColors(struct xkb_geometry * 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(struct xkb_color),
164                              _XkbClearColor);
165 }
166
167 void
168 XkbcFreeGeomPoints(struct xkb_outline * 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(struct xkb_point));
173 }
174
175 static void
176 _XkbClearOutline(char *outline_in)
177 {
178     struct xkb_outline * outline = (struct xkb_outline *)outline_in;
179
180     if (outline->points)
181         XkbcFreeGeomPoints(outline, 0, outline->num_points, True);
182 }
183
184 void
185 XkbcFreeGeomOutlines(struct xkb_shape * 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(struct xkb_outline),
190                              _XkbClearOutline);
191 }
192
193 static void
194 _XkbClearShape(char *shape_in)
195 {
196     struct xkb_shape * shape = (struct xkb_shape *)shape_in;
197
198     if (shape->outlines)
199         XkbcFreeGeomOutlines(shape, 0, shape->num_outlines, True);
200 }
201
202 void
203 XkbcFreeGeomShapes(struct xkb_geometry * 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(struct xkb_shape),
208                              _XkbClearShape);
209 }
210
211 void
212 XkbcFreeGeomOverlayKeys(struct xkb_overlay_row * 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(struct xkb_overlay_key));
218 }
219
220
221 static void
222 _XkbClearOverlayRow(char *row_in)
223 {
224     struct xkb_overlay_row * row = (struct xkb_overlay_row *)row_in;
225
226     if (row->keys)
227         XkbcFreeGeomOverlayKeys(row, 0, row->num_keys, True);
228 }
229
230 void
231 XkbcFreeGeomOverlayRows(struct xkb_overlay * 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(struct xkb_overlay_row),
238                              _XkbClearOverlayRow);
239 }
240
241
242 static void
243 _XkbClearOverlay(char *overlay_in)
244 {
245     struct xkb_overlay * overlay = (struct xkb_overlay *)overlay_in;
246
247     if (overlay->rows)
248         XkbcFreeGeomOverlayRows(overlay, 0, overlay->num_rows, True);
249 }
250
251 void
252 XkbcFreeGeomOverlays(struct xkb_section * 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(struct xkb_overlay),
258                              _XkbClearOverlay);
259 }
260
261
262 void
263 XkbcFreeGeomKeys(struct xkb_row * 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(struct xkb_key));
268 }
269
270
271 static void
272 _XkbClearRow(char *row_in)
273 {
274     struct xkb_row * row = (struct xkb_row *)row_in;
275
276     if (row->keys)
277         XkbcFreeGeomKeys(row, 0, row->num_keys, True);
278 }
279
280 void
281 XkbcFreeGeomRows(struct xkb_section * 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(struct xkb_row),
286                              _XkbClearRow);
287 }
288
289
290 static void
291 _XkbClearSection(char *section_in)
292 {
293     struct xkb_section * section = (struct xkb_section *)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(struct xkb_geometry * 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(struct xkb_section),
309                              _XkbClearSection);
310 }
311
312
313 static void
314 _XkbClearDoodad(char *doodad_in)
315 {
316     union xkb_doodad * doodad = (union xkb_doodad *)doodad_in;
317
318     switch (doodad->any.type) {
319     case XkbTextDoodad:
320         if (doodad->text.text) {
321             free(doodad->text.text);
322             doodad->text.text = NULL;
323         }
324         if (doodad->text.font) {
325             free(doodad->text.font);
326             doodad->text.font = NULL;
327         }
328         break;
329
330     case XkbLogoDoodad:
331         if (doodad->logo.logo_name) {
332             free(doodad->logo.logo_name);
333             doodad->logo.logo_name = NULL;
334         }
335         break;
336     }
337 }
338
339 void
340 XkbcFreeGeomDoodads(union xkb_doodad * doodads, int nDoodads, Bool freeAll)
341 {
342     int i;
343     union xkb_doodad * doodad;
344
345     if (doodads) {
346         for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++)
347             _XkbClearDoodad((char *)doodad);
348         if (freeAll)
349             free(doodads);
350     }
351 }
352
353 void
354 XkbcFreeGeometry(struct xkb_geometry * 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             free(geom->label_font);
386             geom->label_font = NULL;
387         }
388         free(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 *)realloc(*old, (*total) * sz_elem);
409     else
410         *old = (char *)calloc(*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(struct xkb_property))
428 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
429                                               &(g)->num_colors, \
430                                               &(g)->sz_colors, \
431                                               (n), sizeof(struct xkb_color))
432 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
433                                               &(g)->num_shapes, \
434                                               &(g)->sz_shapes, \
435                                               (n), sizeof(struct xkb_shape))
436 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
437                                               &(g)->num_sections, \
438                                               &(g)->sz_sections, \
439                                               (n), sizeof(struct xkb_section))
440 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
441                                               &(g)->num_doodads, \
442                                               &(g)->sz_doodads, \
443                                               (n), sizeof(union xkb_doodad))
444 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
445                                                   &(g)->num_key_aliases, \
446                                                   &(g)->sz_key_aliases, \
447                                                   (n), sizeof(struct xkb_key_alias))
448
449 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
450                                               &(s)->num_outlines, \
451                                               &(s)->sz_outlines, \
452                                               (n), sizeof(struct xkb_outline))
453 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
454                                               &(s)->num_rows, \
455                                               &(s)->sz_rows, \
456                                               (n), sizeof(struct xkb_row))
457 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
458                                               &(o)->num_points, \
459                                               &(o)->sz_points, \
460                                               (n), sizeof(struct xkb_point))
461 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
462                                               &(r)->num_keys, \
463                                               &(r)->sz_keys, \
464                                               (n), sizeof(struct xkb_key))
465 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
466                                               &(s)->num_overlays, \
467                                               &(s)->sz_overlays, \
468                                               (n), sizeof(struct xkb_overlay))
469 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
470                                                   &(o)->num_rows, \
471                                                   &(o)->sz_rows, \
472                                                   (n), sizeof(struct xkb_overlay_row))
473 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
474                                                   &(r)->num_keys, \
475                                                   &(r)->sz_keys, \
476                                                   (n), sizeof(struct xkb_overlay_key))
477
478 int
479 XkbcAllocGeomProps(struct xkb_geometry * geom, int nProps)
480 {
481     return _XkbAllocProps(geom, nProps);
482 }
483
484 int
485 XkbcAllocGeomColors(struct xkb_geometry * geom, int nColors)
486 {
487     return _XkbAllocColors(geom, nColors);
488 }
489
490 int
491 XkbcAllocGeomKeyAliases(struct xkb_geometry * geom, int nKeyAliases)
492 {
493     return _XkbAllocKeyAliases(geom, nKeyAliases);
494 }
495
496 int
497 XkbcAllocGeomShapes(struct xkb_geometry * geom, int nShapes)
498 {
499     return _XkbAllocShapes(geom, nShapes);
500 }
501
502 int
503 XkbcAllocGeomSections(struct xkb_geometry * geom, int nSections)
504 {
505     return _XkbAllocSections(geom, nSections);
506 }
507
508 int
509 XkbcAllocGeomOverlays(struct xkb_section * section, int nOverlays)
510 {
511     return _XkbAllocOverlays(section, nOverlays);
512 }
513
514 int
515 XkbcAllocGeomOverlayRows(struct xkb_overlay * overlay, int nRows)
516 {
517     return _XkbAllocOverlayRows(overlay, nRows);
518 }
519
520 int
521 XkbcAllocGeomOverlayKeys(struct xkb_overlay_row * row, int nKeys)
522 {
523     return _XkbAllocOverlayKeys(row, nKeys);
524 }
525
526 int
527 XkbcAllocGeomDoodads(struct xkb_geometry * geom, int nDoodads)
528 {
529     return _XkbAllocDoodads(geom, nDoodads);
530 }
531
532 int
533 XkbcAllocGeomSectionDoodads(struct xkb_section * section, int nDoodads)
534 {
535     return _XkbAllocDoodads(section, nDoodads);
536 }
537
538 int
539 XkbcAllocGeomOutlines(struct xkb_shape * shape, int nOL)
540 {
541     return _XkbAllocOutlines(shape, nOL);
542 }
543
544 int
545 XkbcAllocGeomRows(struct xkb_section * section, int nRows)
546 {
547     return _XkbAllocRows(section, nRows);
548 }
549
550 int
551 XkbcAllocGeomPoints(struct xkb_outline * ol, int nPts)
552 {
553     return _XkbAllocPoints(ol, nPts);
554 }
555
556 int
557 XkbcAllocGeomKeys(struct xkb_row * row, int nKeys)
558 {
559     int ret = _XkbAllocKeys(row, nKeys);
560     fprintf(stderr, "!!! allocated %d keys at %p\n", nKeys, row->keys);
561     return ret;
562 }
563
564 int
565 XkbcAllocGeometry(struct xkb_desc * xkb, struct xkb_geometry_sizes * sizes)
566 {
567     struct xkb_geometry * geom;
568     int rtrn;
569
570     if (!xkb->geom) {
571         xkb->geom = _XkbTypedCalloc(1, struct xkb_geometry);
572         if (!xkb->geom)
573             return BadAlloc;
574     }
575     geom = xkb->geom;
576
577     if ((sizes->which & XkbGeomPropertiesMask) &&
578         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
579         goto bail;
580
581     if ((sizes->which & XkbGeomColorsMask) &&
582         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
583         goto bail;
584
585     if ((sizes->which & XkbGeomShapesMask) &&
586         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
587         goto bail;
588
589     if ((sizes->which & XkbGeomSectionsMask) &&
590         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
591         goto bail;
592
593     if ((sizes->which & XkbGeomDoodadsMask) &&
594         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
595         goto bail;
596
597     if ((sizes->which & XkbGeomKeyAliasesMask) &&
598         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
599         goto bail;
600
601     return Success;
602 bail:
603     XkbcFreeGeometry(geom, XkbGeomAllMask, True);
604     xkb->geom = NULL;
605     return rtrn;
606 }
607
608 struct xkb_property *
609 XkbcAddGeomProperty(struct xkb_geometry * geom,const char *name,const char *value)
610 {
611 register int i;
612 register struct xkb_property * prop;
613
614     if ((!geom)||(!name)||(!value))
615         return NULL;
616     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
617         if ((prop->name)&&(strcmp(name,prop->name)==0)) {
618             if (prop->value)
619                 free(prop->value);
620             prop->value= (char *)malloc(strlen(value)+1);
621             if (prop->value)
622                 strcpy(prop->value,value);
623             return prop;
624         }
625     }
626     if ((geom->num_properties>=geom->sz_properties)&&
627                                         (_XkbAllocProps(geom,1)!=Success)) {
628         return NULL;
629     }
630     prop= &geom->properties[geom->num_properties];
631     prop->name= (char *)malloc(strlen(name)+1);
632     if (!name)
633         return NULL;
634     strcpy(prop->name,name);
635     prop->value= (char *)malloc(strlen(value)+1);
636     if (!value) {
637         free(prop->name);
638         prop->name= NULL;
639         return NULL;
640     }
641     strcpy(prop->value,value);
642     geom->num_properties++;
643     return prop;
644 }
645
646 struct xkb_key_alias *
647 XkbcAddGeomKeyAlias(struct xkb_geometry * geom,const char *aliasStr,const char *realStr)
648 {
649 register int i;
650 register struct xkb_key_alias * alias;
651
652     if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
653         return NULL;
654     for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
655         if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
656             bzero(alias->real,XkbKeyNameLength);
657             strncpy(alias->real,realStr,XkbKeyNameLength);
658             return alias;
659         }
660     }
661     if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
662                                 (_XkbAllocKeyAliases(geom,1)!=Success)) {
663         return NULL;
664     }
665     alias= &geom->key_aliases[geom->num_key_aliases];
666     bzero(alias,sizeof(struct xkb_key_alias));
667     strncpy(alias->alias,aliasStr,XkbKeyNameLength);
668     strncpy(alias->real,realStr,XkbKeyNameLength);
669     geom->num_key_aliases++;
670     return alias;
671 }
672
673 struct xkb_color *
674 XkbcAddGeomColor(struct xkb_geometry * geom,const char *spec,unsigned int pixel)
675 {
676 register int i;
677 register struct xkb_color * color;
678
679     if ((!geom)||(!spec))
680         return NULL;
681     for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
682         if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
683             color->pixel= pixel;
684             return color;
685         }
686     }
687     if ((geom->num_colors>=geom->sz_colors)&&
688                                         (_XkbAllocColors(geom,1)!=Success)) {
689         return NULL;
690     }
691     color= &geom->colors[geom->num_colors];
692     color->pixel= pixel;
693     color->spec= (char *)malloc(strlen(spec)+1);
694     if (!color->spec)
695         return NULL;
696     strcpy(color->spec,spec);
697     geom->num_colors++;
698     return color;
699 }
700
701 struct xkb_outline *
702 XkbcAddGeomOutline(struct xkb_shape * shape,int sz_points)
703 {
704 struct xkb_outline *    outline;
705
706     if ((!shape)||(sz_points<0))
707         return NULL;
708     if ((shape->num_outlines>=shape->sz_outlines)&&
709                                         (_XkbAllocOutlines(shape,1)!=Success)) {
710         return NULL;
711     }
712     outline= &shape->outlines[shape->num_outlines];
713     bzero(outline,sizeof(struct xkb_outline));
714     if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
715         return NULL;
716     shape->num_outlines++;
717     return outline;
718 }
719
720 struct xkb_shape *
721 XkbcAddGeomShape(struct xkb_geometry * geom,uint32_t name,int sz_outlines)
722 {
723 struct xkb_shape *      shape;
724 register int    i;
725
726     if ((!geom)||(!name)||(sz_outlines<0))
727         return NULL;
728     if (geom->num_shapes>0) {
729         for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
730             if (name==shape->name)
731                 return shape;
732         }
733     }
734     if ((geom->num_shapes>=geom->sz_shapes)&&
735                                         (_XkbAllocShapes(geom,1)!=Success))
736         return NULL;
737     shape= &geom->shapes[geom->num_shapes];
738     bzero(shape,sizeof(struct xkb_shape));
739     if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
740         return NULL;
741     shape->name= name;
742     shape->primary= shape->approx= NULL;
743     geom->num_shapes++;
744     return shape;
745 }
746
747 struct xkb_key *
748 XkbcAddGeomKey(struct xkb_row * row)
749 {
750 struct xkb_key *        key;
751     if (!row)
752         return NULL;
753     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
754         return NULL;
755     key= &row->keys[row->num_keys++];
756     bzero(key,sizeof(struct xkb_key));
757     return key;
758 }
759
760 struct xkb_row *
761 XkbcAddGeomRow(struct xkb_section * section,int sz_keys)
762 {
763 struct xkb_row *        row;
764
765     if ((!section)||(sz_keys<0))
766         return NULL;
767     if ((section->num_rows>=section->sz_rows)&&
768                                         (_XkbAllocRows(section,1)!=Success))
769         return NULL;
770     row= &section->rows[section->num_rows];
771     bzero(row,sizeof(struct xkb_row));
772     if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
773         return NULL;
774     section->num_rows++;
775     return row;
776 }
777
778 struct xkb_section *
779 XkbcAddGeomSection(     struct xkb_geometry *   geom,
780                         uint32_t                name,
781                         int             sz_rows,
782                         int             sz_doodads,
783                         int             sz_over)
784 {
785 register int    i;
786 struct xkb_section *    section;
787
788     if ((!geom)||(name==None)||(sz_rows<0))
789         return NULL;
790     for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
791         if (section->name!=name)
792             continue;
793         if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
794             ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
795             ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
796             return NULL;
797         return section;
798     }
799     if ((geom->num_sections>=geom->sz_sections)&&
800                                         (_XkbAllocSections(geom,1)!=Success))
801         return NULL;
802     section= &geom->sections[geom->num_sections];
803     if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
804         return NULL;
805     if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
806         if (section->rows) {
807             free(section->rows);
808             section->rows= NULL;
809             section->sz_rows= section->num_rows= 0;
810         }
811         return NULL;
812     }
813     section->name= name;
814     geom->num_sections++;
815     return section;
816 }
817
818 union xkb_doodad *
819 XkbcAddGeomDoodad(struct xkb_geometry * geom,struct xkb_section * section,uint32_t name)
820 {
821 union xkb_doodad *old, *doodad;
822 register int    i,nDoodads;
823
824     if ((!geom)||(name==None))
825         return NULL;
826     if ((section!=NULL)&&(section->num_doodads>0)) {
827         old= section->doodads;
828         nDoodads= section->num_doodads;
829     }
830     else {
831         old= geom->doodads;
832         nDoodads= geom->num_doodads;
833     }
834     for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
835         if (doodad->any.name==name)
836             return doodad;
837     }
838     if (section) {
839         if ((section->num_doodads>=geom->sz_doodads)&&
840             (_XkbAllocDoodads(section,1)!=Success)) {
841             return NULL;
842         }
843         doodad= &section->doodads[section->num_doodads++];
844     }
845     else {
846         if ((geom->num_doodads>=geom->sz_doodads)&&
847                                         (_XkbAllocDoodads(geom,1)!=Success))
848             return NULL;
849         doodad= &geom->doodads[geom->num_doodads++];
850     }
851     bzero(doodad,sizeof(union xkb_doodad));
852     doodad->any.name= name;
853     return doodad;
854 }
855
856 struct xkb_overlay_key *
857 XkbcAddGeomOverlayKey(  struct xkb_overlay *            overlay,
858                         struct xkb_overlay_row *        row,
859                         const char *            over,
860                         const char *            under)
861 {
862 register int    i;
863 struct xkb_overlay_key * key;
864 struct xkb_section *    section;
865 struct xkb_row *        row_under;
866 Bool            found;
867
868     if ((!overlay)||(!row)||(!over)||(!under))
869         return NULL;
870     section= overlay->section_under;
871     if (row->row_under>=section->num_rows)
872         return NULL;
873     row_under= &section->rows[row->row_under];
874     for (i=0,found=False;i<row_under->num_keys;i++) {
875         if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
876             found= True;
877             break;
878         }
879     }
880     if (!found)
881         return NULL;
882     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
883         return NULL;
884     key= &row->keys[row->num_keys];
885     strncpy(key->under.name,under,XkbKeyNameLength);
886     strncpy(key->over.name,over,XkbKeyNameLength);
887     row->num_keys++;
888     return key;
889 }
890
891 struct xkb_overlay_row *
892 XkbcAddGeomOverlayRow(struct xkb_overlay * overlay,int row_under,int sz_keys)
893 {
894 register int            i;
895 struct xkb_overlay_row *        row;
896
897     if ((!overlay)||(sz_keys<0))
898         return NULL;
899     if (row_under>=overlay->section_under->num_rows)
900         return NULL;
901     for (i=0;i<overlay->num_rows;i++) {
902         if (overlay->rows[i].row_under==row_under) {
903             row= &overlay->rows[i];
904             if ((row->sz_keys<sz_keys)&&
905                                 (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
906                 return NULL;
907             }
908             return &overlay->rows[i];
909         }
910     }
911     if ((overlay->num_rows>=overlay->sz_rows)&&
912                                 (_XkbAllocOverlayRows(overlay,1)!=Success))
913         return NULL;
914     row= &overlay->rows[overlay->num_rows];
915     bzero(row,sizeof(struct xkb_overlay_row));
916     if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
917         return NULL;
918     row->row_under= row_under;
919     overlay->num_rows++;
920     return row;
921 }
922
923 struct xkb_overlay *
924 XkbcAddGeomOverlay(struct xkb_section * section,uint32_t name,int sz_rows)
925 {
926 register int    i;
927 struct xkb_overlay *    overlay;
928
929     if ((!section)||(name==None)||(sz_rows==0))
930         return NULL;
931
932     for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
933         if (overlay->name==name) {
934             if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
935                 return NULL;
936             return overlay;
937         }
938     }
939     if ((section->num_overlays>=section->sz_overlays)&&
940                                 (_XkbAllocOverlays(section,1)!=Success))
941         return NULL;
942     overlay= &section->overlays[section->num_overlays];
943     if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
944         return NULL;
945     overlay->name= name;
946     overlay->section_under= section;
947     section->num_overlays++;
948     return overlay;
949 }