XKBGAlloc.c 25.9 KB
Newer Older
1 2 3 4 5 6 7 8
/************************************************************
Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
9 10
documentation, and that the name of Silicon Graphics not be
used in advertising or publicity pertaining to distribution
11
of the software without specific prior written permission.
12
Silicon Graphics makes no representation about the suitability
13 14 15
of this software for any purpose. It is provided "as is"
without any express or implied warranty.

16 17
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 20 21
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 23 24 25 26
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.

********************************************************/

27 28 29 30
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

31
#include <stdio.h>
32 33
#include <X11/X.h>
#include <X11/Xproto.h>
34 35
#include "misc.h"
#include "inputstr.h"
36
#include <xkbsrv.h>
37
#include "xkbgeom.h"
38 39 40

/***====================================================================***/

41 42 43 44 45 46 47
static void
_XkbFreeGeomLeafElems(Bool freeAll,
                      int first,
                      int count,
                      unsigned short *num_inout,
                      unsigned short *sz_inout,
                      char **elems, unsigned int elem_sz)
48
{
49 50 51 52 53
    if ((freeAll) || (*elems == NULL)) {
        *num_inout = *sz_inout = 0;
        free(*elems);
        *elems = NULL;
        return;
54 55
    }

56 57
    if ((first >= (*num_inout)) || (first < 0) || (count < 1))
        return;
58

59 60 61
    if (first + count >= (*num_inout)) {
        /* truncating the array is easy */
        (*num_inout) = first;
62 63
    }
    else {
64 65 66 67 68 69 70 71 72
        char *ptr;
        int extra;

        ptr = *elems;
        extra = ((*num_inout) - (first + count)) * elem_sz;
        if (extra > 0)
            memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz],
                    extra);
        (*num_inout) -= count;
73 74 75 76
    }
    return;
}

77 78
typedef void (*ContentsClearFunc) (char *       /* priv */
    );
79

80 81 82 83 84 85 86 87
static void
_XkbFreeGeomNonLeafElems(Bool freeAll,
                         int first,
                         int count,
                         unsigned short *num_inout,
                         unsigned short *sz_inout,
                         char **elems,
                         unsigned int elem_sz, ContentsClearFunc freeFunc)
88
{
89 90
    register int i;
    register char *ptr;
91 92

    if (freeAll) {
93 94
        first = 0;
        count = (*num_inout);
95
    }
96 97 98 99 100 101
    else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
        return;
    else if (first + count > (*num_inout))
        count = (*num_inout) - first;
    if (*elems == NULL)
        return;
102 103

    if (freeFunc) {
104 105 106 107 108 109
        ptr = *elems;
        ptr += first * elem_sz;
        for (i = 0; i < count; i++) {
            (*freeFunc) (ptr);
            ptr += elem_sz;
        }
110 111
    }
    if (freeAll) {
112 113 114
        (*num_inout) = (*sz_inout) = 0;
        free(*elems);
        *elems = NULL;
115
    }
116 117
    else if (first + count >= (*num_inout))
        *num_inout = first;
118
    else {
119 120 121 122
        i = ((*num_inout) - (first + count)) * elem_sz;
        ptr = *elems;
        memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz], i);
        (*num_inout) -= count;
123 124 125 126 127 128 129 130 131
    }
    return;
}

/***====================================================================***/

static void
_XkbClearProperty(char *prop_in)
{
132
    XkbPropertyPtr prop = (XkbPropertyPtr) prop_in;
133

134 135 136 137
    free(prop->name);
    prop->name = NULL;
    free(prop->value);
    prop->value = NULL;
138 139 140 141
    return;
}

void
142 143 144 145 146 147
XkbFreeGeomProperties(XkbGeometryPtr geom, int first, int count, Bool freeAll)
{
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &geom->num_properties, &geom->sz_properties,
                             (char **) &geom->properties,
                             sizeof(XkbPropertyRec), _XkbClearProperty);
148 149 150 151 152 153
    return;
}

/***====================================================================***/

