Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / XKBGAlloc.c
CommitLineData
a09e091a
JB
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_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include "misc.h"
35#include "inputstr.h"
36#include <xkbsrv.h>
37#include "xkbgeom.h"
38
39/***====================================================================***/
40
41static void
42_XkbFreeGeomLeafElems(Bool freeAll,
43 int first,
44 int count,
45 unsigned short *num_inout,
46 unsigned short *sz_inout,
47 char **elems, unsigned int elem_sz)
48{
49 if ((freeAll) || (*elems == NULL)) {
50 *num_inout = *sz_inout = 0;
51 free(*elems);
52 *elems = NULL;
53 return;
54 }
55
56 if ((first >= (*num_inout)) || (first < 0) || (count < 1))
57 return;
58
59 if (first + count >= (*num_inout)) {
60 /* truncating the array is easy */
61 (*num_inout) = first;
62 }
63 else {
64 char *ptr;
65 int extra;
66
67 ptr = *elems;
68 extra = ((*num_inout) - (first + count)) * elem_sz;
69 if (extra > 0)
70 memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz],
71 extra);
72 (*num_inout) -= count;
73 }
74 return;
75}
76
77typedef void (*ContentsClearFunc) (char * /* priv */
78 );
79
80static void
81_XkbFreeGeomNonLeafElems(Bool freeAll,
82 int first,
83 int count,
84 unsigned short *num_inout,
85 unsigned short *sz_inout,
86 char **elems,
87 unsigned int elem_sz, ContentsClearFunc freeFunc)
88{
89 register int i;
90 register char *ptr;
91
92 if (freeAll) {
93 first = 0;
94 count = (*num_inout);
95 }
96 else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
97 return;
98 else if (first + count > (*num_inout))
99 count = (*num_inout) - first;
100 if (*elems == NULL)
101 return;
102
103 if (freeFunc) {
104 ptr = *elems;
105 ptr += first * elem_sz;
106 for (i = 0; i < count; i++) {
107 (*freeFunc) (ptr);
108 ptr += elem_sz;
109 }
110 }
111 if (freeAll) {
112 (*num_inout) = (*sz_inout) = 0;
113 free(*elems);
114 *elems = NULL;
115 }
116 else if (first + count >= (*num_inout))
117 *num_inout = first;
118 else {
119 i = ((*num_inout) - (first + count)) * elem_sz;
120 ptr = *elems;
121 memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz], i);
122 (*num_inout) -= count;
123 }
124 return;
125}
126
127/***====================================================================***/
128
129static void
130_XkbClearProperty(char *prop_in)
131{
132 XkbPropertyPtr prop = (XkbPropertyPtr) prop_in;
133
134 free(prop->name);
135 prop->name = NULL;
136 free(prop->value);
137 prop->value = NULL;
138 return;
139}
140
141void
142XkbFreeGeomProperties(XkbGeometryPtr geom, int first, int count, Bool freeAll)
143{
144 _XkbFreeGeomNonLeafElems(freeAll, first, count,
145 &geom->num_properties, &geom->sz_properties,
146 (char **) &geom->properties,
147 sizeof(XkbPropertyRec), _XkbClearProperty);
148 return;
149}
150
151/***====================================================================***/
152
153void
154XkbFreeGeomKeyAliases(XkbGeometryPtr geom, int first, int count, Bool freeAll)
155{
156 _XkbFreeGeomLeafElems(freeAll, first, count,
157 &geom->num_key_aliases, &geom->sz_key_aliases,
158 (char **) &geom->key_aliases, sizeof(XkbKeyAliasRec));
159 return;
160}
161
162/***====================================================================***/
163
164static void
165_XkbClearColor(char *color_in)
166{
167 XkbColorPtr color = (XkbColorPtr) color_in;
168
169 free(color->spec);
170 return;
171}
172
173void
174XkbFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll)
175{
176 _XkbFreeGeomNonLeafElems(freeAll, first, count,
177 &geom->num_colors, &geom->sz_colors,
178 (char **) &geom->colors,
179 sizeof(XkbColorRec), _XkbClearColor);
180 return;
181}
182
183/***====================================================================***/
184
185void
186XkbFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll)
187{
188 _XkbFreeGeomLeafElems(freeAll, first, count,
189 &outline->num_points, &outline->sz_points,
190 (char **) &outline->points, sizeof(XkbPointRec));
191 return;
192}
193
194/***====================================================================***/
195
196static void
197_XkbClearOutline(char *outline_in)
198{
199 XkbOutlinePtr outline = (XkbOutlinePtr) outline_in;
200
201 if (outline->points != NULL)
202 XkbFreeGeomPoints(outline, 0, outline->num_points, TRUE);
203 return;
204}
205
206void
207XkbFreeGeomOutlines(XkbShapePtr shape, int first, int count, Bool freeAll)
208{
209 _XkbFreeGeomNonLeafElems(freeAll, first, count,
210 &shape->num_outlines, &shape->sz_outlines,
211 (char **) &shape->outlines,
212 sizeof(XkbOutlineRec), _XkbClearOutline);
213
214 return;
215}
216
217/***====================================================================***/
218
219static void
220_XkbClearShape(char *shape_in)
221{
222 XkbShapePtr shape = (XkbShapePtr) shape_in;
223
224 if (shape->outlines)
225 XkbFreeGeomOutlines(shape, 0, shape->num_outlines, TRUE);
226 return;
227}
228
229void
230XkbFreeGeomShapes(XkbGeometryPtr geom, int first, int count, Bool freeAll)
231{
232 _XkbFreeGeomNonLeafElems(freeAll, first, count,
233 &geom->num_shapes, &geom->sz_shapes,
234 (char **) &geom->shapes,
235 sizeof(XkbShapeRec), _XkbClearShape);
236 return;
237}
238
239/***====================================================================***/
240
241void
242XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row, int first, int count, Bool freeAll)
243{
244 _XkbFreeGeomLeafElems(freeAll, first, count,
245 &row->num_keys, &row->sz_keys,
246 (char **) &row->keys, sizeof(XkbOverlayKeyRec));
247 return;
248}
249
250/***====================================================================***/
251
252void
253XkbFreeGeomKeys(XkbRowPtr row, int first, int count, Bool freeAll)
254{
255 _XkbFreeGeomLeafElems(freeAll, first, count,
256 &row->num_keys, &row->sz_keys,
257 (char **) &row->keys, sizeof(XkbKeyRec));
258 return;
259}
260
261/***====================================================================***/
262
263static void
264_XkbClearRow(char *row_in)
265{
266 XkbRowPtr row = (XkbRowPtr) row_in;
267
268 if (row->keys != NULL)
269 XkbFreeGeomKeys(row, 0, row->num_keys, TRUE);
270 return;
271}
272
273void
274XkbFreeGeomRows(XkbSectionPtr section, int first, int count, Bool freeAll)
275{
276 _XkbFreeGeomNonLeafElems(freeAll, first, count,
277 &section->num_rows, &section->sz_rows,
278 (char **) &section->rows,
279 sizeof(XkbRowRec), _XkbClearRow);
280}
281
282/***====================================================================***/
283
284static void
285_XkbClearSection(char *section_in)
286{
287 XkbSectionPtr section = (XkbSectionPtr) section_in;
288
289 if (section->rows != NULL)
290 XkbFreeGeomRows(section, 0, section->num_rows, TRUE);
291 if (section->doodads != NULL) {
292 XkbFreeGeomDoodads(section->doodads, section->num_doodads, TRUE);
293 section->doodads = NULL;
294 }
295 return;
296}
297
298void
299XkbFreeGeomSections(XkbGeometryPtr geom, int first, int count, Bool freeAll)
300{
301 _XkbFreeGeomNonLeafElems(freeAll, first, count,
302 &geom->num_sections, &geom->sz_sections,
303 (char **) &geom->sections,
304 sizeof(XkbSectionRec), _XkbClearSection);
305 return;
306}
307
308/***====================================================================***/
309
310static void
311_XkbClearDoodad(char *doodad_in)
312{
313 XkbDoodadPtr doodad = (XkbDoodadPtr) doodad_in;
314
315 switch (doodad->any.type) {
316 case XkbTextDoodad:
317 {
318 free(doodad->text.text);
319 doodad->text.text = NULL;
320 free(doodad->text.font);
321 doodad->text.font = NULL;
322 }
323 break;
324 case XkbLogoDoodad:
325 {
326 free(doodad->logo.logo_name);
327 doodad->logo.logo_name = NULL;
328 }
329 break;
330 }
331 return;
332}
333
334void
335XkbFreeGeomDoodads(XkbDoodadPtr doodads, int nDoodads, Bool freeAll)
336{
337 register int i;
338 register XkbDoodadPtr doodad;
339
340 if (doodads) {
341 for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++) {
342 _XkbClearDoodad((char *) doodad);
343 }
344 if (freeAll)
345 free(doodads);
346 }
347 return;
348}
349
350void
351XkbFreeGeometry(XkbGeometryPtr geom, unsigned which, Bool freeMap)
352{
353 if (geom == NULL)
354 return;
355 if (freeMap)
356 which = XkbGeomAllMask;
357 if ((which & XkbGeomPropertiesMask) && (geom->properties != NULL))
358 XkbFreeGeomProperties(geom, 0, geom->num_properties, TRUE);
359 if ((which & XkbGeomColorsMask) && (geom->colors != NULL))
360 XkbFreeGeomColors(geom, 0, geom->num_colors, TRUE);
361 if ((which & XkbGeomShapesMask) && (geom->shapes != NULL))
362 XkbFreeGeomShapes(geom, 0, geom->num_shapes, TRUE);
363 if ((which & XkbGeomSectionsMask) && (geom->sections != NULL))
364 XkbFreeGeomSections(geom, 0, geom->num_sections, TRUE);
365 if ((which & XkbGeomDoodadsMask) && (geom->doodads != NULL)) {
366 XkbFreeGeomDoodads(geom->doodads, geom->num_doodads, TRUE);
367 geom->doodads = NULL;
368 geom->num_doodads = geom->sz_doodads = 0;
369 }
370 if ((which & XkbGeomKeyAliasesMask) && (geom->key_aliases != NULL))
371 XkbFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, TRUE);
372 if (freeMap) {
373 free(geom->label_font);
374 geom->label_font = NULL;
375 free(geom);
376 }
377 return;
378}
379
380/***====================================================================***/
381
382/**
383 * Resize and clear an XKB geometry item array. The array size may
384 * grow or shrink unlike in _XkbGeomAlloc.
385 *
386 * @param buffer[in,out] buffer to reallocate and clear
387 * @param szItems[in] currently allocated item count for "buffer"
388 * @param nrItems[in] required item count for "buffer"
389 * @param itemSize[in] size of a single item in "buffer"
390 * @param clearance[in] items to clear after reallocation
391 *
392 * @see _XkbGeomAlloc
393 *
394 * @return TRUE if reallocation succeeded. Otherwise FALSE is returned
395 * and contents of "buffer" aren't touched.
396 */
397Bool
398XkbGeomRealloc(void **buffer, int szItems, int nrItems,
399 int itemSize, XkbGeomClearance clearance)
400{
401 void *items;
402 int clearBegin;
403
404 /* Check validity of arguments. */
405 if (!buffer)
406 return FALSE;
407 items = *buffer;
408 if (!((items && (szItems > 0)) || (!items && !szItems)))
409 return FALSE;
410 /* Check if there is need to resize. */
411 if (nrItems != szItems)
412 if (!(items = realloc(items, nrItems * itemSize)))
413 return FALSE;
414 /* Clear specified items to zero. */
415 switch (clearance) {
416 case XKB_GEOM_CLEAR_EXCESS:
417 clearBegin = szItems;
418 break;
419 case XKB_GEOM_CLEAR_ALL:
420 clearBegin = 0;
421 break;
422 case XKB_GEOM_CLEAR_NONE:
423 default:
424 clearBegin = nrItems;
425 break;
426 }
427 if (items && (clearBegin < nrItems))
428 memset((char *) items + (clearBegin * itemSize), 0,
429 (nrItems - clearBegin) * itemSize);
430 *buffer = items;
431 return TRUE;
432}
433
434static Status
435_XkbGeomAlloc(void **old,
436 unsigned short *num,
437 unsigned short *total, int num_new, size_t sz_elem)
438{
439 if (num_new < 1)
440 return Success;
441 if ((*old) == NULL)
442 *num = *total = 0;
443
444 if ((*num) + num_new <= (*total))
445 return Success;
446
447 *total = (*num) + num_new;
448
449 if (!XkbGeomRealloc(old, *num, *total, sz_elem, XKB_GEOM_CLEAR_EXCESS)) {
450 free(*old);
451 (*old) = NULL;
452 *total = *num = 0;
453 return BadAlloc;
454 }
455
456 return Success;
457}
458
459#define _XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\
460 &(g)->num_properties,&(g)->sz_properties,\
461 (n),sizeof(XkbPropertyRec))
462#define _XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\
463 &(g)->num_colors,&(g)->sz_colors,\
464 (n),sizeof(XkbColorRec))
465#define _XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\
466 &(g)->num_shapes,&(g)->sz_shapes,\
467 (n),sizeof(XkbShapeRec))
468#define _XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\
469 &(g)->num_sections,&(g)->sz_sections,\
470 (n),sizeof(XkbSectionRec))
471#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\
472 &(g)->num_doodads,&(g)->sz_doodads,\
473 (n),sizeof(XkbDoodadRec))
474#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\
475 &(g)->num_key_aliases,&(g)->sz_key_aliases,\
476 (n),sizeof(XkbKeyAliasRec))
477
478#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\
479 &(s)->num_outlines,&(s)->sz_outlines,\
480 (n),sizeof(XkbOutlineRec))
481#define _XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\
482 &(s)->num_rows,&(s)->sz_rows,\
483 (n),sizeof(XkbRowRec))
484#define _XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\
485 &(o)->num_points,&(o)->sz_points,\
486 (n),sizeof(XkbPointRec))
487#define _XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
488 &(r)->num_keys,&(r)->sz_keys,\
489 (n),sizeof(XkbKeyRec))
490#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\
491 &(s)->num_overlays,&(s)->sz_overlays,\
492 (n),sizeof(XkbOverlayRec))
493#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\
494 &(o)->num_rows,&(o)->sz_rows,\
495 (n),sizeof(XkbOverlayRowRec))
496#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
497 &(r)->num_keys,&(r)->sz_keys,\
498 (n),sizeof(XkbOverlayKeyRec))
499
500Status
501XkbAllocGeometry(XkbDescPtr xkb, XkbGeometrySizesPtr sizes)
502{
503 XkbGeometryPtr geom;
504 Status rtrn;
505
506 if (xkb->geom == NULL) {
507 xkb->geom = calloc(1, sizeof(XkbGeometryRec));
508 if (!xkb->geom)
509 return BadAlloc;
510 }
511 geom = xkb->geom;
512 if ((sizes->which & XkbGeomPropertiesMask) &&
513 ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success)) {
514 goto BAIL;
515 }
516 if ((sizes->which & XkbGeomColorsMask) &&
517 ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success)) {
518 goto BAIL;
519 }
520 if ((sizes->which & XkbGeomShapesMask) &&
521 ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success)) {
522 goto BAIL;
523 }
524 if ((sizes->which & XkbGeomSectionsMask) &&
525 ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success)) {
526 goto BAIL;
527 }
528 if ((sizes->which & XkbGeomDoodadsMask) &&
529 ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success)) {
530 goto BAIL;
531 }
532 if ((sizes->which & XkbGeomKeyAliasesMask) &&
533 ((rtrn =
534 _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success)) {
535 goto BAIL;
536 }
537 return Success;
538 BAIL:
539 XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
540 xkb->geom = NULL;
541 return rtrn;
542}
543
544/***====================================================================***/
545
546XkbPropertyPtr
547XkbAddGeomProperty(XkbGeometryPtr geom, char *name, char *value)
548{
549 register int i;
550 register XkbPropertyPtr prop;
551
552 if ((!geom) || (!name) || (!value))
553 return NULL;
554 for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
555 if ((prop->name) && (strcmp(name, prop->name) == 0)) {
556 free(prop->value);
557 prop->value = strdup(value);
558 return prop;
559 }
560 }
561 if ((geom->num_properties >= geom->sz_properties) &&
562 (_XkbAllocProps(geom, 1) != Success)) {
563 return NULL;
564 }
565 prop = &geom->properties[geom->num_properties];
566 prop->name = strdup(name);
567 if (!prop->name)
568 return NULL;
569 prop->value = strdup(value);
570 if (!prop->value) {
571 free(prop->name);
572 prop->name = NULL;
573 return NULL;
574 }
575 geom->num_properties++;
576 return prop;
577}
578
579XkbKeyAliasPtr
580XkbAddGeomKeyAlias(XkbGeometryPtr geom, char *aliasStr, char *realStr)
581{
582 register int i;
583 register XkbKeyAliasPtr alias;
584
585 if ((!geom) || (!aliasStr) || (!realStr) || (!aliasStr[0]) || (!realStr[0]))
586 return NULL;
587 for (i = 0, alias = geom->key_aliases; i < geom->num_key_aliases;
588 i++, alias++) {
589 if (strncmp(alias->alias, aliasStr, XkbKeyNameLength) == 0) {
590 memset(alias->real, 0, XkbKeyNameLength);
591 strncpy(alias->real, realStr, XkbKeyNameLength);
592 return alias;
593 }
594 }
595 if ((geom->num_key_aliases >= geom->sz_key_aliases) &&
596 (_XkbAllocKeyAliases(geom, 1) != Success)) {
597 return NULL;
598 }
599 alias = &geom->key_aliases[geom->num_key_aliases];
600 memset(alias, 0, sizeof(XkbKeyAliasRec));
601 strncpy(alias->alias, aliasStr, XkbKeyNameLength);
602 strncpy(alias->real, realStr, XkbKeyNameLength);
603 geom->num_key_aliases++;
604 return alias;
605}
606
607XkbColorPtr
608XkbAddGeomColor(XkbGeometryPtr geom, char *spec, unsigned int pixel)
609{
610 register int i;
611 register XkbColorPtr color;
612
613 if ((!geom) || (!spec))
614 return NULL;
615 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
616 if ((color->spec) && (strcmp(color->spec, spec) == 0)) {
617 color->pixel = pixel;
618 return color;
619 }
620 }
621 if ((geom->num_colors >= geom->sz_colors) &&
622 (_XkbAllocColors(geom, 1) != Success)) {
623 return NULL;
624 }
625 color = &geom->colors[geom->num_colors];
626 color->pixel = pixel;
627 color->spec = strdup(spec);
628 if (!color->spec)
629 return NULL;
630 geom->num_colors++;
631 return color;
632}
633
634XkbOutlinePtr
635XkbAddGeomOutline(XkbShapePtr shape, int sz_points)
636{
637 XkbOutlinePtr outline;
638
639 if ((!shape) || (sz_points < 0))
640 return NULL;
641 if ((shape->num_outlines >= shape->sz_outlines) &&
642 (_XkbAllocOutlines(shape, 1) != Success)) {
643 return NULL;
644 }
645 outline = &shape->outlines[shape->num_outlines];
646 memset(outline, 0, sizeof(XkbOutlineRec));
647 if ((sz_points > 0) && (_XkbAllocPoints(outline, sz_points) != Success))
648 return NULL;
649 shape->num_outlines++;
650 return outline;
651}
652
653XkbShapePtr
654XkbAddGeomShape(XkbGeometryPtr geom, Atom name, int sz_outlines)
655{
656 XkbShapePtr shape;
657 register int i;
658
659 if ((!geom) || (!name) || (sz_outlines < 0))
660 return NULL;
661 if (geom->num_shapes > 0) {
662 for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
663 if (name == shape->name)
664 return shape;
665 }
666 }
667 if ((geom->num_shapes >= geom->sz_shapes) &&
668 (_XkbAllocShapes(geom, 1) != Success))
669 return NULL;
670 shape = &geom->shapes[geom->num_shapes];
671 memset(shape, 0, sizeof(XkbShapeRec));
672 if ((sz_outlines > 0) && (_XkbAllocOutlines(shape, sz_outlines) != Success))
673 return NULL;
674 shape->name = name;
675 shape->primary = shape->approx = NULL;
676 geom->num_shapes++;
677 return shape;
678}
679
680XkbKeyPtr
681XkbAddGeomKey(XkbRowPtr row)
682{
683 XkbKeyPtr key;
684
685 if (!row)
686 return NULL;
687 if ((row->num_keys >= row->sz_keys) && (_XkbAllocKeys(row, 1) != Success))
688 return NULL;
689 key = &row->keys[row->num_keys++];
690 memset(key, 0, sizeof(XkbKeyRec));
691 return key;
692}
693
694XkbRowPtr
695XkbAddGeomRow(XkbSectionPtr section, int sz_keys)
696{
697 XkbRowPtr row;
698
699 if ((!section) || (sz_keys < 0))
700 return NULL;
701 if ((section->num_rows >= section->sz_rows) &&
702 (_XkbAllocRows(section, 1) != Success))
703 return NULL;
704 row = &section->rows[section->num_rows];
705 memset(row, 0, sizeof(XkbRowRec));
706 if ((sz_keys > 0) && (_XkbAllocKeys(row, sz_keys) != Success))
707 return NULL;
708 section->num_rows++;
709 return row;
710}
711
712XkbSectionPtr
713XkbAddGeomSection(XkbGeometryPtr geom,
714 Atom name, int sz_rows, int sz_doodads, int sz_over)
715{
716 register int i;
717 XkbSectionPtr section;
718
719 if ((!geom) || (name == None) || (sz_rows < 0))
720 return NULL;
721 for (i = 0, section = geom->sections; i < geom->num_sections;
722 i++, section++) {
723 if (section->name != name)
724 continue;
725 if (((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success)) ||
726 ((sz_doodads > 0) &&
727 (_XkbAllocDoodads(section, sz_doodads) != Success)) ||
728 ((sz_over > 0) && (_XkbAllocOverlays(section, sz_over) != Success)))
729 return NULL;
730 return section;
731 }
732 if ((geom->num_sections >= geom->sz_sections) &&
733 (_XkbAllocSections(geom, 1) != Success))
734 return NULL;
735 section = &geom->sections[geom->num_sections];
736 if ((sz_rows > 0) && (_XkbAllocRows(section, sz_rows) != Success))
737 return NULL;
738 if ((sz_doodads > 0) && (_XkbAllocDoodads(section, sz_doodads) != Success)) {
739 if (section->rows) {
740 free(section->rows);
741 section->rows = NULL;
742 section->sz_rows = section->num_rows = 0;
743 }
744 return NULL;
745 }
746 section->name = name;
747 geom->num_sections++;
748 return section;
749}
750
751XkbDoodadPtr
752XkbAddGeomDoodad(XkbGeometryPtr geom, XkbSectionPtr section, Atom name)
753{
754 XkbDoodadPtr old, doodad;
755 register int i, nDoodads;
756
757 if ((!geom) || (name == None))
758 return NULL;
759 if ((section != NULL) && (section->num_doodads > 0)) {
760 old = section->doodads;
761 nDoodads = section->num_doodads;
762 }
763 else {
764 old = geom->doodads;
765 nDoodads = geom->num_doodads;
766 }
767 for (i = 0, doodad = old; i < nDoodads; i++, doodad++) {
768 if (doodad->any.name == name)
769 return doodad;
770 }
771 if (section) {
772 if ((section->num_doodads >= geom->sz_doodads) &&
773 (_XkbAllocDoodads(section, 1) != Success)) {
774 return NULL;
775 }
776 doodad = &section->doodads[section->num_doodads++];
777 }
778 else {
779 if ((geom->num_doodads >= geom->sz_doodads) &&
780 (_XkbAllocDoodads(geom, 1) != Success))
781 return NULL;
782 doodad = &geom->doodads[geom->num_doodads++];
783 }
784 memset(doodad, 0, sizeof(XkbDoodadRec));
785 doodad->any.name = name;
786 return doodad;
787}
788
789XkbOverlayKeyPtr
790XkbAddGeomOverlayKey(XkbOverlayPtr overlay,
791 XkbOverlayRowPtr row, char *over, char *under)
792{
793 register int i;
794 XkbOverlayKeyPtr key;
795 XkbSectionPtr section;
796 XkbRowPtr row_under;
797 Bool found;
798
799 if ((!overlay) || (!row) || (!over) || (!under))
800 return NULL;
801 section = overlay->section_under;
802 if (row->row_under >= section->num_rows)
803 return NULL;
804 row_under = &section->rows[row->row_under];
805 for (i = 0, found = FALSE; i < row_under->num_keys; i++) {
806 if (strncmp(under, row_under->keys[i].name.name, XkbKeyNameLength) == 0) {
807 found = TRUE;
808 break;
809 }
810 }
811 if (!found)
812 return NULL;
813 if ((row->num_keys >= row->sz_keys) &&
814 (_XkbAllocOverlayKeys(row, 1) != Success))
815 return NULL;
816 key = &row->keys[row->num_keys];
817 strncpy(key->under.name, under, XkbKeyNameLength);
818 strncpy(key->over.name, over, XkbKeyNameLength);
819 row->num_keys++;
820 return key;
821}
822
823XkbOverlayRowPtr
824XkbAddGeomOverlayRow(XkbOverlayPtr overlay, int row_under, int sz_keys)
825{
826 register int i;
827 XkbOverlayRowPtr row;
828
829 if ((!overlay) || (sz_keys < 0))
830 return NULL;
831 if (row_under >= overlay->section_under->num_rows)
832 return NULL;
833 for (i = 0; i < overlay->num_rows; i++) {
834 if (overlay->rows[i].row_under == row_under) {
835 row = &overlay->rows[i];
836 if ((row->sz_keys < sz_keys) &&
837 (_XkbAllocOverlayKeys(row, sz_keys) != Success)) {
838 return NULL;
839 }
840 return &overlay->rows[i];
841 }
842 }
843 if ((overlay->num_rows >= overlay->sz_rows) &&
844 (_XkbAllocOverlayRows(overlay, 1) != Success))
845 return NULL;
846 row = &overlay->rows[overlay->num_rows];
847 memset(row, 0, sizeof(XkbOverlayRowRec));
848 if ((sz_keys > 0) && (_XkbAllocOverlayKeys(row, sz_keys) != Success))
849 return NULL;
850 row->row_under = row_under;
851 overlay->num_rows++;
852 return row;
853}
854
855XkbOverlayPtr
856XkbAddGeomOverlay(XkbSectionPtr section, Atom name, int sz_rows)
857{
858 register int i;
859 XkbOverlayPtr overlay;
860
861 if ((!section) || (name == None) || (sz_rows == 0))
862 return NULL;
863
864 for (i = 0, overlay = section->overlays; i < section->num_overlays;
865 i++, overlay++) {
866 if (overlay->name == name) {
867 if ((sz_rows > 0) &&
868 (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
869 return NULL;
870 return overlay;
871 }
872 }
873 if ((section->num_overlays >= section->sz_overlays) &&
874 (_XkbAllocOverlays(section, 1) != Success))
875 return NULL;
876 overlay = &section->overlays[section->num_overlays];
877 if ((sz_rows > 0) && (_XkbAllocOverlayRows(overlay, sz_rows) != Success))
878 return NULL;
879 overlay->name = name;
880 overlay->section_under = section;
881 section->num_overlays++;
882 return overlay;
883}