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