void
154 155 156 157 158
XkbFreeGeomKeyAliases(XkbGeometryPtr geom, int first, int count, Bool freeAll)
{
    _XkbFreeGeomLeafElems(freeAll, first, count,
                          &geom->num_key_aliases, &geom->sz_key_aliases,
                          (char **) &geom->key_aliases, sizeof(XkbKeyAliasRec));
159 160 161 162 163 164 165 166
    return;
}

/***====================================================================***/

static void
_XkbClearColor(char *color_in)
{
167
    XkbColorPtr color = (XkbColorPtr) color_in;
168

169
    free(color->spec);
170 171 172 173
    return;
}

void
174
XkbFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll)
175
{
176 177 178 179
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &geom->num_colors, &geom->sz_colors,
                             (char **) &geom->colors,
                             sizeof(XkbColorRec), _XkbClearColor);
180 181 182 183 184 185
    return;
}

/***====================================================================***/

void
186
XkbFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll)
187
{
188 189 190
    _XkbFreeGeomLeafElems(freeAll, first, count,
                          &outline->num_points, &outline->sz_points,
                          (char **) &outline->points, sizeof(XkbPointRec));
191 192 193 194 195 196 197 198
    return;
}

/***====================================================================***/

static void
_XkbClearOutline(char *outline_in)
{
199
    XkbOutlinePtr outline = (XkbOutlinePtr) outline_in;
200

201 202
    if (outline->points != NULL)
        XkbFreeGeomPoints(outline, 0, outline->num_points, TRUE);
203 204 205 206
    return;
}

void
207
XkbFreeGeomOutlines(XkbShapePtr shape, int first, int count, Bool freeAll)
208
{
209 210 211 212 213
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &shape->num_outlines, &shape->sz_outlines,
                             (char **) &shape->outlines,
                             sizeof(XkbOutlineRec), _XkbClearOutline);

214 215 216 217 218 219 220 221
    return;
}

/***====================================================================***/

static void
_XkbClearShape(char *shape_in)
{
222
    XkbShapePtr shape = (XkbShapePtr) shape_in;
223 224

    if (shape->outlines)
225
        XkbFreeGeomOutlines(shape, 0, shape->num_outlines, TRUE);
226 227 228 229
    return;
}

void
230
XkbFreeGeomShapes(XkbGeometryPtr geom, int first, int count, Bool freeAll)
231
{
232 233 234 235
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &geom->num_shapes, &geom->sz_shapes,
                             (char **) &geom->shapes,
                             sizeof(XkbShapeRec), _XkbClearShape);
236 237 238 239 240
    return;
}

/***====================================================================***/

241 242
void
XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row, int first, int count, Bool freeAll)
243
{
244 245 246
    _XkbFreeGeomLeafElems(freeAll, first, count,
                          &row->num_keys, &row->sz_keys,
                          (char **) &row->keys, sizeof(XkbOverlayKeyRec));
247 248 249 250 251 252
    return;
}

/***====================================================================***/

void
253
XkbFreeGeomKeys(XkbRowPtr row, int first, int count, Bool freeAll)
254
{
255 256 257
    _XkbFreeGeomLeafElems(freeAll, first, count,
                          &row->num_keys, &row->sz_keys,
                          (char **) &row->keys, sizeof(XkbKeyRec));
258 259 260 261 262 263 264 265
    return;
}

/***====================================================================***/

static void
_XkbClearRow(char *row_in)
{
266
    XkbRowPtr row = (XkbRowPtr) row_in;
267

268 269
    if (row->keys != NULL)
        XkbFreeGeomKeys(row, 0, row->num_keys, TRUE);
270 271 272 273
    return;
}

void
274
XkbFreeGeomRows(XkbSectionPtr section, int first, int count, Bool freeAll)
275
{
276 277 278 279
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &section->num_rows, &section->sz_rows,
                             (char **) &section->rows,
                             sizeof(XkbRowRec), _XkbClearRow);
280 281 282 283 284 285 286
}

/***====================================================================***/

static void
_XkbClearSection(char *section_in)
{
287
    XkbSectionPtr section = (XkbSectionPtr) section_in;
288

289 290 291 292 293
    if (section->rows != NULL)
        XkbFreeGeomRows(section, 0, section->num_rows, TRUE);
    if (section->doodads != NULL) {
        XkbFreeGeomDoodads(section->doodads, section->num_doodads, TRUE);
        section->doodads = NULL;
294 295 296 297 298
    }
    return;
}

