ad24139e65971acf682a8be0565edb7c120e84dd
[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 "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         free(*elems);
42         *elems = NULL;
43         return;
44     }
45
46     if ((first >= (*num_inout)) || (first < 0) || (count < 1))
47         return;
48
49     if (first + count >= (*num_inout))
50         /* truncating the array is easy */
51         (*num_inout) = first;
52     else {
53         char *ptr = *elems;
54         int extra = ((*num_inout) - first + count) * elem_sz;
55
56         if (extra > 0)
57             memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz],
58                     extra);
59
60         (*num_inout) -= count;
61     }
62 }
63
64 typedef void (*ContentsClearFunc)(char *priv);
65
66 static void
67 _XkbFreeGeomNonLeafElems(Bool freeAll, int first, int count,
68                          unsigned short *num_inout, unsigned short *sz_inout,
69                          char **elems, unsigned int elem_sz,
70                          ContentsClearFunc freeFunc)
71 {
72     int i;
73     char *ptr;
74
75     if (freeAll) {
76         first = 0;
77         count = *num_inout;
78     }
79     else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
80         return;
81     else if (first + count > (*num_inout))
82         count = (*num_inout) - first;
83
84     if (!(*elems))
85         return;
86
87     if (freeFunc) {
88         ptr = *elems;
89         ptr += first * elem_sz;
90         for (i = 0; i < count; i++) {
91             (*freeFunc)(ptr);
92             ptr += elem_sz;
93         }
94     }
95
96     if (freeAll) {
97         *num_inout = *sz_inout = 0;
98         free(*elems);
99         *elems = NULL;
100     }
101     else if (first + count >= (*num_inout))
102         *num_inout = first;
103     else {
104         i = ((*num_inout) - first + count) * elem_sz;
105         ptr = *elems;
106         memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz], i);
107         (*num_inout) -= count;
108     }
109 }
110
111 static void
112 _XkbClearProperty(char *prop_in)
113 {
114     struct xkb_property * prop = (struct xkb_property *)prop_in;
115
116     free(prop->name);
117     prop->name = NULL;
118     free(prop->value);
119     prop->value = NULL;
120 }
121
122 static void
123 XkbcFreeGeomProperties(struct xkb_geometry * geom, int first, int count, Bool freeAll)
124 {
125     _XkbFreeGeomNonLeafElems(freeAll, first, count,
126                              &geom->num_properties, &geom->sz_properties,
127                              (char **)&geom->properties,
128                              sizeof(struct xkb_property),
129                              _XkbClearProperty);
130 }
131
132 static void
133 XkbcFreeGeomKeyAliases(struct xkb_geometry * geom, int first, int count, Bool freeAll)
134 {
135     _XkbFreeGeomLeafElems(freeAll, first, count,
136                           &geom->num_key_aliases, &geom->sz_key_aliases,
137                           (char **)&geom->key_aliases,
138                           sizeof(struct xkb_key_alias));
139 }
140
141 static void
142 _XkbClearColor(char *color_in)
143 {
144     struct xkb_color * color = (struct xkb_color *)color_in;
145
146     free(color->spec);
147 }
148
149 static void
150 XkbcFreeGeomColors(struct xkb_geometry * geom, int first, int count, Bool freeAll)
151 {
152     _XkbFreeGeomNonLeafElems(freeAll, first, count,
153                              &geom->num_colors, &geom->sz_colors,
154                              (char **)&geom->colors, sizeof(struct xkb_color),
155                              _XkbClearColor);
156 }
157
158 static void
159 XkbcFreeGeomPoints(struct xkb_outline * outline, int first, int count, Bool freeAll)
160 {
161     _XkbFreeGeomLeafElems(freeAll, first, count,
162                           &outline->num_points, &outline->sz_points,
163                           (char **)&outline->points, sizeof(struct xkb_point));
164 }
165
166 static void
167 _XkbClearOutline(char *outline_in)
168 {
169     struct xkb_outline * outline = (struct xkb_outline *)outline_in;
170
171     if (outline->points)
172         XkbcFreeGeomPoints(outline, 0, outline->num_points, True);
173 }
174
175 static void
176 XkbcFreeGeomOutlines(struct xkb_shape * shape, int first, int count, Bool freeAll)
177 {
178     _XkbFreeGeomNonLeafElems(freeAll, first, count,
179                              &shape->num_outlines, &shape->sz_outlines,
180                              (char **)&shape->outlines, sizeof(struct xkb_outline),
181                              _XkbClearOutline);
182 }
183
184 static void
185 _XkbClearShape(char *shape_in)
186 {
187     struct xkb_shape * shape = (struct xkb_shape *)shape_in;
188
189     if (shape->outlines)
190         XkbcFreeGeomOutlines(shape, 0, shape->num_outlines, True);
191 }
192
193 static void
194 XkbcFreeGeomShapes(struct xkb_geometry * geom, int first, int count, Bool freeAll)
195 {
196     _XkbFreeGeomNonLeafElems(freeAll, first, count,
197                              &geom->num_shapes, &geom->sz_shapes,
198                              (char **)&geom->shapes, sizeof(struct xkb_shape),
199                              _XkbClearShape);
200 }
201
202 static void
203 XkbcFreeGeomKeys(struct xkb_row * row, int first, int count, Bool freeAll)
204 {
205     _XkbFreeGeomLeafElems(freeAll, first, count,
206                           &row->num_keys, &row->sz_keys,
207                           (char **)&row->keys, sizeof(struct xkb_key));
208 }
209
210 static void
211 _XkbClearRow(char *row_in)
212 {
213     struct xkb_row * row = (struct xkb_row *)row_in;
214
215     if (row->keys)
216         XkbcFreeGeomKeys(row, 0, row->num_keys, True);
217 }
218
219 static void
220 XkbcFreeGeomRows(struct xkb_section * section, int first, int count, Bool freeAll)
221 {
222     _XkbFreeGeomNonLeafElems(freeAll, first, count,
223                              &section->num_rows, &section->sz_rows,
224                              (char **)&section->rows, sizeof(struct xkb_row),
225                              _XkbClearRow);
226 }
227
228
229
230 static void
231 _XkbClearDoodad(char *doodad_in)
232 {
233     union xkb_doodad * doodad = (union xkb_doodad *)doodad_in;
234
235     switch (doodad->any.type) {
236     case XkbTextDoodad:
237         free(doodad->text.text);
238         doodad->text.text = NULL;
239         free(doodad->text.font);
240         doodad->text.font = NULL;
241         break;
242
243     case XkbLogoDoodad:
244         free(doodad->logo.logo_name);
245         doodad->logo.logo_name = NULL;
246         break;
247     }
248 }
249
250 static void
251 XkbcFreeGeomDoodads(union xkb_doodad * doodads, int nDoodads, Bool freeAll)
252 {
253     int i;
254     union xkb_doodad * doodad;
255
256     for (i = 0, doodad = doodads; i < nDoodads && doodad; i++, doodad++)
257         _XkbClearDoodad((char *)doodad);
258     if (freeAll)
259         free(doodads);
260 }
261
262 static void
263 _XkbClearSection(char *section_in)
264 {
265     struct xkb_section * section = (struct xkb_section *)section_in;
266
267     if (section->rows)
268         XkbcFreeGeomRows(section, 0, section->num_rows, True);
269     XkbcFreeGeomDoodads(section->doodads, section->num_doodads, True);
270     section->doodads = NULL;
271 }
272
273 static void
274 XkbcFreeGeomSections(struct xkb_geometry * geom, int first, int count, Bool freeAll)
275 {
276     _XkbFreeGeomNonLeafElems(freeAll, first, count,
277                              &geom->num_sections, &geom->sz_sections,
278                              (char **)&geom->sections, sizeof(struct xkb_section),
279                              _XkbClearSection);
280 }
281
282 void
283 XkbcFreeGeometry(struct xkb_geometry * geom, unsigned which, Bool freeMap)
284 {
285     if (!geom)
286         return;
287
288     if (freeMap)
289         which = XkbGeomAllMask;
290
291     if ((which & XkbGeomPropertiesMask) && geom->properties)
292         XkbcFreeGeomProperties(geom, 0, geom->num_properties, True);
293
294     if ((which & XkbGeomColorsMask) && geom->colors)
295         XkbcFreeGeomColors(geom, 0, geom->num_colors, True);
296
297     if ((which & XkbGeomShapesMask) && geom->shapes)
298         XkbcFreeGeomShapes(geom, 0, geom->num_shapes, True);
299
300     if ((which & XkbGeomSectionsMask) && geom->sections)
301         XkbcFreeGeomSections(geom, 0, geom->num_sections, True);
302
303     if ((which & XkbGeomDoodadsMask) && geom->doodads) {
304         XkbcFreeGeomDoodads(geom->doodads, geom->num_doodads, True);
305         geom->doodads = NULL;
306         geom->num_doodads = geom->sz_doodads = 0;
307     }
308
309     if ((which & XkbGeomKeyAliasesMask) && geom->key_aliases)
310         XkbcFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, True);
311
312     if (freeMap) {
313         free(geom->label_font);
314         geom->label_font = NULL;
315         free(geom);
316     }
317 }
318
319 static int
320 _XkbGeomAlloc(char **old, unsigned short *num, unsigned short *total,
321               int num_new, size_t sz_elem)
322 {
323     if (num_new < 1)
324         return Success;
325
326     if (!(*old))
327         *num = *total = 0;
328
329     if ((*num) + num_new <= (*total))
330         return Success;
331
332     *total = (*num) + num_new;
333
334     if (*old)
335         *old = (char *)realloc(*old, (*total) * sz_elem);
336     else
337         *old = (char *)calloc(*total, sz_elem);
338     if (!(*old)) {
339         *total = *num = 0;
340         return BadAlloc;
341     }
342
343     if (*num > 0) {
344         char *tmp = *old;
345         bzero(&tmp[sz_elem * (*num)], num_new * sz_elem);
346     }
347
348     return Success;
349 }
350
351 #define _XkbAllocProps(g, n)    _XkbGeomAlloc((char **)&(g)->properties, \
352                                               &(g)->num_properties, \
353                                               &(g)->sz_properties, \
354                                               (n), sizeof(struct xkb_property))
355 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
356                                               &(g)->num_colors, \
357                                               &(g)->sz_colors, \
358                                               (n), sizeof(struct xkb_color))
359 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
360                                               &(g)->num_shapes, \
361                                               &(g)->sz_shapes, \
362                                               (n), sizeof(struct xkb_shape))
363 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
364                                               &(g)->num_sections, \
365                                               &(g)->sz_sections, \
366                                               (n), sizeof(struct xkb_section))
367 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
368                                               &(g)->num_doodads, \
369                                               &(g)->sz_doodads, \
370                                               (n), sizeof(union xkb_doodad))
371 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
372                                                   &(g)->num_key_aliases, \
373                                                   &(g)->sz_key_aliases, \
374                                                   (n), sizeof(struct xkb_key_alias))
375
376 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
377                                               &(s)->num_outlines, \
378                                               &(s)->sz_outlines, \
379                                               (n), sizeof(struct xkb_outline))
380 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
381                                               &(s)->num_rows, \
382                                               &(s)->sz_rows, \
383                                               (n), sizeof(struct xkb_row))
384 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
385                                               &(o)->num_points, \
386                                               &(o)->sz_points, \
387                                               (n), sizeof(struct xkb_point))
388 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
389                                               &(r)->num_keys, \
390                                               &(r)->sz_keys, \
391                                               (n), sizeof(struct xkb_key))
392 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
393                                               &(s)->num_overlays, \
394                                               &(s)->sz_overlays, \
395                                               (n), sizeof(struct xkb_overlay))
396 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
397                                                   &(o)->num_rows, \
398                                                   &(o)->sz_rows, \
399                                                   (n), sizeof(struct xkb_overlay_row))
400 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
401                                                   &(r)->num_keys, \
402                                                   &(r)->sz_keys, \
403                                                   (n), sizeof(struct xkb_overlay_key))
404
405 int
406 XkbcAllocGeomKeyAliases(struct xkb_geometry * geom, int nKeyAliases)
407 {
408     return _XkbAllocKeyAliases(geom, nKeyAliases);
409 }
410
411 int
412 XkbcAllocGeometry(struct xkb_desc * xkb, struct xkb_geometry_sizes * sizes)
413 {
414     struct xkb_geometry * geom;
415     int rtrn;
416
417     if (!xkb->geom) {
418         xkb->geom = _XkbTypedCalloc(1, struct xkb_geometry);
419         if (!xkb->geom)
420             return BadAlloc;
421     }
422     geom = xkb->geom;
423
424     if ((sizes->which & XkbGeomPropertiesMask) &&
425         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
426         goto bail;
427
428     if ((sizes->which & XkbGeomColorsMask) &&
429         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
430         goto bail;
431
432     if ((sizes->which & XkbGeomShapesMask) &&
433         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
434         goto bail;
435
436     if ((sizes->which & XkbGeomSectionsMask) &&
437         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
438         goto bail;
439
440     if ((sizes->which & XkbGeomDoodadsMask) &&
441         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
442         goto bail;
443
444     if ((sizes->which & XkbGeomKeyAliasesMask) &&
445         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
446         goto bail;
447
448     return Success;
449 bail:
450     XkbcFreeGeometry(geom, XkbGeomAllMask, True);
451     xkb->geom = NULL;
452     return rtrn;
453 }
454
455 struct xkb_property *
456 XkbcAddGeomProperty(struct xkb_geometry * geom,const char *name,const char *value)
457 {
458     int i;
459     struct xkb_property * prop;
460
461     if ((!geom)||(!name)||(!value))
462         return NULL;
463     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
464         if ((prop->name)&&(strcmp(name,prop->name)==0)) {
465             free(prop->value);
466             prop->value = strdup(value);
467             return prop;
468         }
469     }
470     if ((geom->num_properties>=geom->sz_properties)&&
471                                         (_XkbAllocProps(geom,1)!=Success)) {
472         return NULL;
473     }
474     prop= &geom->properties[geom->num_properties];
475     prop->name = strdup(name);
476     if (!prop->name)
477         return NULL;
478     prop->value = strdup(value);
479     if (!prop->value) {
480         free(prop->name);
481         prop->name= NULL;
482         return NULL;
483     }
484     geom->num_properties++;
485     return prop;
486 }
487
488 struct xkb_color *
489 XkbcAddGeomColor(struct xkb_geometry * geom,const char *spec,unsigned int pixel)
490 {
491     int i;
492     struct xkb_color * color;
493
494     if ((!geom)||(!spec))
495         return NULL;
496     for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
497         if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
498             color->pixel= pixel;
499             return color;
500         }
501     }
502     if ((geom->num_colors>=geom->sz_colors)&&
503                                         (_XkbAllocColors(geom,1)!=Success)) {
504         return NULL;
505     }
506     color= &geom->colors[geom->num_colors];
507     color->pixel= pixel;
508     color->spec = strdup(spec);
509     if (!color->spec)
510         return NULL;
511     geom->num_colors++;
512     return color;
513 }
514
515 struct xkb_outline *
516 XkbcAddGeomOutline(struct xkb_shape * shape,int sz_points)
517 {
518 struct xkb_outline *    outline;
519
520     if ((!shape)||(sz_points<0))
521         return NULL;
522     if ((shape->num_outlines>=shape->sz_outlines)&&
523                                         (_XkbAllocOutlines(shape,1)!=Success)) {
524         return NULL;
525     }
526     outline= &shape->outlines[shape->num_outlines];
527     bzero(outline,sizeof(struct xkb_outline));
528     if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
529         return NULL;
530     shape->num_outlines++;
531     return outline;
532 }
533
534 struct xkb_shape *
535 XkbcAddGeomShape(struct xkb_geometry * geom,uint32_t name,int sz_outlines)
536 {
537     struct xkb_shape *shape;
538     int i;
539
540     if ((!geom)||(!name)||(sz_outlines<0))
541         return NULL;
542     if (geom->num_shapes>0) {
543         for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
544             if (name==shape->name)
545                 return shape;
546         }
547     }
548     if ((geom->num_shapes>=geom->sz_shapes)&&
549                                         (_XkbAllocShapes(geom,1)!=Success))
550         return NULL;
551     shape= &geom->shapes[geom->num_shapes];
552     bzero(shape,sizeof(struct xkb_shape));
553     if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
554         return NULL;
555     shape->name= name;
556     shape->primary= shape->approx= NULL;
557     geom->num_shapes++;
558     return shape;
559 }
560
561 struct xkb_key *
562 XkbcAddGeomKey(struct xkb_row * row)
563 {
564 struct xkb_key *        key;
565     if (!row)
566         return NULL;
567     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
568         return NULL;
569     key= &row->keys[row->num_keys++];
570     bzero(key,sizeof(struct xkb_key));
571     return key;
572 }
573
574 struct xkb_row *
575 XkbcAddGeomRow(struct xkb_section * section,int sz_keys)
576 {
577 struct xkb_row *        row;
578
579     if ((!section)||(sz_keys<0))
580         return NULL;
581     if ((section->num_rows>=section->sz_rows)&&
582                                         (_XkbAllocRows(section,1)!=Success))
583         return NULL;
584     row= &section->rows[section->num_rows];
585     bzero(row,sizeof(struct xkb_row));
586     if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
587         return NULL;
588     section->num_rows++;
589     return row;
590 }
591
592 struct xkb_section *
593 XkbcAddGeomSection(     struct xkb_geometry *   geom,
594                         uint32_t                name,
595                         int             sz_rows,
596                         int             sz_doodads,
597                         int             sz_over)
598 {
599     int i;
600     struct xkb_section *        section;
601
602     if ((!geom)||(name==None)||(sz_rows<0))
603         return NULL;
604     for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
605         if (section->name!=name)
606             continue;
607         if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
608             ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
609             ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
610             return NULL;
611         return section;
612     }
613     if ((geom->num_sections>=geom->sz_sections)&&
614                                         (_XkbAllocSections(geom,1)!=Success))
615         return NULL;
616     section= &geom->sections[geom->num_sections];
617     if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
618         return NULL;
619     if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
620         free(section->rows);
621         section->rows= NULL;
622         section->sz_rows= section->num_rows= 0;
623         return NULL;
624     }
625     section->name= name;
626     geom->num_sections++;
627     return section;
628 }
629
630 union xkb_doodad *
631 XkbcAddGeomDoodad(struct xkb_geometry * geom,struct xkb_section * section,uint32_t name)
632 {
633     union xkb_doodad *old, *doodad;
634     int i, nDoodads;
635
636     if ((!geom)||(name==None))
637         return NULL;
638     if ((section!=NULL)&&(section->num_doodads>0)) {
639         old= section->doodads;
640         nDoodads= section->num_doodads;
641     }
642     else {
643         old= geom->doodads;
644         nDoodads= geom->num_doodads;
645     }
646     for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
647         if (doodad->any.name==name)
648             return doodad;
649     }
650     if (section) {
651         if ((section->num_doodads>=geom->sz_doodads)&&
652             (_XkbAllocDoodads(section,1)!=Success)) {
653             return NULL;
654         }
655         doodad= &section->doodads[section->num_doodads++];
656     }
657     else {
658         if ((geom->num_doodads>=geom->sz_doodads)&&
659                                         (_XkbAllocDoodads(geom,1)!=Success))
660             return NULL;
661         doodad= &geom->doodads[geom->num_doodads++];
662     }
663     bzero(doodad,sizeof(union xkb_doodad));
664     doodad->any.name= name;
665     return doodad;
666 }
667
668 struct xkb_overlay_row *
669 XkbcAddGeomOverlayRow(struct xkb_overlay * overlay,int row_under,int sz_keys)
670 {
671     int i;
672     struct xkb_overlay_row *row;
673
674     if ((!overlay)||(sz_keys<0))
675         return NULL;
676     if (row_under>=overlay->section_under->num_rows)
677         return NULL;
678     for (i=0;i<overlay->num_rows;i++) {
679         if (overlay->rows[i].row_under==row_under) {
680             row= &overlay->rows[i];
681             if ((row->sz_keys<sz_keys)&&
682                                 (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
683                 return NULL;
684             }
685             return &overlay->rows[i];
686         }
687     }
688     if ((overlay->num_rows>=overlay->sz_rows)&&
689                                 (_XkbAllocOverlayRows(overlay,1)!=Success))
690         return NULL;
691     row= &overlay->rows[overlay->num_rows];
692     bzero(row,sizeof(struct xkb_overlay_row));
693     if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
694         return NULL;
695     row->row_under= row_under;
696     overlay->num_rows++;
697     return row;
698 }
699
700 struct xkb_overlay *
701 XkbcAddGeomOverlay(struct xkb_section * section,uint32_t name,int sz_rows)
702 {
703     int i;
704     struct xkb_overlay *overlay;
705
706     if ((!section)||(name==None)||(sz_rows==0))
707         return NULL;
708
709     for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
710         if (overlay->name==name) {
711             if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
712                 return NULL;
713             return overlay;
714         }
715     }
716     if ((section->num_overlays>=section->sz_overlays)&&
717                                 (_XkbAllocOverlays(section,1)!=Success))
718         return NULL;
719     overlay= &section->overlays[section->num_overlays];
720     if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
721         return NULL;
722     overlay->name= name;
723     overlay->section_under= section;
724     section->num_overlays++;
725     return overlay;
726 }