Move include path from X11/extensions/ to xkbcommon/
[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 "xkbcommon/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 static 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 static 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 static 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 static 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 static 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 static 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 static void
212 XkbcFreeGeomKeys(struct xkb_row * row, int first, int count, Bool freeAll)
213 {
214     _XkbFreeGeomLeafElems(freeAll, first, count,
215                           &row->num_keys, &row->sz_keys,
216                           (char **)&row->keys, sizeof(struct xkb_key));
217 }
218
219 static void
220 _XkbClearRow(char *row_in)
221 {
222     struct xkb_row * row = (struct xkb_row *)row_in;
223
224     if (row->keys)
225         XkbcFreeGeomKeys(row, 0, row->num_keys, True);
226 }
227
228 static void
229 XkbcFreeGeomRows(struct xkb_section * section, int first, int count, Bool freeAll)
230 {
231     _XkbFreeGeomNonLeafElems(freeAll, first, count,
232                              &section->num_rows, &section->sz_rows,
233                              (char **)&section->rows, sizeof(struct xkb_row),
234                              _XkbClearRow);
235 }
236
237
238
239 static void
240 _XkbClearDoodad(char *doodad_in)
241 {
242     union xkb_doodad * doodad = (union xkb_doodad *)doodad_in;
243
244     switch (doodad->any.type) {
245     case XkbTextDoodad:
246         if (doodad->text.text) {
247             free(doodad->text.text);
248             doodad->text.text = NULL;
249         }
250         if (doodad->text.font) {
251             free(doodad->text.font);
252             doodad->text.font = NULL;
253         }
254         break;
255
256     case XkbLogoDoodad:
257         if (doodad->logo.logo_name) {
258             free(doodad->logo.logo_name);
259             doodad->logo.logo_name = NULL;
260         }
261         break;
262     }
263 }
264
265 static void
266 XkbcFreeGeomDoodads(union xkb_doodad * doodads, int nDoodads, Bool freeAll)
267 {
268     int i;
269     union xkb_doodad * doodad;
270
271     if (doodads) {
272         for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++)
273             _XkbClearDoodad((char *)doodad);
274         if (freeAll)
275             free(doodads);
276     }
277 }
278
279 static void
280 _XkbClearSection(char *section_in)
281 {
282     struct xkb_section * section = (struct xkb_section *)section_in;
283
284     if (section->rows)
285         XkbcFreeGeomRows(section, 0, section->num_rows, True);
286     if (section->doodads) {
287         XkbcFreeGeomDoodads(section->doodads, section->num_doodads, True);
288         section->doodads = NULL;
289     }
290 }
291
292 static void
293 XkbcFreeGeomSections(struct xkb_geometry * geom, int first, int count, Bool freeAll)
294 {
295     _XkbFreeGeomNonLeafElems(freeAll, first, count,
296                              &geom->num_sections, &geom->sz_sections,
297                              (char **)&geom->sections, sizeof(struct xkb_section),
298                              _XkbClearSection);
299 }
300
301 void
302 XkbcFreeGeometry(struct xkb_geometry * geom, unsigned which, Bool freeMap)
303 {
304     if (!geom)
305         return;
306
307     if (freeMap)
308         which = XkbGeomAllMask;
309
310     if ((which & XkbGeomPropertiesMask) && geom->properties)
311         XkbcFreeGeomProperties(geom, 0, geom->num_properties, True);
312
313     if ((which & XkbGeomColorsMask) && geom->colors)
314         XkbcFreeGeomColors(geom, 0, geom->num_colors, True);
315
316     if ((which & XkbGeomShapesMask) && geom->shapes)
317         XkbcFreeGeomShapes(geom, 0, geom->num_shapes, True);
318
319     if ((which & XkbGeomSectionsMask) && geom->sections)
320         XkbcFreeGeomSections(geom, 0, geom->num_sections, True);
321
322     if ((which & XkbGeomDoodadsMask) && geom->doodads) {
323         XkbcFreeGeomDoodads(geom->doodads, geom->num_doodads, True);
324         geom->doodads = NULL;
325         geom->num_doodads = geom->sz_doodads = 0;
326     }
327
328     if ((which & XkbGeomKeyAliasesMask) && geom->key_aliases)
329         XkbcFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, True);
330
331     if (freeMap) {
332         if (geom->label_font) {
333             free(geom->label_font);
334             geom->label_font = NULL;
335         }
336         free(geom);
337     }
338 }
339
340 static int
341 _XkbGeomAlloc(char **old, unsigned short *num, unsigned short *total,
342               int num_new, size_t sz_elem)
343 {
344     if (num_new < 1)
345         return Success;
346
347     if (!(*old))
348         *num = *total = 0;
349
350     if ((*num) + num_new <= (*total))
351         return Success;
352
353     *total = (*num) + num_new;
354
355     if (*old)
356         *old = (char *)realloc(*old, (*total) * sz_elem);
357     else
358         *old = (char *)calloc(*total, sz_elem);
359     if (!(*old)) {
360         *total = *num = 0;
361         return BadAlloc;
362     }
363
364     if (*num > 0) {
365         char *tmp = *old;
366         bzero(&tmp[sz_elem * (*num)], num_new * sz_elem);
367     }
368
369     return Success;
370 }
371
372 #define _XkbAllocProps(g, n)    _XkbGeomAlloc((char **)&(g)->properties, \
373                                               &(g)->num_properties, \
374                                               &(g)->sz_properties, \
375                                               (n), sizeof(struct xkb_property))
376 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
377                                               &(g)->num_colors, \
378                                               &(g)->sz_colors, \
379                                               (n), sizeof(struct xkb_color))
380 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
381                                               &(g)->num_shapes, \
382                                               &(g)->sz_shapes, \
383                                               (n), sizeof(struct xkb_shape))
384 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
385                                               &(g)->num_sections, \
386                                               &(g)->sz_sections, \
387                                               (n), sizeof(struct xkb_section))
388 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
389                                               &(g)->num_doodads, \
390                                               &(g)->sz_doodads, \
391                                               (n), sizeof(union xkb_doodad))
392 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
393                                                   &(g)->num_key_aliases, \
394                                                   &(g)->sz_key_aliases, \
395                                                   (n), sizeof(struct xkb_key_alias))
396
397 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
398                                               &(s)->num_outlines, \
399                                               &(s)->sz_outlines, \
400                                               (n), sizeof(struct xkb_outline))
401 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
402                                               &(s)->num_rows, \
403                                               &(s)->sz_rows, \
404                                               (n), sizeof(struct xkb_row))
405 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
406                                               &(o)->num_points, \
407                                               &(o)->sz_points, \
408                                               (n), sizeof(struct xkb_point))
409 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
410                                               &(r)->num_keys, \
411                                               &(r)->sz_keys, \
412                                               (n), sizeof(struct xkb_key))
413 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
414                                               &(s)->num_overlays, \
415                                               &(s)->sz_overlays, \
416                                               (n), sizeof(struct xkb_overlay))
417 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
418                                                   &(o)->num_rows, \
419                                                   &(o)->sz_rows, \
420                                                   (n), sizeof(struct xkb_overlay_row))
421 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
422                                                   &(r)->num_keys, \
423                                                   &(r)->sz_keys, \
424                                                   (n), sizeof(struct xkb_overlay_key))
425
426 int
427 XkbcAllocGeomKeyAliases(struct xkb_geometry * geom, int nKeyAliases)
428 {
429     return _XkbAllocKeyAliases(geom, nKeyAliases);
430 }
431
432 int
433 XkbcAllocGeometry(struct xkb_desc * xkb, struct xkb_geometry_sizes * sizes)
434 {
435     struct xkb_geometry * geom;
436     int rtrn;
437
438     if (!xkb->geom) {
439         xkb->geom = _XkbTypedCalloc(1, struct xkb_geometry);
440         if (!xkb->geom)
441             return BadAlloc;
442     }
443     geom = xkb->geom;
444
445     if ((sizes->which & XkbGeomPropertiesMask) &&
446         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
447         goto bail;
448
449     if ((sizes->which & XkbGeomColorsMask) &&
450         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
451         goto bail;
452
453     if ((sizes->which & XkbGeomShapesMask) &&
454         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
455         goto bail;
456
457     if ((sizes->which & XkbGeomSectionsMask) &&
458         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
459         goto bail;
460
461     if ((sizes->which & XkbGeomDoodadsMask) &&
462         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
463         goto bail;
464
465     if ((sizes->which & XkbGeomKeyAliasesMask) &&
466         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
467         goto bail;
468
469     return Success;
470 bail:
471     XkbcFreeGeometry(geom, XkbGeomAllMask, True);
472     xkb->geom = NULL;
473     return rtrn;
474 }
475
476 struct xkb_property *
477 XkbcAddGeomProperty(struct xkb_geometry * geom,const char *name,const char *value)
478 {
479 register int i;
480 register struct xkb_property * prop;
481
482     if ((!geom)||(!name)||(!value))
483         return NULL;
484     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
485         if ((prop->name)&&(strcmp(name,prop->name)==0)) {
486             if (prop->value)
487                 free(prop->value);
488             prop->value= (char *)malloc(strlen(value)+1);
489             if (prop->value)
490                 strcpy(prop->value,value);
491             return prop;
492         }
493     }
494     if ((geom->num_properties>=geom->sz_properties)&&
495                                         (_XkbAllocProps(geom,1)!=Success)) {
496         return NULL;
497     }
498     prop= &geom->properties[geom->num_properties];
499     prop->name= (char *)malloc(strlen(name)+1);
500     if (!name)
501         return NULL;
502     strcpy(prop->name,name);
503     prop->value= (char *)malloc(strlen(value)+1);
504     if (!value) {
505         free(prop->name);
506         prop->name= NULL;
507         return NULL;
508     }
509     strcpy(prop->value,value);
510     geom->num_properties++;
511     return prop;
512 }
513
514 struct xkb_color *
515 XkbcAddGeomColor(struct xkb_geometry * geom,const char *spec,unsigned int pixel)
516 {
517 register int i;
518 register struct xkb_color * color;
519
520     if ((!geom)||(!spec))
521         return NULL;
522     for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
523         if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
524             color->pixel= pixel;
525             return color;
526         }
527     }
528     if ((geom->num_colors>=geom->sz_colors)&&
529                                         (_XkbAllocColors(geom,1)!=Success)) {
530         return NULL;
531     }
532     color= &geom->colors[geom->num_colors];
533     color->pixel= pixel;
534     color->spec= (char *)malloc(strlen(spec)+1);
535     if (!color->spec)
536         return NULL;
537     strcpy(color->spec,spec);
538     geom->num_colors++;
539     return color;
540 }
541
542 struct xkb_outline *
543 XkbcAddGeomOutline(struct xkb_shape * shape,int sz_points)
544 {
545 struct xkb_outline *    outline;
546
547     if ((!shape)||(sz_points<0))
548         return NULL;
549     if ((shape->num_outlines>=shape->sz_outlines)&&
550                                         (_XkbAllocOutlines(shape,1)!=Success)) {
551         return NULL;
552     }
553     outline= &shape->outlines[shape->num_outlines];
554     bzero(outline,sizeof(struct xkb_outline));
555     if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
556         return NULL;
557     shape->num_outlines++;
558     return outline;
559 }
560
561 struct xkb_shape *
562 XkbcAddGeomShape(struct xkb_geometry * geom,uint32_t name,int sz_outlines)
563 {
564 struct xkb_shape *      shape;
565 register int    i;
566
567     if ((!geom)||(!name)||(sz_outlines<0))
568         return NULL;
569     if (geom->num_shapes>0) {
570         for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
571             if (name==shape->name)
572                 return shape;
573         }
574     }
575     if ((geom->num_shapes>=geom->sz_shapes)&&
576                                         (_XkbAllocShapes(geom,1)!=Success))
577         return NULL;
578     shape= &geom->shapes[geom->num_shapes];
579     bzero(shape,sizeof(struct xkb_shape));
580     if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
581         return NULL;
582     shape->name= name;
583     shape->primary= shape->approx= NULL;
584     geom->num_shapes++;
585     return shape;
586 }
587
588 struct xkb_key *
589 XkbcAddGeomKey(struct xkb_row * row)
590 {
591 struct xkb_key *        key;
592     if (!row)
593         return NULL;
594     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
595         return NULL;
596     key= &row->keys[row->num_keys++];
597     bzero(key,sizeof(struct xkb_key));
598     return key;
599 }
600
601 struct xkb_row *
602 XkbcAddGeomRow(struct xkb_section * section,int sz_keys)
603 {
604 struct xkb_row *        row;
605
606     if ((!section)||(sz_keys<0))
607         return NULL;
608     if ((section->num_rows>=section->sz_rows)&&
609                                         (_XkbAllocRows(section,1)!=Success))
610         return NULL;
611     row= &section->rows[section->num_rows];
612     bzero(row,sizeof(struct xkb_row));
613     if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
614         return NULL;
615     section->num_rows++;
616     return row;
617 }
618
619 struct xkb_section *
620 XkbcAddGeomSection(     struct xkb_geometry *   geom,
621                         uint32_t                name,
622                         int             sz_rows,
623                         int             sz_doodads,
624                         int             sz_over)
625 {
626 register int    i;
627 struct xkb_section *    section;
628
629     if ((!geom)||(name==None)||(sz_rows<0))
630         return NULL;
631     for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
632         if (section->name!=name)
633             continue;
634         if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
635             ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
636             ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
637             return NULL;
638         return section;
639     }
640     if ((geom->num_sections>=geom->sz_sections)&&
641                                         (_XkbAllocSections(geom,1)!=Success))
642         return NULL;
643     section= &geom->sections[geom->num_sections];
644     if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
645         return NULL;
646     if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
647         if (section->rows) {
648             free(section->rows);
649             section->rows= NULL;
650             section->sz_rows= section->num_rows= 0;
651         }
652         return NULL;
653     }
654     section->name= name;
655     geom->num_sections++;
656     return section;
657 }
658
659 union xkb_doodad *
660 XkbcAddGeomDoodad(struct xkb_geometry * geom,struct xkb_section * section,uint32_t name)
661 {
662 union xkb_doodad *old, *doodad;
663 register int    i,nDoodads;
664
665     if ((!geom)||(name==None))
666         return NULL;
667     if ((section!=NULL)&&(section->num_doodads>0)) {
668         old= section->doodads;
669         nDoodads= section->num_doodads;
670     }
671     else {
672         old= geom->doodads;
673         nDoodads= geom->num_doodads;
674     }
675     for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
676         if (doodad->any.name==name)
677             return doodad;
678     }
679     if (section) {
680         if ((section->num_doodads>=geom->sz_doodads)&&
681             (_XkbAllocDoodads(section,1)!=Success)) {
682             return NULL;
683         }
684         doodad= &section->doodads[section->num_doodads++];
685     }
686     else {
687         if ((geom->num_doodads>=geom->sz_doodads)&&
688                                         (_XkbAllocDoodads(geom,1)!=Success))
689             return NULL;
690         doodad= &geom->doodads[geom->num_doodads++];
691     }
692     bzero(doodad,sizeof(union xkb_doodad));
693     doodad->any.name= name;
694     return doodad;
695 }
696
697 struct xkb_overlay_row *
698 XkbcAddGeomOverlayRow(struct xkb_overlay * overlay,int row_under,int sz_keys)
699 {
700 register int            i;
701 struct xkb_overlay_row *        row;
702
703     if ((!overlay)||(sz_keys<0))
704         return NULL;
705     if (row_under>=overlay->section_under->num_rows)
706         return NULL;
707     for (i=0;i<overlay->num_rows;i++) {
708         if (overlay->rows[i].row_under==row_under) {
709             row= &overlay->rows[i];
710             if ((row->sz_keys<sz_keys)&&
711                                 (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
712                 return NULL;
713             }
714             return &overlay->rows[i];
715         }
716     }
717     if ((overlay->num_rows>=overlay->sz_rows)&&
718                                 (_XkbAllocOverlayRows(overlay,1)!=Success))
719         return NULL;
720     row= &overlay->rows[overlay->num_rows];
721     bzero(row,sizeof(struct xkb_overlay_row));
722     if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
723         return NULL;
724     row->row_under= row_under;
725     overlay->num_rows++;
726     return row;
727 }
728
729 struct xkb_overlay *
730 XkbcAddGeomOverlay(struct xkb_section * section,uint32_t name,int sz_rows)
731 {
732 register int    i;
733 struct xkb_overlay *    overlay;
734
735     if ((!section)||(name==None)||(sz_rows==0))
736         return NULL;
737
738     for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
739         if (overlay->name==name) {
740             if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
741                 return NULL;
742             return overlay;
743         }
744     }
745     if ((section->num_overlays>=section->sz_overlays)&&
746                                 (_XkbAllocOverlays(section,1)!=Success))
747         return NULL;
748     overlay= &section->overlays[section->num_overlays];
749     if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
750         return NULL;
751     overlay->name= name;
752     overlay->section_under= section;
753     section->num_overlays++;
754     return overlay;
755 }