void
299
XkbFreeGeomSections(XkbGeometryPtr geom, int first, int count, Bool freeAll)
300
{
301 302 303 304
    _XkbFreeGeomNonLeafElems(freeAll, first, count,
                             &geom->num_sections, &geom->sz_sections,
                             (char **) &geom->sections,
                             sizeof(XkbSectionRec), _XkbClearSection);
305 306 307 308 309 310 311 312
    return;
}

/***====================================================================***/

static void
_XkbClearDoodad(char *doodad_in)
{
313
    XkbDoodadPtr doodad = (XkbDoodadPtr) doodad_in;
314 315

    switch (doodad->any.type) {
316 317 318 319 320 321 322 323 324 325 326 327 328 329
    case XkbTextDoodad:
    {
        free(doodad->text.text);
        doodad->text.text = NULL;
        free(doodad->text.font);
        doodad->text.font = NULL;
    }
        break;
    case XkbLogoDoodad:
    {
        free(doodad->logo.logo_name);
        doodad->logo.logo_name = NULL;
    }
        break;
330 331 332 333 334
    }
    return;
}

void
335
XkbFreeGeomDoodads(XkbDoodadPtr doodads, int nDoodads, Bool freeAll)
336
{
337 338
    register int i;
    register XkbDoodadPtr doodad;
339 340

    if (doodads) {
341 342 343 344 345
        for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++) {
            _XkbClearDoodad((char *) doodad);
        }
        if (freeAll)
            free(doodads);
346 347 348 349 350
    }
    return;
}

void
351
XkbFreeGeometry(XkbGeometryPtr geom, unsigned which, Bool freeMap)
352
{
353 354
    if (geom == NULL)
        return;
355
    if (freeMap)
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
        which = XkbGeomAllMask;
    if ((which & XkbGeomPropertiesMask) && (geom->properties != NULL))
        XkbFreeGeomProperties(geom, 0, geom->num_properties, TRUE);
    if ((which & XkbGeomColorsMask) && (geom->colors != NULL))
        XkbFreeGeomColors(geom, 0, geom->num_colors, TRUE);
    if ((which & XkbGeomShapesMask) && (geom->shapes != NULL))
        XkbFreeGeomShapes(geom, 0, geom->num_shapes, TRUE);
    if ((which & XkbGeomSectionsMask) && (geom->sections != NULL))
        XkbFreeGeomSections(geom, 0, geom->num_sections, TRUE);
    if ((which & XkbGeomDoodadsMask) && (geom->doodads != NULL)) {
        XkbFreeGeomDoodads(geom->doodads, geom->num_doodads, TRUE);
        geom->doodads = NULL;
        geom->num_doodads = geom->sz_doodads = 0;
    }
    if ((which & XkbGeomKeyAliasesMask) && (geom->key_aliases != NULL))
        XkbFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, TRUE);
372
    if (freeMap) {
373 374 375
        free(geom->label_font);
        geom->label_font = NULL;
        free(geom);
376 377 378 379 380 381
    }
    return;
}

/***====================================================================***/

382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
/**
 * Resize and clear an XKB geometry item array. The array size may
 * grow or shrink unlike in _XkbGeomAlloc.
 *
 * @param buffer[in,out]  buffer to reallocate and clear
 * @param szItems[in]     currently allocated item count for "buffer"
 * @param nrItems[in]     required item count for "buffer"
 * @param itemSize[in]    size of a single item in "buffer"
 * @param clearance[in]   items to clear after reallocation
 *
 * @see _XkbGeomAlloc
 *
 * @return TRUE if reallocation succeeded. Otherwise FALSE is returned
 *         and contents of "buffer" aren't touched.
 */
