XKBGAlloc.c revision e9628295
11.16Suwe/************************************************************
21.10SmattCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
31.10Smatt
41.10SmattPermission to use, copy, modify, and distribute this
51.1Sthorpejsoftware and its documentation for any purpose and without
61.3Skleinkfee is hereby granted, provided that the above copyright
71.1Sthorpejnotice appear in all copies and that both that copyright
81.3Skleinknotice and this permission notice appear in supporting
91.1Sthorpejdocumentation, and that the name of Silicon Graphics not be
101.1Sthorpejused in advertising or publicity pertaining to distribution
111.6Srossof the software without specific prior written permission.
121.1SthorpejSilicon Graphics makes no representation about the suitability
131.6Srossof this software for any purpose. It is provided "as is"
141.6Srosswithout any express or implied warranty.
151.5Sthorpej
161.5SthorpejSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
171.6SrossSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181.4SminouraAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
191.14SchristosGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
201.6SrossDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
211.15SchristosDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221.6SrossOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231.6SrossTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241.15Schristos
251.4Sminoura********************************************************/
261.6Sross
271.1Sthorpej#ifdef HAVE_CONFIG_H
281.9Smatt#include <config.h>
291.9Smatt#endif
301.11Smatt
311.11Smatt
321.11Smatt#include <stdio.h>
331.11Smatt#include "Xlibint.h"
341.9Smatt#include "XKBlibint.h"
351.10Smatt#include "X11/extensions/XKBgeom.h"
361.10Smatt#include <X11/extensions/XKBproto.h>
371.10Smatt
381.10Smatt/***====================================================================***/
391.10Smatt
401.10Smattstatic void
411.10Smatt_XkbFreeGeomLeafElems(Bool freeAll,
421.10Smatt                      int first,
431.10Smatt                      int count,
441.10Smatt                      unsigned short *num_inout,
451.10Smatt                      unsigned short *sz_inout,
461.10Smatt                      char **elems,
471.10Smatt                      unsigned int elem_sz)
481.10Smatt{
491.10Smatt    if ((freeAll) || (*elems == NULL)) {
501.10Smatt        *num_inout = *sz_inout = 0;
511.10Smatt        if (*elems != NULL) {
521.10Smatt            _XkbFree(*elems);
531.10Smatt            *elems = NULL;
541.10Smatt        }
551.10Smatt        return;
561.10Smatt    }
571.10Smatt
581.10Smatt    if ((first >= (*num_inout)) || (first < 0) || (count < 1))
591.10Smatt        return;
601.10Smatt
611.10Smatt    if (first + count >= (*num_inout)) {
621.10Smatt        /* truncating the array is easy */
631.10Smatt        (*num_inout) = first;
641.10Smatt    }
651.10Smatt    else {
661.10Smatt        char *ptr;
671.10Smatt        int extra;
681.10Smatt
691.10Smatt        ptr = *elems;
701.10Smatt        extra = ((*num_inout) - (first + count)) * elem_sz;
711.10Smatt        if (extra > 0)
721.10Smatt            memmove(&ptr[(unsigned) first * elem_sz], &ptr[(unsigned)(first + count) * elem_sz],
731.10Smatt                    (size_t) extra);
741.16Suwe        (*num_inout) -= count;
751.10Smatt    }
761.10Smatt    return;
771.10Smatt}
781.10Smatt
791.10Smatttypedef void (*ContentsClearFunc) (
801.10Smatt    char *       /* priv */
811.10Smatt);
821.10Smatt
831.7Sfrezastatic void
841.10Smatt_XkbFreeGeomNonLeafElems(Bool freeAll,
851.10Smatt                         int first,
861.10Smatt                         int count,
871.10Smatt                         unsigned short *num_inout,
881.10Smatt                         unsigned short *sz_inout,
891.10Smatt                         char **elems,
901.10Smatt                         unsigned int elem_sz,
911.10Smatt                         ContentsClearFunc freeFunc)
921.10Smatt{
931.10Smatt    register int i;
941.10Smatt    register char *ptr;
951.10Smatt
961.10Smatt    if (freeAll) {
971.10Smatt        first = 0;
981.10Smatt        count = (*num_inout);
991.10Smatt    }
1001.10Smatt    else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
1011.10Smatt        return;
1021.10Smatt    else if (first + count > (*num_inout))
1031.10Smatt        count = (*num_inout) - first;
1041.7Sfreza    if (*elems == NULL)
1051.10Smatt        return;
1061.10Smatt
1071.10Smatt    if (freeFunc) {
1081.10Smatt        ptr = *elems;
1091.10Smatt        ptr += first * elem_sz;
1101.10Smatt        for (i = 0; i < count; i++) {
1111.10Smatt            (*freeFunc) (ptr);
1121.10Smatt            ptr += elem_sz;
1131.10Smatt        }
1141.10Smatt    }
1151.10Smatt    if (freeAll) {
1161.10Smatt        (*num_inout) = (*sz_inout) = 0;
1171.10Smatt        if (*elems) {
1181.10Smatt            _XkbFree(*elems);
1191.10Smatt            *elems = NULL;
1201.10Smatt        }
1211.10Smatt    }
1221.10Smatt    else if (first + count >= (*num_inout))
1231.10Smatt        *num_inout = first;
1241.10Smatt    else {
1251.10Smatt        i = ((*num_inout) - (first + count)) * elem_sz;
1261.10Smatt        ptr = *elems;
1271.10Smatt        memmove(&ptr[(unsigned) first * elem_sz], &ptr[(unsigned)(first + count) * elem_sz], (size_t) i);
1281.10Smatt        (*num_inout) -= count;
1291.10Smatt    }
1301.10Smatt    return;
1311.10Smatt}
1321.10Smatt
1331.10Smatt/***====================================================================***/
1341.10Smatt
1351.10Smattstatic void
1361.10Smatt_XkbClearProperty(char *prop_in)
1371.10Smatt{
1381.10Smatt    XkbPropertyPtr prop = (XkbPropertyPtr) prop_in;
1391.10Smatt
1401.10Smatt    if (prop->name) {
1411.10Smatt        _XkbFree(prop->name);
1421.10Smatt        prop->name = NULL;
1431.10Smatt    }
1441.10Smatt    if (prop->value) {
1451.10Smatt        _XkbFree(prop->value);
1461.10Smatt        prop->value = NULL;
1471.10Smatt    }
1481.10Smatt    return;
1491.10Smatt}
1501.10Smatt
1511.2Stsubaivoid
1521.8SskrllXkbFreeGeomProperties(XkbGeometryPtr geom, int first, int count, Bool freeAll)
1531.10Smatt{
1541.8Sskrll    _XkbFreeGeomNonLeafElems(freeAll, first, count,
1551.10Smatt                             &geom->num_properties, &geom->sz_properties,
1561.10Smatt                             (char **) &geom->properties,
1571.10Smatt                             sizeof(XkbPropertyRec), _XkbClearProperty);
1581.10Smatt    return;
1591.10Smatt}
1601.10Smatt
1611.10Smatt/***====================================================================***/
1621.10Smatt
1631.10Smattvoid
1641.10SmattXkbFreeGeomKeyAliases(XkbGeometryPtr geom, int first, int count, Bool freeAll)
1651.10Smatt{
1661.10Smatt    _XkbFreeGeomLeafElems(freeAll, first, count,
1671.10Smatt                          &geom->num_key_aliases, &geom->sz_key_aliases,
1681.10Smatt                          (char **) &geom->key_aliases,
1691.10Smatt                          sizeof(XkbKeyAliasRec));
1701.10Smatt    return;
1711.10Smatt}
1721.10Smatt
1731.10Smatt/***====================================================================***/
1741.10Smatt
1751.10Smattstatic void
1761.10Smatt_XkbClearColor(char *color_in)
1771.10Smatt{
1781.10Smatt    XkbColorPtr color = (XkbColorPtr) color_in;
1791.10Smatt
1801.10Smatt    _XkbFree(color->spec);
1811.10Smatt    return;
1821.10Smatt}
1831.10Smatt
1841.8Sskrllvoid
1851.8SskrllXkbFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll)
1861.8Sskrll{
1871.10Smatt    _XkbFreeGeomNonLeafElems(freeAll, first, count,
1881.10Smatt                             &geom->num_colors, &geom->sz_colors,
1891.10Smatt                             (char **) &geom->colors,
1901.10Smatt                             sizeof(XkbColorRec), _XkbClearColor);
1911.10Smatt    return;
1921.10Smatt}
1931.10Smatt
1941.10Smatt/***====================================================================***/
1951.10Smatt
1961.10Smattvoid
1971.10SmattXkbFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll)
1981.10Smatt{
1991.10Smatt    _XkbFreeGeomLeafElems(freeAll, first, count,
2001.10Smatt                          &outline->num_points, &outline->sz_points,
2011.10Smatt                          (char **) &outline->points,
2021.13Sjoerg                          sizeof(XkbPointRec));
2031.13Sjoerg    return;
2041.13Sjoerg}
2051.9Smatt
2061.10Smatt/***====================================================================***/
2071.10Smatt
2081.10Smattstatic void
2091.10Smatt_XkbClearOutline(char *outline_in)
2101.9Smatt{
2111.7Sfreza    XkbOutlinePtr outline = (XkbOutlinePtr) outline_in;
2121.10Smatt
2131.10Smatt    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