Use CARD32 instead of Atom, move geom headers in
[platform/upstream/libxkbcommon.git] / src / galloc.c
1 /*
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 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 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "xkbgeom.h"
30 #include "X11/extensions/XKBcommon.h"
31 #include "XKBcommonint.h"
32 #include <X11/extensions/XKB.h>
33
34 static void
35 _XkbFreeGeomLeafElems(Bool freeAll, int first, int count,
36                       unsigned short *num_inout, unsigned short *sz_inout,
37                       char **elems, unsigned int elem_sz)
38 {
39     if (freeAll || !(*elems)) {
40         *num_inout = *sz_inout = 0;
41         if (*elems) {
42             _XkbFree(*elems);
43             *elems = NULL;
44         }
45         return;
46     }
47
48     if ((first >= (*num_inout)) || (first < 0) || (count < 1))
49         return;
50
51     if (first + count >= (*num_inout))
52         /* truncating the array is easy */
53         (*num_inout) = first;
54     else {
55         char *ptr = *elems;
56         int extra = ((*num_inout) - first + count) * elem_sz;
57
58         if (extra > 0)
59             memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz],
60                     extra);
61
62         (*num_inout) -= count;
63     }
64 }
65
66 typedef void (*ContentsClearFunc)(char *priv);
67
68 static void
69 _XkbFreeGeomNonLeafElems(Bool freeAll, int first, int count,
70                          unsigned short *num_inout, unsigned short *sz_inout,
71                          char **elems, unsigned int elem_sz,
72                          ContentsClearFunc freeFunc)
73 {
74     int i;
75     char *ptr;
76
77     if (freeAll) {
78         first = 0;
79         count = *num_inout;
80     }
81     else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
82         return;
83     else if (first + count > (*num_inout))
84         count = (*num_inout) - first;
85
86     if (!(*elems))
87         return;
88
89     if (freeFunc) {
90         ptr = *elems;
91         ptr += first * elem_sz;
92         for (i = 0; i < count; i++) {
93             (*freeFunc)(ptr);
94             ptr += elem_sz;
95         }
96     }
97
98     if (freeAll) {
99         *num_inout = *sz_inout = 0;
100         if (*elems) {
101             _XkbFree(*elems);
102             *elems = NULL;
103         }
104     }
105     else if (first + count >= (*num_inout))
106         *num_inout = first;
107     else {
108         i = ((*num_inout) - first + count) * elem_sz;
109         ptr = *elems;
110         memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz], i);
111         (*num_inout) -= count;
112     }
113 }
114
115 static void
116 _XkbClearProperty(char *prop_in)
117 {
118     XkbcPropertyPtr prop = (XkbcPropertyPtr)prop_in;
119
120     if (prop->name) {
121         _XkbFree(prop->name);
122         prop->name = NULL;
123     }
124     if (prop->value) {
125         _XkbFree(prop->value);
126         prop->value = NULL;
127     }
128 }
129
130 void
131 XkbcFreeGeomProperties(XkbcGeometryPtr geom, int first, int count, Bool freeAll)
132 {
133     _XkbFreeGeomNonLeafElems(freeAll, first, count,
134                              &geom->num_properties, &geom->sz_properties,
135                              (char **)&geom->properties,
136                              sizeof(XkbcPropertyRec),
137                              _XkbClearProperty);
138 }
139
140 void
141 XkbcFreeGeomKeyAliases(XkbcGeometryPtr geom, int first, int count, Bool freeAll)
142 {
143     _XkbFreeGeomLeafElems(freeAll, first, count,
144                           &geom->num_key_aliases, &geom->sz_key_aliases,
145                           (char **)&geom->key_aliases,
146                           sizeof(XkbKeyAliasRec));
147 }
148
149 static void
150 _XkbClearColor(char *color_in)
151 {
152     XkbcColorPtr color = (XkbcColorPtr)color_in;
153
154     if (color->spec)
155         _XkbFree(color->spec);
156 }
157
158 void
159 XkbcFreeGeomColors(XkbcGeometryPtr geom, int first, int count, Bool freeAll)
160 {
161     _XkbFreeGeomNonLeafElems(freeAll, first, count,
162                              &geom->num_colors, &geom->sz_colors,
163                              (char **)&geom->colors, sizeof(XkbcColorRec),
164                              _XkbClearColor);
165 }
166
167 void
168 XkbcFreeGeomPoints(XkbcOutlinePtr outline, int first, int count, Bool freeAll)
169 {
170     _XkbFreeGeomLeafElems(freeAll, first, count,
171                           &outline->num_points, &outline->sz_points,
172                           (char **)&outline->points, sizeof(XkbcPointRec));
173 }
174
175 static void
176 _XkbClearOutline(char *outline_in)
177 {
178     XkbcOutlinePtr outline = (XkbcOutlinePtr)outline_in;
179
180     if (outline->points)
181         XkbcFreeGeomPoints(outline, 0, outline->num_points, True);
182 }
183
184 void
185 XkbcFreeGeomOutlines(XkbcShapePtr shape, int first, int count, Bool freeAll)
186 {
187     _XkbFreeGeomNonLeafElems(freeAll, first, count,
188                              &shape->num_outlines, &shape->sz_outlines,
189                              (char **)&shape->outlines, sizeof(XkbcOutlineRec),
190                              _XkbClearOutline);
191 }
192
193 static void
194 _XkbClearShape(char *shape_in)
195 {
196     XkbcShapePtr shape = (XkbcShapePtr)shape_in;
197
198     if (shape->outlines)
199         XkbcFreeGeomOutlines(shape, 0, shape->num_outlines, True);
200 }
201
202 void
203 XkbcFreeGeomShapes(XkbcGeometryPtr geom, int first, int count, Bool freeAll)
204 {
205     _XkbFreeGeomNonLeafElems(freeAll, first, count,
206                              &geom->num_shapes, &geom->sz_shapes,
207                              (char **)&geom->shapes, sizeof(XkbcShapeRec),
208                              _XkbClearShape);
209 }
210
211 void
212 XkbcFreeGeomOverlayKeys(XkbcOverlayRowPtr row, int first, int count,
213                         Bool freeAll)
214 {
215     _XkbFreeGeomLeafElems(freeAll, first, count,
216                           &row->num_keys, &row->sz_keys,
217                           (char **)&row->keys, sizeof(XkbcOverlayKeyRec));
218 }
219
220
221 static void
222 _XkbClearOverlayRow(char *row_in)
223 {
224     XkbcOverlayRowPtr row = (XkbcOverlayRowPtr)row_in;
225
226     if (row->keys)
227         XkbcFreeGeomOverlayKeys(row, 0, row->num_keys, True);
228 }
229
230 void
231 XkbcFreeGeomOverlayRows(XkbcOverlayPtr overlay, int first, int count,
232                         Bool freeAll)
233 {
234     _XkbFreeGeomNonLeafElems(freeAll, first, count,
235                              &overlay->num_rows, &overlay->sz_rows,
236                              (char **)&overlay->rows,
237                              sizeof(XkbcOverlayRowRec),
238                              _XkbClearOverlayRow);
239 }
240
241
242 static void
243 _XkbClearOverlay(char *overlay_in)
244 {
245     XkbcOverlayPtr overlay = (XkbcOverlayPtr)overlay_in;
246
247     if (overlay->rows)
248         XkbcFreeGeomOverlayRows(overlay, 0, overlay->num_rows, True);
249 }
250
251 void
252 XkbcFreeGeomOverlays(XkbcSectionPtr section, int first, int count, Bool freeAll)
253 {
254     _XkbFreeGeomNonLeafElems(freeAll, first, count,
255                              &section->num_overlays, &section->sz_overlays,
256                              (char **)&section->overlays,
257                              sizeof(XkbcOverlayRec),
258                              _XkbClearOverlay);
259 }
260
261
262 void
263 XkbcFreeGeomKeys(XkbcRowPtr row, int first, int count, Bool freeAll)
264 {
265     _XkbFreeGeomLeafElems(freeAll, first, count,
266                           &row->num_keys, &row->sz_keys,
267                           (char **)&row->keys, sizeof(XkbcKeyRec));
268 }
269
270
271 static void
272 _XkbClearRow(char *row_in)
273 {
274     XkbcRowPtr row = (XkbcRowPtr)row_in;
275
276     if (row->keys)
277         XkbcFreeGeomKeys(row, 0, row->num_keys, True);
278 }
279
280 void
281 XkbcFreeGeomRows(XkbcSectionPtr section, int first, int count, Bool freeAll)
282 {
283     _XkbFreeGeomNonLeafElems(freeAll, first, count,
284                              &section->num_rows, &section->sz_rows,
285                              (char **)&section->rows, sizeof(XkbcRowRec),
286                              _XkbClearRow);
287 }
288
289
290 static void
291 _XkbClearSection(char *section_in)
292 {
293     XkbcSectionPtr section = (XkbcSectionPtr)section_in;
294
295     if (section->rows)
296         XkbcFreeGeomRows(section, 0, section->num_rows, True);
297     if (section->doodads) {
298         XkbcFreeGeomDoodads(section->doodads, section->num_doodads, True);
299         section->doodads = NULL;
300     }
301 }
302
303 void
304 XkbcFreeGeomSections(XkbcGeometryPtr geom, int first, int count, Bool freeAll)
305 {
306     _XkbFreeGeomNonLeafElems(freeAll, first, count,
307                              &geom->num_sections, &geom->sz_sections,
308                              (char **)&geom->sections, sizeof(XkbcSectionRec),
309                              _XkbClearSection);
310 }
311
312
313 static void
314 _XkbClearDoodad(char *doodad_in)
315 {
316     XkbcDoodadPtr doodad = (XkbcDoodadPtr)doodad_in;
317
318     switch (doodad->any.type) {
319     case XkbTextDoodad:
320         if (doodad->text.text) {
321             _XkbFree(doodad->text.text);
322             doodad->text.text = NULL;
323         }
324         if (doodad->text.font) {
325             _XkbFree(doodad->text.font);
326             doodad->text.font = NULL;
327         }
328         break;
329
330     case XkbLogoDoodad:
331         if (doodad->logo.logo_name) {
332             _XkbFree(doodad->logo.logo_name);
333             doodad->logo.logo_name = NULL;
334         }
335         break;
336     }
337 }
338
339 void
340 XkbcFreeGeomDoodads(XkbcDoodadPtr doodads, int nDoodads, Bool freeAll)
341 {
342     int i;
343     XkbcDoodadPtr doodad;
344
345     if (doodads) {
346         for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++)
347             _XkbClearDoodad((char *)doodad);
348         if (freeAll)
349             _XkbFree(doodads);
350     }
351 }
352
353 void
354 XkbcFreeGeometry(XkbcGeometryPtr geom, unsigned which, Bool freeMap)
355 {
356     if (!geom)
357         return;
358
359     if (freeMap)
360         which = XkbGeomAllMask;
361
362     if ((which & XkbGeomPropertiesMask) && geom->properties)
363         XkbcFreeGeomProperties(geom, 0, geom->num_properties, True);
364
365     if ((which & XkbGeomColorsMask) && geom->colors)
366         XkbcFreeGeomColors(geom, 0, geom->num_colors, True);
367
368     if ((which & XkbGeomShapesMask) && geom->shapes)
369         XkbcFreeGeomShapes(geom, 0, geom->num_shapes, True);
370
371     if ((which & XkbGeomSectionsMask) && geom->sections)
372         XkbcFreeGeomSections(geom, 0, geom->num_sections, True);
373
374     if ((which & XkbGeomDoodadsMask) && geom->doodads) {
375         XkbcFreeGeomDoodads(geom->doodads, geom->num_doodads, True);
376         geom->doodads = NULL;
377         geom->num_doodads = geom->sz_doodads = 0;
378     }
379
380     if ((which & XkbGeomKeyAliasesMask) && geom->key_aliases)
381         XkbcFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, True);
382
383     if (freeMap) {
384         if (geom->label_font) {
385             _XkbFree(geom->label_font);
386             geom->label_font = NULL;
387         }
388         _XkbFree(geom);
389     }
390 }
391
392 static int
393 _XkbGeomAlloc(char **old, unsigned short *num, unsigned short *total,
394               int num_new, size_t sz_elem)
395 {
396     if (num_new < 1)
397         return Success;
398
399     if (!(*old))
400         *num = *total = 0;
401
402     if ((*num) + num_new <= (*total))
403         return Success;
404
405     *total = (*num) + num_new;
406
407     if (*old)
408         *old = (char *)_XkbRealloc(*old, (*total) * sz_elem);
409     else
410         *old = (char *)_XkbCalloc(*total, sz_elem);
411     if (!(*old)) {
412         *total = *num = 0;
413         return BadAlloc;
414     }
415
416     if (*num > 0) {
417         char *tmp = *old;
418         bzero(&tmp[sz_elem * (*num)], num_new * sz_elem);
419     }
420
421     return Success;
422 }
423
424 #define _XkbAllocProps(g, n)    _XkbGeomAlloc((char **)&(g)->properties, \
425                                               &(g)->num_properties, \
426                                               &(g)->sz_properties, \
427                                               (n), sizeof(XkbcPropertyRec))
428 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
429                                               &(g)->num_colors, \
430                                               &(g)->sz_colors, \
431                                               (n), sizeof(XkbcColorRec))
432 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
433                                               &(g)->num_shapes, \
434                                               &(g)->sz_shapes, \
435                                               (n), sizeof(XkbcShapeRec))
436 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
437                                               &(g)->num_sections, \
438                                               &(g)->sz_sections, \
439                                               (n), sizeof(XkbcSectionRec))
440 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
441                                               &(g)->num_doodads, \
442                                               &(g)->sz_doodads, \
443                                               (n), sizeof(XkbcDoodadRec))
444 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
445                                                   &(g)->num_key_aliases, \
446                                                   &(g)->sz_key_aliases, \
447                                                   (n), sizeof(XkbKeyAliasRec))
448
449 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
450                                               &(s)->num_outlines, \
451                                               &(s)->sz_outlines, \
452                                               (n), sizeof(XkbcOutlineRec))
453 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
454                                               &(s)->num_rows, \
455                                               &(s)->sz_rows, \
456                                               (n), sizeof(XkbcRowRec))
457 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
458                                               &(o)->num_points, \
459                                               &(o)->sz_points, \
460                                               (n), sizeof(XkbcPointRec))
461 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
462                                               &(r)->num_keys, \
463                                               &(r)->sz_keys, \
464                                               (n), sizeof(XkbcKeyRec))
465 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
466                                               &(s)->num_overlays, \
467                                               &(s)->sz_overlays, \
468                                               (n), sizeof(XkbcOverlayRec))
469 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
470                                                   &(o)->num_rows, \
471                                                   &(o)->sz_rows, \
472                                                   (n), sizeof(XkbcOverlayRowRec))
473 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
474                                                   &(r)->num_keys, \
475                                                   &(r)->sz_keys, \
476                                                   (n), sizeof(XkbcOverlayKeyRec))
477
478 int
479 XkbcAllocGeomProps(XkbcGeometryPtr geom, int nProps)
480 {
481     return _XkbAllocProps(geom, nProps);
482 }
483
484 int
485 XkbcAllocGeomColors(XkbcGeometryPtr geom, int nColors)
486 {
487     return _XkbAllocColors(geom, nColors);
488 }
489
490 int
491 XkbcAllocGeomKeyAliases(XkbcGeometryPtr geom, int nKeyAliases)
492 {
493     return _XkbAllocKeyAliases(geom, nKeyAliases);
494 }
495
496 int
497 XkbcAllocGeomShapes(XkbcGeometryPtr geom, int nShapes)
498 {
499     return _XkbAllocShapes(geom, nShapes);
500 }
501
502 int
503 XkbcAllocGeomSections(XkbcGeometryPtr geom, int nSections)
504 {
505     return _XkbAllocSections(geom, nSections);
506 }
507
508 int
509 XkbcAllocGeomOverlays(XkbcSectionPtr section, int nOverlays)
510 {
511     return _XkbAllocOverlays(section, nOverlays);
512 }
513
514 int
515 XkbcAllocGeomOverlayRows(XkbcOverlayPtr overlay, int nRows)
516 {
517     return _XkbAllocOverlayRows(overlay, nRows);
518 }
519
520 int
521 XkbcAllocGeomOverlayKeys(XkbcOverlayRowPtr row, int nKeys)
522 {
523     return _XkbAllocOverlayKeys(row, nKeys);
524 }
525
526 int
527 XkbcAllocGeomDoodads(XkbcGeometryPtr geom, int nDoodads)
528 {
529     return _XkbAllocDoodads(geom, nDoodads);
530 }
531
532 int
533 XkbcAllocGeomSectionDoodads(XkbcSectionPtr section, int nDoodads)
534 {
535     return _XkbAllocDoodads(section, nDoodads);
536 }
537
538 int
539 XkbcAllocGeomOutlines(XkbcShapePtr shape, int nOL)
540 {
541     return _XkbAllocOutlines(shape, nOL);
542 }
543
544 int
545 XkbcAllocGeomRows(XkbcSectionPtr section, int nRows)
546 {
547     return _XkbAllocRows(section, nRows);
548 }
549
550 int
551 XkbcAllocGeomPoints(XkbcOutlinePtr ol, int nPts)
552 {
553     return _XkbAllocPoints(ol, nPts);
554 }
555
556 int
557 XkbcAllocGeomKeys(XkbcRowPtr row, int nKeys)
558 {
559     int ret = _XkbAllocKeys(row, nKeys);
560     fprintf(stderr, "!!! allocated %d keys at %p\n", nKeys, row->keys);
561     return ret;
562 }
563
564 int
565 XkbcAllocGeometry(XkbcDescPtr xkb, XkbcGeometrySizesPtr sizes)
566 {
567     XkbcGeometryPtr geom;
568     int rtrn;
569
570     if (!xkb->geom) {
571         xkb->geom = _XkbTypedCalloc(1, XkbcGeometryRec);
572         if (!xkb->geom)
573             return BadAlloc;
574     }
575     geom = xkb->geom;
576
577     if ((sizes->which & XkbGeomPropertiesMask) &&
578         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
579         goto bail;
580
581     if ((sizes->which & XkbGeomColorsMask) &&
582         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
583         goto bail;
584
585     if ((sizes->which & XkbGeomShapesMask) &&
586         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
587         goto bail;
588
589     if ((sizes->which & XkbGeomSectionsMask) &&
590         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
591         goto bail;
592
593     if ((sizes->which & XkbGeomDoodadsMask) &&
594         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
595         goto bail;
596
597     if ((sizes->which & XkbGeomKeyAliasesMask) &&
598         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
599         goto bail;
600
601     return Success;
602 bail:
603     XkbcFreeGeometry(geom, XkbGeomAllMask, True);
604     xkb->geom = NULL;
605     return rtrn;
606 }
607
608 XkbcPropertyPtr
609 XkbcAddGeomProperty(XkbcGeometryPtr geom,char *name,char *value)
610 {
611 register int i;
612 register XkbcPropertyPtr prop;
613
614     if ((!geom)||(!name)||(!value))
615         return NULL;
616     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
617         if ((prop->name)&&(strcmp(name,prop->name)==0)) {
618             if (prop->value)
619                 _XkbFree(prop->value);
620             prop->value= (char *)_XkbAlloc(strlen(value)+1);
621             if (prop->value)
622                 strcpy(prop->value,value);
623             return prop;
624         }
625     }
626     if ((geom->num_properties>=geom->sz_properties)&&
627                                         (_XkbAllocProps(geom,1)!=Success)) {
628         return NULL;
629     }
630     prop= &geom->properties[geom->num_properties];
631     prop->name= (char *)_XkbAlloc(strlen(name)+1);
632     if (!name)
633         return NULL;
634     strcpy(prop->name,name);
635     prop->value= (char *)_XkbAlloc(strlen(value)+1);
636     if (!value) {
637         _XkbFree(prop->name);
638         prop->name= NULL;
639         return NULL;
640     }
641     strcpy(prop->value,value);
642     geom->num_properties++;
643     return prop;
644 }
645
646 XkbKeyAliasPtr
647 XkbcAddGeomKeyAlias(XkbcGeometryPtr geom,char *aliasStr,char *realStr)
648 {
649 register int i;
650 register XkbKeyAliasPtr alias;
651
652     if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
653         return NULL;
654     for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
655         if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
656             bzero(alias->real,XkbKeyNameLength);
657             strncpy(alias->real,realStr,XkbKeyNameLength);
658             return alias;
659         }
660     }
661     if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
662                                 (_XkbAllocKeyAliases(geom,1)!=Success)) {
663         return NULL;
664     }
665     alias= &geom->key_aliases[geom->num_key_aliases];
666     bzero(alias,sizeof(XkbKeyAliasRec));
667     strncpy(alias->alias,aliasStr,XkbKeyNameLength);
668     strncpy(alias->real,realStr,XkbKeyNameLength);
669     geom->num_key_aliases++;
670     return alias;
671 }
672
673 XkbcColorPtr
674 XkbcAddGeomColor(XkbcGeometryPtr geom,char *spec,unsigned int pixel)
675 {
676 register int i;
677 register XkbcColorPtr color;
678
679     if ((!geom)||(!spec))
680         return NULL;
681     for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
682         if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
683             color->pixel= pixel;
684             return color;
685         }
686     }
687     if ((geom->num_colors>=geom->sz_colors)&&
688                                         (_XkbAllocColors(geom,1)!=Success)) {
689         return NULL;
690     }
691     color= &geom->colors[geom->num_colors];
692     color->pixel= pixel;
693     color->spec= (char *)_XkbAlloc(strlen(spec)+1);
694     if (!color->spec)
695         return NULL;
696     strcpy(color->spec,spec);
697     geom->num_colors++;
698     return color;
699 }
700
701 XkbcOutlinePtr
702 XkbcAddGeomOutline(XkbcShapePtr shape,int sz_points)
703 {
704 XkbcOutlinePtr  outline;
705
706     if ((!shape)||(sz_points<0))
707         return NULL;
708     if ((shape->num_outlines>=shape->sz_outlines)&&
709                                         (_XkbAllocOutlines(shape,1)!=Success)) {
710         return NULL;
711     }
712     outline= &shape->outlines[shape->num_outlines];
713     bzero(outline,sizeof(XkbcOutlineRec));
714     if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
715         return NULL;
716     shape->num_outlines++;
717     return outline;
718 }
719
720 XkbcShapePtr
721 XkbcAddGeomShape(XkbcGeometryPtr geom,CARD32 name,int sz_outlines)
722 {
723 XkbcShapePtr    shape;
724 register int    i;
725
726     if ((!geom)||(!name)||(sz_outlines<0))
727         return NULL;
728     if (geom->num_shapes>0) {
729         for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
730             if (name==shape->name)
731                 return shape;
732         }
733     }
734     if ((geom->num_shapes>=geom->sz_shapes)&&
735                                         (_XkbAllocShapes(geom,1)!=Success))
736         return NULL;
737     shape= &geom->shapes[geom->num_shapes];
738     bzero(shape,sizeof(XkbcShapeRec));
739     if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
740         return NULL;
741     shape->name= name;
742     shape->primary= shape->approx= NULL;
743     geom->num_shapes++;
744     return shape;
745 }
746
747 XkbcKeyPtr
748 XkbcAddGeomKey(XkbcRowPtr row)
749 {
750 XkbcKeyPtr      key;
751     if (!row)
752         return NULL;
753     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
754         return NULL;
755     key= &row->keys[row->num_keys++];
756     bzero(key,sizeof(XkbcKeyRec));
757     return key;
758 }
759
760 XkbcRowPtr
761 XkbcAddGeomRow(XkbcSectionPtr section,int sz_keys)
762 {
763 XkbcRowPtr      row;
764
765     if ((!section)||(sz_keys<0))
766         return NULL;
767     if ((section->num_rows>=section->sz_rows)&&
768                                         (_XkbAllocRows(section,1)!=Success))
769         return NULL;
770     row= &section->rows[section->num_rows];
771     bzero(row,sizeof(XkbcRowRec));
772     if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
773         return NULL;
774     section->num_rows++;
775     return row;
776 }
777
778 XkbcSectionPtr
779 XkbcAddGeomSection(     XkbcGeometryPtr geom,
780                         CARD32          name,
781                         int             sz_rows,
782                         int             sz_doodads,
783                         int             sz_over)
784 {
785 register int    i;
786 XkbcSectionPtr  section;
787
788     if ((!geom)||(name==None)||(sz_rows<0))
789         return NULL;
790     for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
791         if (section->name!=name)
792             continue;
793         if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
794             ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
795             ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
796             return NULL;
797         return section;
798     }
799     if ((geom->num_sections>=geom->sz_sections)&&
800                                         (_XkbAllocSections(geom,1)!=Success))
801         return NULL;
802     section= &geom->sections[geom->num_sections];
803     if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
804         return NULL;
805     if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
806         if (section->rows) {
807             _XkbFree(section->rows);
808             section->rows= NULL;
809             section->sz_rows= section->num_rows= 0;
810         }
811         return NULL;
812     }
813     section->name= name;
814     geom->num_sections++;
815     return section;
816 }
817
818 XkbcDoodadPtr
819 XkbcAddGeomDoodad(XkbcGeometryPtr geom,XkbcSectionPtr section,CARD32 name)
820 {
821 XkbcDoodadPtr   old,doodad;
822 register int    i,nDoodads;
823
824     if ((!geom)||(name==None))
825         return NULL;
826     if ((section!=NULL)&&(section->num_doodads>0)) {
827         old= section->doodads;
828         nDoodads= section->num_doodads;
829     }
830     else {
831         old= geom->doodads;
832         nDoodads= geom->num_doodads;
833     }
834     for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
835         if (doodad->any.name==name)
836             return doodad;
837     }
838     if (section) {
839         if ((section->num_doodads>=geom->sz_doodads)&&
840             (_XkbAllocDoodads(section,1)!=Success)) {
841             return NULL;
842         }
843         doodad= &section->doodads[section->num_doodads++];
844     }
845     else {
846         if ((geom->num_doodads>=geom->sz_doodads)&&
847                                         (_XkbAllocDoodads(geom,1)!=Success))
848             return NULL;
849         doodad= &geom->doodads[geom->num_doodads++];
850     }
851     bzero(doodad,sizeof(XkbcDoodadRec));
852     doodad->any.name= name;
853     return doodad;
854 }
855
856 XkbcOverlayKeyPtr
857 XkbcAddGeomOverlayKey(  XkbcOverlayPtr          overlay,
858                         XkbcOverlayRowPtr       row,
859                         char *                  over,
860                         char *                  under)
861 {
862 register int    i;
863 XkbcOverlayKeyPtr key;
864 XkbcSectionPtr  section;
865 XkbcRowPtr      row_under;
866 Bool            found;
867
868     if ((!overlay)||(!row)||(!over)||(!under))
869         return NULL;
870     section= overlay->section_under;
871     if (row->row_under>=section->num_rows)
872         return NULL;
873     row_under= &section->rows[row->row_under];
874     for (i=0,found=False;i<row_under->num_keys;i++) {
875         if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
876             found= True;
877             break;
878         }
879     }
880     if (!found)
881         return NULL;
882     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
883         return NULL;
884     key= &row->keys[row->num_keys];
885     strncpy(key->under.name,under,XkbKeyNameLength);
886     strncpy(key->over.name,over,XkbKeyNameLength);
887     row->num_keys++;
888     return key;
889 }
890
891 XkbcOverlayRowPtr
892 XkbcAddGeomOverlayRow(XkbcOverlayPtr overlay,int row_under,int sz_keys)
893 {
894 register int            i;
895 XkbcOverlayRowPtr       row;
896
897     if ((!overlay)||(sz_keys<0))
898         return NULL;
899     if (row_under>=overlay->section_under->num_rows)
900         return NULL;
901     for (i=0;i<overlay->num_rows;i++) {
902         if (overlay->rows[i].row_under==row_under) {
903             row= &overlay->rows[i];
904             if ((row->sz_keys<sz_keys)&&
905                                 (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
906                 return NULL;
907             }
908             return &overlay->rows[i];
909         }
910     }
911     if ((overlay->num_rows>=overlay->sz_rows)&&
912                                 (_XkbAllocOverlayRows(overlay,1)!=Success))
913         return NULL;
914     row= &overlay->rows[overlay->num_rows];
915     bzero(row,sizeof(XkbcOverlayRowRec));
916     if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
917         return NULL;
918     row->row_under= row_under;
919     overlay->num_rows++;
920     return row;
921 }
922
923 XkbcOverlayPtr
924 XkbcAddGeomOverlay(XkbcSectionPtr section,CARD32 name,int sz_rows)
925 {
926 register int    i;
927 XkbcOverlayPtr  overlay;
928
929     if ((!section)||(name==None)||(sz_rows==0))
930         return NULL;
931
932     for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
933         if (overlay->name==name) {
934             if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
935                 return NULL;
936             return overlay;
937         }
938     }
939     if ((section->num_overlays>=section->sz_overlays)&&
940                                 (_XkbAllocOverlays(section,1)!=Success))
941         return NULL;
942     overlay= &section->overlays[section->num_overlays];
943     if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
944         return NULL;
945     overlay->name= name;
946     overlay->section_under= section;
947     section->num_overlays++;
948     return overlay;
949 }