Bool
XkbGeomRealloc(void **buffer, int szItems, int nrItems,
               int itemSize, XkbGeomClearance clearance)
{
    void *items;
    int clearBegin;
403

404 405 406 407 408 409 410 411
    /* Check validity of arguments. */
    if (!buffer)
        return FALSE;
    items = *buffer;
    if (!((items && (szItems > 0)) || (!items && !szItems)))
        return FALSE;
    /* Check if there is need to resize. */
    if (nrItems != szItems)
412
        if (!(items = reallocarray(items, nrItems, itemSize)))
413 414
            return FALSE;
    /* Clear specified items to zero. */
415
    switch (clearance) {
416 417 418 419 420 421 422 423 424 425 426 427
    case XKB_GEOM_CLEAR_EXCESS:
        clearBegin = szItems;
        break;
    case XKB_GEOM_CLEAR_ALL:
        clearBegin = 0;
        break;
    case XKB_GEOM_CLEAR_NONE:
    default:
        clearBegin = nrItems;
        break;
    }
    if (items && (clearBegin < nrItems))
428 429
        memset((char *) items + (clearBegin * itemSize), 0,
               (nrItems - clearBegin) * itemSize);
430 431 432 433
    *buffer = items;
    return TRUE;
}

434
static Status
435 436 437
_XkbGeomAlloc(void **old,
              unsigned short *num,
              unsigned short *total, int num_new, size_t sz_elem)
438
{
439 440 441 442
    if (num_new < 1)
        return Success;
    if ((*old) == NULL)
        *num = *total = 0;
443

444 445
    if ((*num) + num_new <= (*total))
        return Success;
446

447
    *total = (*num) + num_new;
448

449 450 451 452 453
    if (!XkbGeomRealloc(old, *num, *total, sz_elem, XKB_GEOM_CLEAR_EXCESS)) {
        free(*old);
        (*old) = NULL;
        *total = *num = 0;
        return BadAlloc;
454 455 456 457 458
    }

    return Success;
}

459
#define	_XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\
460 461
				&(g)->num_properties,&(g)->sz_properties,\
				(n),sizeof(XkbPropertyRec))
462
#define	_XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\
463 464
				&(g)->num_colors,&(g)->sz_colors,\
				(n),sizeof(XkbColorRec))
465
#define	_XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\
466 467
				&(g)->num_shapes,&(g)->sz_shapes,\
				(n),sizeof(XkbShapeRec))
468
#define	_XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\
469 470
				&(g)->num_sections,&(g)->sz_sections,\
				(n),sizeof(XkbSectionRec))
471
#define	_XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\
472 473
				&(g)->num_doodads,&(g)->sz_doodads,\
				(n),sizeof(XkbDoodadRec))
474
#define	_XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\
475 476 477
				&(g)->num_key_aliases,&(g)->sz_key_aliases,\
				(n),sizeof(XkbKeyAliasRec))

478
#define	_XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\
479 480
				&(s)->num_outlines,&(s)->sz_outlines,\
				(n),sizeof(XkbOutlineRec))
481
#define	_XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\
482 483
				&(s)->num_rows,&(s)->sz_rows,\
				(n),sizeof(XkbRowRec))
484
#define	_XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\
485 486
				&(o)->num_points,&(o)->sz_points,\
				(n),sizeof(XkbPointRec))
487
#define	_XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
488 489
				&(r)->num_keys,&(r)->sz_keys,\
				(n),sizeof(XkbKeyRec))
490
#define	_XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\
491 492
				&(s)->num_overlays,&(s)->sz_overlays,\
				(n),sizeof(XkbOverlayRec))
493
#define	_XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\
494 495
				&(o)->num_rows,&(o)->sz_rows,\
				(n),sizeof(XkbOverlayRowRec))
496
#define	_XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
497 498
				&(r)->num_keys,&(r)->sz_keys,\
				(n),sizeof(XkbOverlayKeyRec))
499

500
Status
501
XkbAllocGeometry(XkbDescPtr xkb, XkbGeometrySizesPtr sizes)
502
{
503 504
    XkbGeometryPtr geom;
    Status rtrn;
505

506 507 508 509
    if (xkb->geom == NULL) {
        xkb->geom = calloc(1, sizeof(XkbGeometryRec));
        if (!xkb->geom)
            return BadAlloc;
510
    }
511 512 513 514
    geom = xkb->geom;
    if ((sizes->which & XkbGeomPropertiesMask) &&
        ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success)) {
        goto BAIL;
515
    }
516 517 518
    if ((sizes->which & XkbGeomColorsMask) &&
        ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success)) {
        goto BAIL;
519
    }
