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 
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 
41 static void
_XkbFreeGeomLeafElems(Bool freeAll,int first,int count,unsigned short * num_inout,unsigned short * sz_inout,char ** elems,unsigned int elem_sz)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 
77 typedef void (*ContentsClearFunc) (char *       /* priv */
78     );
79 
80 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)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 
129 static void
_XkbClearProperty(char * prop_in)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 
141 void
XkbFreeGeomProperties(XkbGeometryPtr geom,int first,int count,Bool freeAll)142 XkbFreeGeomProperties(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 
153 void
XkbFreeGeomKeyAliases(XkbGeometryPtr geom,int first,int count,Bool freeAll)154 XkbFreeGeomKeyAliases(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 
164 static void
_XkbClearColor(char * color_in)165 _XkbClearColor(char *color_in)
166 {
167     XkbColorPtr color = (XkbColorPtr) color_in;
168 
169     free(color->spec);
170     return;
171 }
172 
173 void
XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)174 XkbFreeGeomColors(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 
185 void
XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)186 XkbFreeGeomPoints(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 
196 static void
_XkbClearOutline(char * outline_in)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 
206 void
XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll)207 XkbFreeGeomOutlines(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 
219 static void
_XkbClearShape(char * shape_in)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 
229 void
XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)230 XkbFreeGeomShapes(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 
241 void
XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)242 XkbFreeGeomOverlayKeys(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 
252 void
XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)253 XkbFreeGeomKeys(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 
263 static void
_XkbClearRow(char * row_in)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 
273 void
XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)274 XkbFreeGeomRows(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 
284 static void
_XkbClearSection(char * section_in)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 
298 void
XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)299 XkbFreeGeomSections(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 
310 static void
_XkbClearDoodad(char * doodad_in)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 
334 void
XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)335 XkbFreeGeomDoodads(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 
350 void
XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)351 XkbFreeGeometry(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  */
397 Bool
XkbGeomRealloc(void ** buffer,int szItems,int nrItems,int itemSize,XkbGeomClearance clearance)398 XkbGeomRealloc(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 = reallocarray(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 
434 static Status
_XkbGeomAlloc(void ** old,unsigned short * num,unsigned short * total,int num_new,size_t sz_elem)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 
500 Status
XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)501 XkbAllocGeometry(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 
546 XkbPropertyPtr
XkbAddGeomProperty(XkbGeometryPtr geom,char * name,char * value)547 XkbAddGeomProperty(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 
579 XkbKeyAliasPtr
XkbAddGeomKeyAlias(XkbGeometryPtr geom,char * aliasStr,char * realStr)580 XkbAddGeomKeyAlias(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             memcpy(alias->real, realStr, strnlen(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     memcpy(alias->alias, aliasStr, strnlen(aliasStr, XkbKeyNameLength));
602     memcpy(alias->real, realStr, strnlen(realStr, XkbKeyNameLength));
603     geom->num_key_aliases++;
604     return alias;
605 }
606 
607 XkbColorPtr
XkbAddGeomColor(XkbGeometryPtr geom,char * spec,unsigned int pixel)608 XkbAddGeomColor(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 
634 XkbOutlinePtr
XkbAddGeomOutline(XkbShapePtr shape,int sz_points)635 XkbAddGeomOutline(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 
653 XkbShapePtr
XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)654 XkbAddGeomShape(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 
680 XkbKeyPtr
XkbAddGeomKey(XkbRowPtr row)681 XkbAddGeomKey(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 
694 XkbRowPtr
XkbAddGeomRow(XkbSectionPtr section,int sz_keys)695 XkbAddGeomRow(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 
712 XkbSectionPtr
XkbAddGeomSection(XkbGeometryPtr geom,Atom name,int sz_rows,int sz_doodads,int sz_over)713 XkbAddGeomSection(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 
751 XkbDoodadPtr
XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)752 XkbAddGeomDoodad(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 
789 XkbOverlayKeyPtr
XkbAddGeomOverlayKey(XkbOverlayPtr overlay,XkbOverlayRowPtr row,char * over,char * under)790 XkbAddGeomOverlayKey(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     memcpy(key->under.name, under, strnlen(under, XkbKeyNameLength));
818     memcpy(key->over.name, over, strnlen(over, XkbKeyNameLength));
819     row->num_keys++;
820     return key;
821 }
822 
823 XkbOverlayRowPtr
XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)824 XkbAddGeomOverlayRow(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 
855 XkbOverlayPtr
XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)856 XkbAddGeomOverlay(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 }
884