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[(unsigned) first * elem_sz], &ptr[(unsigned)(first + count) * elem_sz],
73                    (size_t) 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[(unsigned) first * elem_sz], &ptr[(unsigned)(first + count) * elem_sz], (size_t) 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, _Xconst char *name, _Xconst 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, _Xconst char *aliasStr,
687                   _Xconst char *realStr)
688{
689    register int i;
690    register XkbKeyAliasPtr alias;
691
692    if ((!geom) || (!aliasStr) || (!realStr) || (!aliasStr[0]) || (!realStr[0]))
693        return NULL;
694    for (i = 0, alias = geom->key_aliases; i < geom->num_key_aliases;
695         i++, alias++) {
696        if (strncmp(alias->alias, aliasStr, XkbKeyNameLength) == 0) {
697            bzero(alias->real, XkbKeyNameLength);
698            strncpy(alias->real, realStr, XkbKeyNameLength);
699            return alias;
700        }
701    }
702    if ((geom->num_key_aliases >= geom->sz_key_aliases) &&
703        (_XkbAllocKeyAliases(geom, 1) != Success)) {
704        return NULL;
705    }
706    alias = &geom->key_aliases[geom->num_key_aliases];
707    bzero(alias, sizeof(XkbKeyAliasRec));
708    strncpy(alias->alias, aliasStr, XkbKeyNameLength);
709    strncpy(alias->real, realStr, XkbKeyNameLength);
710    geom->num_key_aliases++;
711    return alias;
712}
713
714XkbColorPtr
715XkbAddGeomColor(XkbGeometryPtr geom, _Xconst char *spec, unsigned int pixel)
716{
717    register int i;
718    register XkbColorPtr color;
719
720    if ((!geom) || (!spec))
721        return NULL;
722    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
723        if ((color->spec) && (strcmp(color->spec, spec) == 0)) {
724            color->pixel = pixel;
725            return color;
726        }
727    }
728    if ((geom->num_colors >= geom->sz_colors) &&
729        (_XkbAllocColors(geom, 1) != Success)) {
730        return NULL;
731    }
732    color = &geom->colors[geom->num_colors];
733    color->pixel = pixel;
734    color->spec = strdup(spec);
735    if (!color->spec)
736        return NULL;
737    geom->num_colors++;
738    return color;
739}
740
741XkbOutlinePtr
742XkbAddGeomOutline(XkbShapePtr shape, int sz_points)
743{
744    XkbOutlinePtr outline;
745
746    if ((!shape) || (sz_points < 0))
747        return NULL;
748    if ((shape->num_outlines >= shape->sz_outlines) &&
749        (_XkbAllocOutlines(shape, 1) != Success)) {
750        return NULL;
751    }
752    outline = &shape->outlines[shape->num_outlines];
753    bzero(outline, sizeof(XkbOutlineRec));
754    if ((sz_points > 0) && (_XkbAllocPoints(outline, sz_points) != Success))
755        return NULL;
756    shape->num_outlines++;
757    return outline;
758}
759
760XkbShapePtr
761XkbAddGeomShape(XkbGeometryPtr geom, Atom name, int sz_outlines)
762{
763    XkbShapePtr shape;
764    register int i;
765
766    if ((!geom) || (!name) || (sz_outlines < 0))
767        return NULL;
768    if (geom->num_shapes > 0) {
769        for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
770            if (name == shape->name)
771                return shape;
772        }
773    }
774    if ((geom->num_shapes >= geom->sz_shapes) &&
775        (_XkbAllocShapes(geom, 1) != Success))
776        return NULL;
777    shape = &geom->shapes[geom->num_shapes];
778    bzero(shape, sizeof(XkbShapeRec));
779    if ((sz_outlines > 0) && (_XkbAllocOutlines(shape, sz_outlines) != Success))
780        return NULL;
781    shape->name = name;
782    shape->primary = shape->approx = NULL;
783    geom->num_shapes++;
784    return shape;
785}
786
787XkbKeyPtr
788XkbAddGeomKey(XkbRowPtr row)
789{
790    XkbKeyPtr key;
791
792    if (!row)
793        return NULL;
794    if ((row->num_keys >= row->sz_keys) && (_XkbAllocKeys(row, 1) != Success))
795        return NULL;
796    key = &row->keys[row->num_keys++];
797    bzero(key, sizeof(XkbKeyRec));
798    return key;
799}
800
801XkbRowPtr
802XkbAddGeomRow(XkbSectionPtr section, int sz_keys)
803{
804    XkbRowPtr row;
805
806    if ((!section) || (sz_keys < 0))
807        return NULL;
808    if ((section->num_rows >= section->sz_rows) &&
809        (_XkbAllocRows(section, 1) != Success))
810        return NULL;
811    row = &section->rows[section->num_rows];
812    bzero(row, sizeof(XkbRowRec));
813    if ((sz_keys > 0) && (_XkbAllocKeys(row, sz_keys) != Success))
814        return NULL;
815    section->num_rows++;
816    return row;
817}
818
819XkbSectionPtr
820XkbAddGeomSection(XkbGeometryPtr geom,
821                  Atom name,
822                  int sz_rows,
823                  int sz_doodads,
824                  int sz_over)
825{
826    register int i;
827    XkbSectionPtr section;
828
829    if ((!geom) || (name == None) || (sz_rows < 0))
830        return NULL;
831    for (i = 0, section = geom->sections; i < geom->num_sections;
832         i++, section++) {
833        if (section->name != name)
834            continue;
835        if (((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success)) ||
836            ((sz_doodads > 0) &&
837             (_XkbAllocDoodads(section, sz_doodads) != Success)) ||
838            ((sz_over > 0) && (_XkbAllocOverlays(section, sz_over) != Success)))
839            return NULL;
840        return section;
841    }
842    if ((geom->num_sections >= geom->sz_sections) &&
843        (_XkbAllocSections(geom, 1) != Success))
844        return NULL;
845    section = &geom->sections[geom->num_sections];
846    if ((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success))
847        return NULL;
848    if ((sz_doodads > 0) && (_XkbAllocDoodads(section, sz_doodads) != Success)) {
849        if (section->rows) {
850            _XkbFree(section->rows);
851            section->rows = NULL;
852            section->sz_rows = section->num_rows = 0;
853        }
854        return NULL;
855    }
856    section->name = name;
857    geom->num_sections++;
858    return section;
859}
860
861XkbDoodadPtr
862XkbAddGeomDoodad(XkbGeometryPtr geom, XkbSectionPtr section, Atom name)
863{
864    XkbDoodadPtr old, doodad;
865    register int i, nDoodads;
866
867    if ((!geom) || (name == None))
868        return NULL;
869    if ((section != NULL) && (section->num_doodads > 0)) {
870        old = section->doodads;
871        nDoodads = section->num_doodads;
872    }
873    else {
874        old = geom->doodads;
875        nDoodads = geom->num_doodads;
876    }
877    for (i = 0, doodad = old; i < nDoodads; i++, doodad++) {
878        if (doodad->any.name == name)
879            return doodad;
880    }
881    if (section) {
882        if ((section->num_doodads >= geom->sz_doodads) &&
883            (_XkbAllocDoodads(section, 1) != Success)) {
884            return NULL;
885        }
886        doodad = &section->doodads[section->num_doodads++];
887    }
888    else {
889        if ((geom->num_doodads >= geom->sz_doodads) &&
890            (_XkbAllocDoodads(geom, 1) != Success))
891            return NULL;
892        doodad = &geom->doodads[geom->num_doodads++];
893    }
894    bzero(doodad, sizeof(XkbDoodadRec));
895    doodad->any.name = name;
896    return doodad;
897}
898
899XkbOverlayKeyPtr
900XkbAddGeomOverlayKey(XkbOverlayPtr overlay,
901                     XkbOverlayRowPtr row,
902                     _Xconst char *over,
903                     _Xconst char *under)
904{
905    register int i;
906    XkbOverlayKeyPtr key;
907    XkbSectionPtr section;
908    XkbRowPtr row_under;
909    Bool found;
910
911    if ((!overlay) || (!row) || (!over) || (!under))
912        return NULL;
913    section = overlay->section_under;
914    if (row->row_under >= section->num_rows)
915        return NULL;
916    row_under = &section->rows[row->row_under];
917    for (i = 0, found = False; i < row_under->num_keys; i++) {
918        if (strncmp(under, row_under->keys[i].name.name, XkbKeyNameLength) == 0) {
919            found = True;
920            break;
921        }
922    }
923    if (!found)
924        return NULL;
925    if ((row->num_keys >= row->sz_keys) &&
926        (_XkbAllocOverlayKeys(row, 1) != Success))
927        return NULL;
928    key = &row->keys[row->num_keys];
929    strncpy(key->under.name, under, XkbKeyNameLength);
930    strncpy(key->over.name, over, XkbKeyNameLength);
931    row->num_keys++;
932    return key;
933}
934
935XkbOverlayRowPtr
936XkbAddGeomOverlayRow(XkbOverlayPtr overlay, int row_under, int sz_keys)
937{
938    register int i;
939    XkbOverlayRowPtr row;
940
941    if ((!overlay) || (sz_keys < 0))
942        return NULL;
943    if (row_under >= overlay->section_under->num_rows)
944        return NULL;
945    for (i = 0; i < overlay->num_rows; i++) {
946        if (overlay->rows[i].row_under == row_under) {
947            row = &overlay->rows[i];
948            if ((row->sz_keys < sz_keys) &&
949                (_XkbAllocOverlayKeys(row, sz_keys) != Success)) {
950                return NULL;
951            }
952            return &overlay->rows[i];
953        }
954    }
955    if ((overlay->num_rows >= overlay->sz_rows) &&
956        (_XkbAllocOverlayRows(overlay, 1) != Success))
957        return NULL;
958    row = &overlay->rows[overlay->num_rows];
959    bzero(row, sizeof(XkbOverlayRowRec));
960    if ((sz_keys > 0) && (_XkbAllocOverlayKeys(row, sz_keys) != Success))
961        return NULL;
962    row->row_under = row_under;
963    overlay->num_rows++;
964    return row;
965}
966
967XkbOverlayPtr
968XkbAddGeomOverlay(XkbSectionPtr section, Atom name, int sz_rows)
969{
970    register int i;
971    XkbOverlayPtr overlay;
972
973    if ((!section) || (name == None) || (sz_rows == 0))
974        return NULL;
975
976    for (i = 0, overlay = section->overlays; i < section->num_overlays;
977         i++, overlay++) {
978        if (overlay->name == name) {
979            if ((sz_rows > 0) &&
980                (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
981                return NULL;
982            return overlay;
983        }
984    }
985    if ((section->num_overlays >= section->sz_overlays) &&
986        (_XkbAllocOverlays(section, 1) != Success))
987        return NULL;
988    overlay = &section->overlays[section->num_overlays];
989    if ((sz_rows > 0) && (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
990        return NULL;
991    overlay->name = name;
992    overlay->section_under = section;
993    section->num_overlays++;
994    return overlay;
995}
996