520 521 522
    if ((sizes->which & XkbGeomShapesMask) &&
        ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success)) {
        goto BAIL;
523
    }
524 525 526
    if ((sizes->which & XkbGeomSectionsMask) &&
        ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success)) {
        goto BAIL;
527
    }
528 529 530
    if ((sizes->which & XkbGeomDoodadsMask) &&
        ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success)) {
        goto BAIL;
531
    }
532 533 534 535
    if ((sizes->which & XkbGeomKeyAliasesMask) &&
        ((rtrn =
          _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success)) {
        goto BAIL;
536 537
    }
    return Success;
538 539 540
 BAIL:
    XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
    xkb->geom = NULL;
541 542 543 544 545 546
    return rtrn;
}

/***====================================================================***/

XkbPropertyPtr
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
XkbAddGeomProperty(XkbGeometryPtr geom, char *name, char *value)
{
    register int i;
    register XkbPropertyPtr prop;

    if ((!geom) || (!name) || (!value))
        return NULL;
    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
        if ((prop->name) && (strcmp(name, prop->name) == 0)) {
            free(prop->value);
            prop->value = strdup(value);
            return prop;
        }
    }
    if ((geom->num_properties >= geom->sz_properties) &&
        (_XkbAllocProps(geom, 1) != Success)) {
        return NULL;
    }
    prop = &geom->properties[geom->num_properties];
    prop->name = strdup(name);
567
    if (!prop->name)
568 569
        return NULL;
    prop->value = strdup(value);
570
    if (!prop->value) {
571 572 573
        free(prop->name);
        prop->name = NULL;
        return NULL;
574 575 576 577 578 579
    }
    geom->num_properties++;
    return prop;
}

XkbKeyAliasPtr
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
XkbAddGeomKeyAlias(XkbGeometryPtr geom, char *aliasStr, char *realStr)
{
    register int i;
    register XkbKeyAliasPtr alias;

    if ((!geom) || (!aliasStr) || (!realStr) || (!aliasStr[0]) || (!realStr[0]))
        return NULL;
    for (i = 0, alias = geom->key_aliases; i < geom->num_key_aliases;
         i++, alias++) {
        if (strncmp(alias->alias, aliasStr, XkbKeyNameLength) == 0) {
            memset(alias->real, 0, XkbKeyNameLength);
            strncpy(alias->real, realStr, XkbKeyNameLength);
            return alias;
        }
    }
    if ((geom->num_key_aliases >= geom->sz_key_aliases) &&
        (_XkbAllocKeyAliases(geom, 1) != Success)) {
        return NULL;
    }
    alias = &geom->key_aliases[geom->num_key_aliases];
600
    memset(alias, 0, sizeof(XkbKeyAliasRec));
601 602
    strncpy(alias->alias, aliasStr, XkbKeyNameLength);
    strncpy(alias->real, realStr, XkbKeyNameLength);
603 604 605 606 607
    geom->num_key_aliases++;
    return alias;
}

XkbColorPtr
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
XkbAddGeomColor(XkbGeometryPtr geom, char *spec, unsigned int pixel)
{
    register int i;
    register XkbColorPtr color;

    if ((!geom) || (!spec))
        return NULL;
    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
        if ((color->spec) && (strcmp(color->spec, spec) == 0)) {
            color->pixel = pixel;
            return color;
        }
    }
    if ((geom->num_colors >= geom->sz_colors) &&
        (_XkbAllocColors(geom, 1) != Success)) {
        return NULL;
    }
    color = &geom->colors[geom->num_colors];
    color->pixel = pixel;
    color->spec = strdup(spec);
628
    if (!color->spec)
629
        return NULL;
630 631 632 633 634
    geom->num_colors++;
    return color;
}

XkbOutlinePtr
635
XkbAddGeomOutline(XkbShapePtr shape, int sz_points)
636
{
637
    XkbOutlinePtr outline;
638

639 640 641 642 643
    if ((!shape) || (sz_points < 0))
        return NULL;
    if ((shape->num_outlines >= shape->sz_outlines) &&
        (_XkbAllocOutlines(shape, 1) != Success)) {
        return NULL;
644
    }
645
    outline = &shape->outlines[shape->num_outlines];
646
    memset(outline, 0, sizeof(XkbOutlineRec));
647 648
    if ((sz_points > 0) && (_XkbAllocPoints(outline, sz_points) != Success))
        return NULL;
649 650 651 652 653
    shape->num_outlines++;
    return outline;
}

