XKBGAlloc.c revision 5afda2e6
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    _XkbFree(color->spec);
181    return;
182}
183
184void
185XkbFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll)
186{
187    _XkbFreeGeomNonLeafElems(freeAll, first, count,
188                             &geom->num_colors, &geom->sz_colors,
189                             (char **) &geom->colors,
190                             sizeof(XkbColorRec), _XkbClearColor);
191    return;
192}
193
194/***====================================================================***/
195
196void
197XkbFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll)
198{
199    _XkbFreeGeomLeafElems(freeAll, first, count,
200                          &outline->num_points, &outline->sz_points,
201                          (char **) &outline->points,
202                          sizeof(XkbPointRec));
203    return;
204}
205
206/***====================================================================***/
207
208static void
209_XkbClearOutline(char *outline_in)
210{
211    XkbOutlinePtr outline = (XkbOutlinePtr) outline_in;
212
213    if (outline->points != NULL)
214        XkbFreeGeomPoints(outline, 0, outline->num_points, True);
215    return;
216}
217
218void
219XkbFreeGeomOutlines(XkbShapePtr shape, int first, int count, Bool freeAll)
220{
221    _XkbFreeGeomNonLeafElems(freeAll, first, count,
222                             &shape->num_outlines, &shape->sz_outlines,
223                             (char **) &shape->outlines,
224                             sizeof(XkbOutlineRec), _XkbClearOutline);
225
226    return;
227}
228
229/***====================================================================***/
230
231static void
232_XkbClearShape(char *shape_in)
233{
234    XkbShapePtr shape = (XkbShapePtr) shape_in;
235
236    if (shape->outlines)
237        XkbFreeGeomOutlines(shape, 0, shape->num_outlines, True);
238    return;
239}
240
241void
242XkbFreeGeomShapes(XkbGeometryPtr geom, int first, int count, Bool freeAll)
243{
244    _XkbFreeGeomNonLeafElems(freeAll, first, count,
245                             &geom->num_shapes, &geom->sz_shapes,
246                             (char **) &geom->shapes,
247                             sizeof(XkbShapeRec), _XkbClearShape);
248    return;
249}
250
251/***====================================================================***/
252
253void
254XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row, int first, int count, Bool freeAll)
255{
256    _XkbFreeGeomLeafElems(freeAll, first, count,
257                          &row->num_keys, &row->sz_keys,
258                          (char **) &row->keys,
259                          sizeof(XkbOverlayKeyRec));
260    return;
261}
262
263/***====================================================================***/
264
265static void
266_XkbClearOverlayRow(char *row_in)
267{
268    XkbOverlayRowPtr row = (XkbOverlayRowPtr) row_in;
269
270    if (row->keys != NULL)
271        XkbFreeGeomOverlayKeys(row, 0, row->num_keys, True);
272    return;
273}
274
275void
276XkbFreeGeomOverlayRows(XkbOverlayPtr overlay, int first, int count,
277                       Bool freeAll)
278{
279    _XkbFreeGeomNonLeafElems(freeAll, first, count,
280                             &overlay->num_rows, &overlay->sz_rows,
281                             (char **) &overlay->rows,
282                             sizeof(XkbOverlayRowRec), _XkbClearOverlayRow);
283    return;
284}
285
286/***====================================================================***/
287
288static void
289_XkbClearOverlay(char *overlay_in)
290{
291    XkbOverlayPtr overlay = (XkbOverlayPtr) overlay_in;
292
293    if (overlay->rows != NULL)
294        XkbFreeGeomOverlayRows(overlay, 0, overlay->num_rows, True);
295    return;
296}
297
298void
299XkbFreeGeomOverlays(XkbSectionPtr section, int first, int count, Bool freeAll)
300{
301    _XkbFreeGeomNonLeafElems(freeAll, first, count,
302                             &section->num_overlays, &section->sz_overlays,
303                             (char **) &section->overlays,
304                             sizeof(XkbOverlayRec), _XkbClearOverlay);
305    return;
306}
307
308/***====================================================================***/
309
310void
311XkbFreeGeomKeys(XkbRowPtr row, int first, int count, Bool freeAll)
312{
313    _XkbFreeGeomLeafElems(freeAll, first, count,
314                          &row->num_keys, &row->sz_keys,
315                          (char **) &row->keys,
316                          sizeof(XkbKeyRec));
317    return;
318}
319
320/***====================================================================***/
321
322static void
323_XkbClearRow(char *row_in)
324{
325    XkbRowPtr row = (XkbRowPtr) row_in;
326
327    if (row->keys != NULL)
328        XkbFreeGeomKeys(row, 0, row->num_keys, True);
329    return;
330}
331
332void
333XkbFreeGeomRows(XkbSectionPtr section, int first, int count, Bool freeAll)
334{
335    _XkbFreeGeomNonLeafElems(freeAll, first, count,
336                             &section->num_rows, &section->sz_rows,
337                             (char **) &section->rows,
338                             sizeof(XkbRowRec), _XkbClearRow);
339}
340
341/***====================================================================***/
342
343static void
344_XkbClearSection(char *section_in)
345{
346    XkbSectionPtr section = (XkbSectionPtr) section_in;
347
348    if (section->rows != NULL)
349        XkbFreeGeomRows(section, 0, section->num_rows, True);
350    if (section->doodads != NULL) {
351        XkbFreeGeomDoodads(section->doodads, section->num_doodads, True);
352        section->doodads = NULL;
353    }
354    return;
355}
356
357void
358XkbFreeGeomSections(XkbGeometryPtr geom, int first, int count, Bool freeAll)
359{
360    _XkbFreeGeomNonLeafElems(freeAll, first, count,
361                             &geom->num_sections, &geom->sz_sections,
362                             (char **) &geom->sections,
363                             sizeof(XkbSectionRec), _XkbClearSection);
364    return;
365}
366
367/***====================================================================***/
368
369static void
370_XkbClearDoodad(char *doodad_in)
371{
372    XkbDoodadPtr doodad = (XkbDoodadPtr) doodad_in;
373
374    switch (doodad->any.type) {
375    case XkbTextDoodad:
376    {
377        if (doodad->text.text != NULL) {
378            _XkbFree(doodad->text.text);
379            doodad->text.text = NULL;
380        }
381        if (doodad->text.font != NULL) {
382            _XkbFree(doodad->text.font);
383            doodad->text.font = NULL;
384        }
385    }
386        break;
387    case XkbLogoDoodad:
388    {
389        if (doodad->logo.logo_name != NULL) {
390            _XkbFree(doodad->logo.logo_name);
391            doodad->logo.logo_name = NULL;
392        }
393    }
394        break;
395    }
396    return;
397}
398
399void
400XkbFreeGeomDoodads(XkbDoodadPtr doodads, int nDoodads, Bool freeAll)
401{
402    register int i;
403    register XkbDoodadPtr doodad;
404
405    if (doodads) {
406        for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++) {
407            _XkbClearDoodad((char *) doodad);
408        }
409        if (freeAll)
410            _XkbFree(doodads);
411    }
412    return;
413}
414
415void
416XkbFreeGeometry(XkbGeometryPtr geom, unsigned which, Bool freeMap)
417{
418    if (geom == NULL)
419        return;
420    if (freeMap)
421        which = XkbGeomAllMask;
422    if ((which & XkbGeomPropertiesMask) && (geom->properties != NULL))
423        XkbFreeGeomProperties(geom, 0, geom->num_properties, True);
424    if ((which & XkbGeomColorsMask) && (geom->colors != NULL))
425        XkbFreeGeomColors(geom, 0, geom->num_colors, True);
426    if ((which & XkbGeomShapesMask) && (geom->shapes != NULL))
427        XkbFreeGeomShapes(geom, 0, geom->num_shapes, True);
428    if ((which & XkbGeomSectionsMask) && (geom->sections != NULL))
429        XkbFreeGeomSections(geom, 0, geom->num_sections, True);
430    if ((which & XkbGeomDoodadsMask) && (geom->doodads != NULL)) {
431        XkbFreeGeomDoodads(geom->doodads, geom->num_doodads, True);
432        geom->doodads = NULL;
433        geom->num_doodads = geom->sz_doodads = 0;
434    }
435    if ((which & XkbGeomKeyAliasesMask) && (geom->key_aliases != NULL))
436        XkbFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, True);
437    if (freeMap) {
438        if (geom->label_font != NULL) {
439            _XkbFree(geom->label_font);
440            geom->label_font = NULL;
441        }
442        _XkbFree(geom);
443    }
444    return;
445}
446
447/***====================================================================***/
448
449static Status
450_XkbGeomAlloc(XPointer *old,
451              unsigned short *num,
452              unsigned short *total,
453              int num_new,
454              size_t sz_elem)
455{
456    if (num_new < 1)
457        return Success;
458    if ((*old) == NULL)
459        *num = *total = 0;
460
461    if ((*num) + num_new <= (*total))
462        return Success;
463
464    *total = (*num) + num_new;
465    if ((*old) != NULL)
466        (*old) = (XPointer) _XkbRealloc((*old), (*total) * sz_elem);
467    else
468        (*old) = (XPointer) _XkbCalloc((*total), sz_elem);
469    if ((*old) == NULL) {
470        *total = *num = 0;
471        return BadAlloc;
472    }
473
474    if (*num > 0) {
475        char *tmp = (char *) (*old);
476        bzero(&tmp[sz_elem * (*num)], (num_new * sz_elem));
477    }
478    return Success;
479}
480
481#define _XkbAllocProps(g, n) _XkbGeomAlloc((XPointer *)&(g)->properties, \
482                                &(g)->num_properties, &(g)->sz_properties, \
483                                (n), sizeof(XkbPropertyRec))
484#define _XkbAllocColors(g, n) _XkbGeomAlloc((XPointer *)&(g)->colors, \
485                                &(g)->num_colors, &(g)->sz_colors, \
486                                (n), sizeof(XkbColorRec))
487#define _XkbAllocShapes(g, n) _XkbGeomAlloc((XPointer *)&(g)->shapes, \
488                                &(g)->num_shapes, &(g)->sz_shapes, \
489                                (n), sizeof(XkbShapeRec))
490#define _XkbAllocSections(g, n) _XkbGeomAlloc((XPointer *)&(g)->sections, \
491                                &(g)->num_sections, &(g)->sz_sections, \
492                                (n), sizeof(XkbSectionRec))
493#define _XkbAllocDoodads(g, n) _XkbGeomAlloc((XPointer *)&(g)->doodads, \
494                                &(g)->num_doodads, &(g)->sz_doodads, \
495                                (n), sizeof(XkbDoodadRec))
496#define _XkbAllocKeyAliases(g, n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases, \
497                                &(g)->num_key_aliases, &(g)->sz_key_aliases, \
498                                (n), sizeof(XkbKeyAliasRec))
499
500#define _XkbAllocOutlines(s, n) _XkbGeomAlloc((XPointer *)&(s)->outlines, \
501                                &(s)->num_outlines, &(s)->sz_outlines, \
502                                (n), sizeof(XkbOutlineRec))
503#define _XkbAllocRows(s, n) _XkbGeomAlloc((XPointer *)&(s)->rows, \
504                                &(s)->num_rows, &(s)->sz_rows, \
505                                (n), sizeof(XkbRowRec))
506#define _XkbAllocPoints(o, n) _XkbGeomAlloc((XPointer *)&(o)->points, \
507                                &(o)->num_points, &(o)->sz_points, \
508                                (n), sizeof(XkbPointRec))
509#define _XkbAllocKeys(r, n) _XkbGeomAlloc((XPointer *)&(r)->keys, \
510                                &(r)->num_keys, &(r)->sz_keys, \
511                                (n), sizeof(XkbKeyRec))
512#define _XkbAllocOverlays(s, n) _XkbGeomAlloc((XPointer *)&(s)->overlays, \
513                                &(s)->num_overlays, &(s)->sz_overlays, \
514                                (n), sizeof(XkbOverlayRec))
515#define _XkbAllocOverlayRows(o, n) _XkbGeomAlloc((XPointer *)&(o)->rows, \
516                                &(o)->num_rows, &(o)->sz_rows, \
517                                (n), sizeof(XkbOverlayRowRec))
518#define _XkbAllocOverlayKeys(r, n) _XkbGeomAlloc((XPointer *)&(r)->keys, \
519                                &(r)->num_keys, &(r)->sz_keys, \
520                                (n), sizeof(XkbOverlayKeyRec))
521
522Status
523XkbAllocGeomProps(XkbGeometryPtr geom, int nProps)
524{
525    return _XkbAllocProps(geom, nProps);
526}
527
528Status
529XkbAllocGeomColors(XkbGeometryPtr geom, int nColors)
530{
531    return _XkbAllocColors(geom, nColors);
532}
533
534Status
535XkbAllocGeomKeyAliases(XkbGeometryPtr geom, int nKeyAliases)
536{
537    return _XkbAllocKeyAliases(geom, nKeyAliases);
538}
539
540Status
541XkbAllocGeomShapes(XkbGeometryPtr geom, int nShapes)
542{
543    return _XkbAllocShapes(geom, nShapes);
544}
545
546Status
547XkbAllocGeomSections(XkbGeometryPtr geom, int nSections)
548{
549    return _XkbAllocSections(geom, nSections);
550}
551
552Status
553XkbAllocGeomOverlays(XkbSectionPtr section, int nOverlays)
554{
555    return _XkbAllocOverlays(section, nOverlays);
556}
557
558Status
559XkbAllocGeomOverlayRows(XkbOverlayPtr overlay, int nRows)
560{
561    return _XkbAllocOverlayRows(overlay, nRows);
562}
563
564Status
565XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row, int nKeys)
566{
567    return _XkbAllocOverlayKeys(row, nKeys);
568}
569
570Status
571XkbAllocGeomDoodads(XkbGeometryPtr geom, int nDoodads)
572{
573    return _XkbAllocDoodads(geom, nDoodads);
574}
575
576Status
577XkbAllocGeomSectionDoodads(XkbSectionPtr section, int nDoodads)
578{
579    return _XkbAllocDoodads(section, nDoodads);
580}
581
582Status
583XkbAllocGeomOutlines(XkbShapePtr shape, int nOL)
584{
585    return _XkbAllocOutlines(shape, nOL);
586}
587
588Status
589XkbAllocGeomRows(XkbSectionPtr section, int nRows)
590{
591    return _XkbAllocRows(section, nRows);
592}
593
594Status
595XkbAllocGeomPoints(XkbOutlinePtr ol, int nPts)
596{
597    return _XkbAllocPoints(ol, nPts);
598}
599
600Status
601XkbAllocGeomKeys(XkbRowPtr row, int nKeys)
602{
603    return _XkbAllocKeys(row, nKeys);
604}
605
606Status
607XkbAllocGeometry(XkbDescPtr xkb, XkbGeometrySizesPtr sizes)
608{
609    XkbGeometryPtr geom;
610    Status rtrn;
611
612    if (xkb->geom == NULL) {
613        xkb->geom = _XkbTypedCalloc(1, XkbGeometryRec);
614        if (!xkb->geom)
615            return BadAlloc;
616    }
617    geom = xkb->geom;
618    if ((sizes->which & XkbGeomPropertiesMask) &&
619        ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success)) {
620        goto BAIL;
621    }
622    if ((sizes->which & XkbGeomColorsMask) &&
623        ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success)) {
624        goto BAIL;
625    }
626    if ((sizes->which & XkbGeomShapesMask) &&
627        ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success)) {
628        goto BAIL;
629    }
630    if ((sizes->which & XkbGeomSectionsMask) &&
631        ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success)) {
632        goto BAIL;
633    }
634    if ((sizes->which & XkbGeomDoodadsMask) &&
635        ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success)) {
636        goto BAIL;
637    }
638    if ((sizes->which & XkbGeomKeyAliasesMask) &&
639        ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases))
640         != Success)) {
641        goto BAIL;
642    }
643    return Success;
644 BAIL:
645    XkbFreeGeometry(geom, XkbGeomAllMask, True);
646    xkb->geom = NULL;
647    return rtrn;
648}
649
650/***====================================================================***/
651
652XkbPropertyPtr
653XkbAddGeomProperty(XkbGeometryPtr geom, char *name, char *value)
654{
655    register int i;
656    register XkbPropertyPtr prop;
657
658    if ((!geom) || (!name) || (!value))
659        return NULL;
660    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
661        if ((prop->name) && (strcmp(name, prop->name) == 0)) {
662            _XkbFree(prop->value);
663            prop->value = strdup(value);
664            return prop;
665        }
666    }
667    if ((geom->num_properties >= geom->sz_properties) &&
668        (_XkbAllocProps(geom, 1) != Success)) {
669        return NULL;
670    }
671    prop = &geom->properties[geom->num_properties];
672    prop->name = strdup(name);
673    if (!prop->name)
674        return NULL;
675    prop->value = strdup(value);
676    if (!prop->value) {
677        _XkbFree(prop->name);
678        prop->name = NULL;
679        return NULL;
680    }
681    geom->num_properties++;
682    return prop;
683}
684
685XkbKeyAliasPtr
686XkbAddGeomKeyAlias(XkbGeometryPtr geom, char *aliasStr, char *realStr)
687{
688    register int i;
689    register XkbKeyAliasPtr alias;
690
691    if ((!geom) || (!aliasStr) || (!realStr) || (!aliasStr[0]) || (!realStr[0]))
692        return NULL;
693    for (i = 0, alias = geom->key_aliases; i < geom->num_key_aliases;
694         i++, alias++) {
695        if (strncmp(alias->alias, aliasStr, XkbKeyNameLength) == 0) {
696            bzero(alias->real, XkbKeyNameLength);
697            strncpy(alias->real, realStr, XkbKeyNameLength);
698            return alias;
699        }
700    }
701    if ((geom->num_key_aliases >= geom->sz_key_aliases) &&
702        (_XkbAllocKeyAliases(geom, 1) != Success)) {
703        return NULL;
704    }
705    alias = &geom->key_aliases[geom->num_key_aliases];
706    bzero(alias, sizeof(XkbKeyAliasRec));
707    strncpy(alias->alias, aliasStr, XkbKeyNameLength);
708    strncpy(alias->real, realStr, XkbKeyNameLength);
709    geom->num_key_aliases++;
710    return alias;
711}
712
713XkbColorPtr
714XkbAddGeomColor(XkbGeometryPtr geom, char *spec, unsigned int pixel)
715{
716    register int i;
717    register XkbColorPtr color;
718
719    if ((!geom) || (!spec))
720        return NULL;
721    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
722        if ((color->spec) && (strcmp(color->spec, spec) == 0)) {
723            color->pixel = pixel;
724            return color;
725        }
726    }
727    if ((geom->num_colors >= geom->sz_colors) &&
728        (_XkbAllocColors(geom, 1) != Success)) {
729        return NULL;
730    }
731    color = &geom->colors[geom->num_colors];
732    color->pixel = pixel;
733    color->spec = strdup(spec);
734    if (!color->spec)
735        return NULL;
736    geom->num_colors++;
737    return color;
738}
739
740XkbOutlinePtr
741XkbAddGeomOutline(XkbShapePtr shape, int sz_points)
742{
743    XkbOutlinePtr outline;
744
745    if ((!shape) || (sz_points < 0))
746        return NULL;
747    if ((shape->num_outlines >= shape->sz_outlines) &&
748        (_XkbAllocOutlines(shape, 1) != Success)) {
749        return NULL;
750    }
751    outline = &shape->outlines[shape->num_outlines];
752    bzero(outline, sizeof(XkbOutlineRec));
753    if ((sz_points > 0) && (_XkbAllocPoints(outline, sz_points) != Success))
754        return NULL;
755    shape->num_outlines++;
756    return outline;
757}
758
759XkbShapePtr
760XkbAddGeomShape(XkbGeometryPtr geom, Atom name, int sz_outlines)
761{
762    XkbShapePtr shape;
763    register int i;
764
765    if ((!geom) || (!name) || (sz_outlines < 0))
766        return NULL;
767    if (geom->num_shapes > 0) {
768        for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
769            if (name == shape->name)
770                return shape;
771        }
772    }
773    if ((geom->num_shapes >= geom->sz_shapes) &&
774        (_XkbAllocShapes(geom, 1) != Success))
775        return NULL;
776    shape = &geom->shapes[geom->num_shapes];
777    bzero(shape, sizeof(XkbShapeRec));
778    if ((sz_outlines > 0) && (_XkbAllocOutlines(shape, sz_outlines) != Success))
779        return NULL;
780    shape->name = name;
781    shape->primary = shape->approx = NULL;
782    geom->num_shapes++;
783    return shape;
784}
785
786XkbKeyPtr
787XkbAddGeomKey(XkbRowPtr row)
788{
789    XkbKeyPtr key;
790
791    if (!row)
792        return NULL;
793    if ((row->num_keys >= row->sz_keys) && (_XkbAllocKeys(row, 1) != Success))
794        return NULL;
795    key = &row->keys[row->num_keys++];
796    bzero(key, sizeof(XkbKeyRec));
797    return key;
798}
799
800XkbRowPtr
801XkbAddGeomRow(XkbSectionPtr section, int sz_keys)
802{
803    XkbRowPtr row;
804
805    if ((!section) || (sz_keys < 0))
806        return NULL;
807    if ((section->num_rows >= section->sz_rows) &&
808        (_XkbAllocRows(section, 1) != Success))
809        return NULL;
810    row = &section->rows[section->num_rows];
811    bzero(row, sizeof(XkbRowRec));
812    if ((sz_keys > 0) && (_XkbAllocKeys(row, sz_keys) != Success))
813        return NULL;
814    section->num_rows++;
815    return row;
816}
817
818XkbSectionPtr
819XkbAddGeomSection(XkbGeometryPtr geom,
820                  Atom name,
821                  int sz_rows,
822                  int sz_doodads,
823                  int sz_over)
824{
825    register int i;
826    XkbSectionPtr section;
827
828    if ((!geom) || (name == None) || (sz_rows < 0))
829        return NULL;
830    for (i = 0, section = geom->sections; i < geom->num_sections;
831         i++, section++) {
832        if (section->name != name)
833            continue;
834        if (((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success)) ||
835            ((sz_doodads > 0) &&
836             (_XkbAllocDoodads(section, sz_doodads) != Success)) ||
837            ((sz_over > 0) && (_XkbAllocOverlays(section, sz_over) != Success)))
838            return NULL;
839        return section;
840    }
841    if ((geom->num_sections >= geom->sz_sections) &&
842        (_XkbAllocSections(geom, 1) != Success))
843        return NULL;
844    section = &geom->sections[geom->num_sections];
845    if ((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success))
846        return NULL;
847    if ((sz_doodads > 0) && (_XkbAllocDoodads(section, sz_doodads) != Success)) {
848        if (section->rows) {
849            _XkbFree(section->rows);
850            section->rows = NULL;
851            section->sz_rows = section->num_rows = 0;
852        }
853        return NULL;
854    }
855    section->name = name;
856    geom->num_sections++;
857    return section;
858}
859
860XkbDoodadPtr
861XkbAddGeomDoodad(XkbGeometryPtr geom, XkbSectionPtr section, Atom name)
862{
863    XkbDoodadPtr old, doodad;
864    register int i, nDoodads;
865
866    if ((!geom) || (name == None))
867        return NULL;
868    if ((section != NULL) && (section->num_doodads > 0)) {
869        old = section->doodads;
870        nDoodads = section->num_doodads;
871    }
872    else {
873        old = geom->doodads;
874        nDoodads = geom->num_doodads;
875    }
876    for (i = 0, doodad = old; i < nDoodads; i++, doodad++) {
877        if (doodad->any.name == name)
878            return doodad;
879    }
880    if (section) {
881        if ((section->num_doodads >= geom->sz_doodads) &&
882            (_XkbAllocDoodads(section, 1) != Success)) {
883            return NULL;
884        }
885        doodad = &section->doodads[section->num_doodads++];
886    }
887    else {
888        if ((geom->num_doodads >= geom->sz_doodads) &&
889            (_XkbAllocDoodads(geom, 1) != Success))
890            return NULL;
891        doodad = &geom->doodads[geom->num_doodads++];
892    }
893    bzero(doodad, sizeof(XkbDoodadRec));
894    doodad->any.name = name;
895    return doodad;
896}
897
898XkbOverlayKeyPtr
899XkbAddGeomOverlayKey(XkbOverlayPtr overlay,
900                     XkbOverlayRowPtr row,
901                     char *over,
902                     char *under)
903{
904    register int i;
905    XkbOverlayKeyPtr key;
906    XkbSectionPtr section;
907    XkbRowPtr row_under;
908    Bool found;
909
910    if ((!overlay) || (!row) || (!over) || (!under))
911        return NULL;
912    section = overlay->section_under;
913    if (row->row_under >= section->num_rows)
914        return NULL;
915    row_under = &section->rows[row->row_under];
916    for (i = 0, found = False; i < row_under->num_keys; i++) {
917        if (strncmp(under, row_under->keys[i].name.name, XkbKeyNameLength) == 0) {
918            found = True;
919            break;
920        }
921    }
922    if (!found)
923        return NULL;
924    if ((row->num_keys >= row->sz_keys) &&
925        (_XkbAllocOverlayKeys(row, 1) != Success))
926        return NULL;
927    key = &row->keys[row->num_keys];
928    strncpy(key->under.name, under, XkbKeyNameLength);
929    strncpy(key->over.name, over, XkbKeyNameLength);
930    row->num_keys++;
931    return key;
932}
933
934XkbOverlayRowPtr
935XkbAddGeomOverlayRow(XkbOverlayPtr overlay, int row_under, int sz_keys)
936{
937    register int i;
938    XkbOverlayRowPtr row;
939
940    if ((!overlay) || (sz_keys < 0))
941        return NULL;
942    if (row_under >= overlay->section_under->num_rows)
943        return NULL;
944    for (i = 0; i < overlay->num_rows; i++) {
945        if (overlay->rows[i].row_under == row_under) {
946            row = &overlay->rows[i];
947            if ((row->sz_keys < sz_keys) &&
948                (_XkbAllocOverlayKeys(row, sz_keys) != Success)) {
949                return NULL;
950            }
951            return &overlay->rows[i];
952        }
953    }
954    if ((overlay->num_rows >= overlay->sz_rows) &&
955        (_XkbAllocOverlayRows(overlay, 1) != Success))
956        return NULL;
957    row = &overlay->rows[overlay->num_rows];
958    bzero(row, sizeof(XkbOverlayRowRec));
959    if ((sz_keys > 0) && (_XkbAllocOverlayKeys(row, sz_keys) != Success))
960        return NULL;
961    row->row_under = row_under;
962    overlay->num_rows++;
963    return row;
964}
965
966XkbOverlayPtr
967XkbAddGeomOverlay(XkbSectionPtr section, Atom name, int sz_rows)
968{
969    register int i;
970    XkbOverlayPtr overlay;
971
972    if ((!section) || (name == None) || (sz_rows == 0))
973        return NULL;
974
975    for (i = 0, overlay = section->overlays; i < section->num_overlays;
976         i++, overlay++) {
977        if (overlay->name == name) {
978            if ((sz_rows > 0) &&
979                (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
980                return NULL;
981            return overlay;
982        }
983    }
984    if ((section->num_overlays >= section->sz_overlays) &&
985        (_XkbAllocOverlays(section, 1) != Success))
986        return NULL;
987    overlay = &section->overlays[section->num_overlays];
988    if ((sz_rows > 0) && (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
989        return NULL;
990    overlay->name = name;
991    overlay->section_under = section;
992    section->num_overlays++;
993    return overlay;
994}
995