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 §ion->num_rows, §ion->sz_rows,
278 (char **) §ion->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 = §ion->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 = §ion->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 = §ion->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 = §ion->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