XkbShapePtr
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
XkbAddGeomShape(XkbGeometryPtr geom, Atom name, int sz_outlines)
{
    XkbShapePtr shape;
    register int i;

    if ((!geom) || (!name) || (sz_outlines < 0))
        return NULL;
    if (geom->num_shapes > 0) {
        for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
            if (name == shape->name)
                return shape;
        }
    }
    if ((geom->num_shapes >= geom->sz_shapes) &&
        (_XkbAllocShapes(geom, 1) != Success))
        return NULL;
    shape = &geom->shapes[geom->num_shapes];
671
    memset(shape, 0, sizeof(XkbShapeRec));
672 673 674 675
    if ((sz_outlines > 0) && (_XkbAllocOutlines(shape, sz_outlines) != Success))
        return NULL;
    shape->name = name;
    shape->primary = shape->approx = NULL;
676 677 678 679 680 681 682
    geom->num_shapes++;
    return shape;
}

XkbKeyPtr
XkbAddGeomKey(XkbRowPtr row)
{
683 684
    XkbKeyPtr key;

685
    if (!row)
686 687 688 689
        return NULL;
    if ((row->num_keys >= row->sz_keys) && (_XkbAllocKeys(row, 1) != Success))
        return NULL;
    key = &row->keys[row->num_keys++];
690
    memset(key, 0, sizeof(XkbKeyRec));
691 692 693 694
    return key;
}

XkbRowPtr
695
XkbAddGeomRow(XkbSectionPtr section, int sz_keys)
696
{
697
    XkbRowPtr row;
698

699 700 701 702 703 704
    if ((!section) || (sz_keys < 0))
        return NULL;
    if ((section->num_rows >= section->sz_rows) &&
        (_XkbAllocRows(section, 1) != Success))
        return NULL;
    row = &section->rows[section->num_rows];
705
    memset(row, 0, sizeof(XkbRowRec));
706 707
    if ((sz_keys > 0) && (_XkbAllocKeys(row, sz_keys) != Success))
        return NULL;
708 709 710 711 712
    section->num_rows++;
    return row;
}

XkbSectionPtr
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
XkbAddGeomSection(XkbGeometryPtr geom,
                  Atom name, int sz_rows, int sz_doodads, int sz_over)
{
    register int i;
    XkbSectionPtr section;

    if ((!geom) || (name == None) || (sz_rows < 0))
        return NULL;
    for (i = 0, section = geom->sections; i < geom->num_sections;
         i++, section++) {
        if (section->name != name)
            continue;
        if (((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success)) ||
            ((sz_doodads > 0) &&
             (_XkbAllocDoodads(section, sz_doodads) != Success)) ||
            ((sz_over > 0) && (_XkbAllocOverlays(section, sz_over) != Success)))
            return NULL;
        return section;
    }
    if ((geom->num_sections >= geom->sz_sections) &&
        (_XkbAllocSections(geom, 1) != Success))
        return NULL;
    section = &geom->sections[geom->num_sections];
    if ((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success))
        return NULL;
    if ((sz_doodads > 0) && (_XkbAllocDoodads(section, sz_doodads) != Success)) {
        if (section->rows) {
            free(section->rows);
            section->rows = NULL;
            section->sz_rows = section->num_rows = 0;
        }
        return NULL;
    }
    section->name = name;
747 748 749 750 751
    geom->num_sections++;
    return section;
}

XkbDoodadPtr
752
XkbAddGeomDoodad(XkbGeometryPtr geom, XkbSectionPtr section, Atom name)
753
{
754 755
    XkbDoodadPtr old, doodad;
    register int i, nDoodads;
756

757 758 759 760 761
    if ((!geom) || (name == None))
        return NULL;
    if ((section != NULL) && (section->num_doodads > 0)) {
        old = section->doodads;
        nDoodads = section->num_doodads;
762 763
    }
    else {
764 765
        old = geom->doodads;
        nDoodads = geom->num_doodads;
766
    }
767 768 769
    for (i = 0, doodad = old; i < nDoodads; i++, doodad++) {
        if (doodad->any.name == name)
            return doodad;
770 771
    }
    if (section) {
772 773 774 775 776
        if ((section->num_doodads >= geom->sz_doodads) &&
            (_XkbAllocDoodads(section, 1) != Success)) {
            return NULL;
        }
        doodad = &section->doodads[section->num_doodads++];
777 778
    }
    else {
779 780 781 782
        if ((geom->num_doodads >= geom->sz_doodads) &&
            (_XkbAllocDoodads(geom, 1) != Success))
            return NULL;
        doodad = &geom->doodads[geom->num_doodads++];
783
    }
784
    memset(doodad, 0, sizeof(XkbDoodadRec));
785
    doodad->any.name = name;
786 787 788 789
    return doodad;
}

XkbOverlayKeyPtr
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
XkbAddGeomOverlayKey(XkbOverlayPtr overlay,
                     XkbOverlayRowPtr row, char *over, char *under)
{
    register int i;
    XkbOverlayKeyPtr key;
    XkbSectionPtr section;
    XkbRowPtr row_under;
    Bool found;

    if ((!overlay) || (!row) || (!over) || (!under))
        return NULL;
    section = overlay->section_under;
    if (row->row_under >= section->num_rows)
        return NULL;
    row_under = &section->rows[row->row_under];
    for (i = 0, found = FALSE; i < row_under->num_keys; i++) {
        if (strncmp(under, row_under->keys[i].name.name, XkbKeyNameLength) == 0) {
            found = TRUE;
            break;
        }
810 811
    }
    if (!found)
812 813 814 815 816 817 818
        return NULL;
    if ((row->num_keys >= row->sz_keys) &&
        (_XkbAllocOverlayKeys(row, 1) != Success))
        return NULL;
    key = &row->keys[row->num_keys];
    strncpy(key->under.name, under, XkbKeyNameLength);
    strncpy(key->over.name, over, XkbKeyNameLength);
819 820 821 822 823
    row->num_keys++;
    return key;
}

XkbOverlayRowPtr
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
XkbAddGeomOverlayRow(XkbOverlayPtr overlay, int row_under, int sz_keys)
{
    register int i;
    XkbOverlayRowPtr row;

    if ((!overlay) || (sz_keys < 0))
        return NULL;
    if (row_under >= overlay->section_under->num_rows)
        return NULL;
    for (i = 0; i < overlay->num_rows; i++) {
        if (overlay->rows[i].row_under == row_under) {
            row = &overlay->rows[i];
            if ((row->sz_keys < sz_keys) &&
                (_XkbAllocOverlayKeys(row, sz_keys) != Success)) {
                return NULL;
            }
            return &overlay->rows[i];
        }
    }
    if ((overlay->num_rows >= overlay->sz_rows) &&
        (_XkbAllocOverlayRows(overlay, 1) != Success))
        return NULL;
    row = &overlay->rows[overlay->num_rows];
847
    memset(row, 0, sizeof(XkbOverlayRowRec));
848 849 850
    if ((sz_keys > 0) && (_XkbAllocOverlayKeys(row, sz_keys) != Success))
        return NULL;
    row->row_under = row_under;
851 852 853 854 855
    overlay->num_rows++;
    return row;
}

XkbOverlayPtr
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
XkbAddGeomOverlay(XkbSectionPtr section, Atom name, int sz_rows)
{
    register int i;
    XkbOverlayPtr overlay;

    if ((!section) || (name == None) || (sz_rows == 0))
        return NULL;

    for (i = 0, overlay = section->overlays; i < section->num_overlays;
         i++, overlay++) {
        if (overlay->name == name) {
            if ((sz_rows > 0) &&
                (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
                return NULL;
            return overlay;
        }
    }
    if ((section->num_overlays >= section->sz_overlays) &&
        (_XkbAllocOverlays(section, 1) != Success))
        return NULL;
    overlay = &section->overlays[section->num_overlays];
    if ((sz_rows > 0) && (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
        return NULL;
    overlay->name = name;
    overlay->section_under = section;
881 882 883
    section->num_overlays++;
    return overlay;
}