Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
165 | _XkbClearColor(char *color_in) | |
166 | { | |
167 | XkbColorPtr color = (XkbColorPtr) color_in; | |
168 | ||
169 | free(color->spec); | |
170 | return; | |
171 | } | |
172 | ||
173 | void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 = realloc(items, nrItems * itemSize))) | |
413 | return FALSE; | |
414 | /* Clear specified items to zero. */ | |
415 | switch (clearance) { | |
416 | case XKB_GEOM_CLEAR_EXCESS: | |
417 | clearBegin = szItems; | |
418 | break; | |
419 | case XKB_GEOM_CLEAR_ALL: | |
420 | clearBegin = 0; | |
421 | break; | |
422 | case XKB_GEOM_CLEAR_NONE: | |
423 | default: | |
424 | clearBegin = nrItems; | |
425 | break; | |
426 | } | |
427 | if (items && (clearBegin < nrItems)) | |
428 | memset((char *) items + (clearBegin * itemSize), 0, | |
429 | (nrItems - clearBegin) * itemSize); | |
430 | *buffer = items; | |
431 | return TRUE; | |
432 | } | |
433 | ||
434 | static Status | |
435 | _XkbGeomAlloc(void **old, | |
436 | unsigned short *num, | |
437 | unsigned short *total, int num_new, size_t sz_elem) | |
438 | { | |
439 | if (num_new < 1) | |
440 | return Success; | |
441 | if ((*old) == NULL) | |
442 | *num = *total = 0; | |
443 | ||
444 | if ((*num) + num_new <= (*total)) | |
445 | return Success; | |
446 | ||
447 | *total = (*num) + num_new; | |
448 | ||
449 | if (!XkbGeomRealloc(old, *num, *total, sz_elem, XKB_GEOM_CLEAR_EXCESS)) { | |
450 | free(*old); | |
451 | (*old) = NULL; | |
452 | *total = *num = 0; | |
453 | return BadAlloc; | |
454 | } | |
455 | ||
456 | return Success; | |
457 | } | |
458 | ||
459 | #define _XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\ | |
460 | &(g)->num_properties,&(g)->sz_properties,\ | |
461 | (n),sizeof(XkbPropertyRec)) | |
462 | #define _XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\ | |
463 | &(g)->num_colors,&(g)->sz_colors,\ | |
464 | (n),sizeof(XkbColorRec)) | |
465 | #define _XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\ | |
466 | &(g)->num_shapes,&(g)->sz_shapes,\ | |
467 | (n),sizeof(XkbShapeRec)) | |
468 | #define _XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\ | |
469 | &(g)->num_sections,&(g)->sz_sections,\ | |
470 | (n),sizeof(XkbSectionRec)) | |
471 | #define _XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\ | |
472 | &(g)->num_doodads,&(g)->sz_doodads,\ | |
473 | (n),sizeof(XkbDoodadRec)) | |
474 | #define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\ | |
475 | &(g)->num_key_aliases,&(g)->sz_key_aliases,\ | |
476 | (n),sizeof(XkbKeyAliasRec)) | |
477 | ||
478 | #define _XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\ | |
479 | &(s)->num_outlines,&(s)->sz_outlines,\ | |
480 | (n),sizeof(XkbOutlineRec)) | |
481 | #define _XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\ | |
482 | &(s)->num_rows,&(s)->sz_rows,\ | |
483 | (n),sizeof(XkbRowRec)) | |
484 | #define _XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\ | |
485 | &(o)->num_points,&(o)->sz_points,\ | |
486 | (n),sizeof(XkbPointRec)) | |
487 | #define _XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ | |
488 | &(r)->num_keys,&(r)->sz_keys,\ | |
489 | (n),sizeof(XkbKeyRec)) | |
490 | #define _XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\ | |
491 | &(s)->num_overlays,&(s)->sz_overlays,\ | |
492 | (n),sizeof(XkbOverlayRec)) | |
493 | #define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\ | |
494 | &(o)->num_rows,&(o)->sz_rows,\ | |
495 | (n),sizeof(XkbOverlayRowRec)) | |
496 | #define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ | |
497 | &(r)->num_keys,&(r)->sz_keys,\ | |
498 | (n),sizeof(XkbOverlayKeyRec)) | |
499 | ||
500 | Status | |
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 | |
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 | |
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 | strncpy(alias->real, realStr, XkbKeyNameLength); | |
592 | return alias; | |
593 | } | |
594 | } | |
595 | if ((geom->num_key_aliases >= geom->sz_key_aliases) && | |
596 | (_XkbAllocKeyAliases(geom, 1) != Success)) { | |
597 | return NULL; | |
598 | } | |
599 | alias = &geom->key_aliases[geom->num_key_aliases]; | |
600 | memset(alias, 0, sizeof(XkbKeyAliasRec)); | |
601 | strncpy(alias->alias, aliasStr, XkbKeyNameLength); | |
602 | strncpy(alias->real, realStr, XkbKeyNameLength); | |
603 | geom->num_key_aliases++; | |
604 | return alias; | |
605 | } | |
606 | ||
607 | XkbColorPtr | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | strncpy(key->under.name, under, XkbKeyNameLength); | |
818 | strncpy(key->over.name, over, XkbKeyNameLength); | |
819 | row->num_keys++; | |
820 | return key; | |
821 | } | |
822 | ||
823 | XkbOverlayRowPtr | |
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 | |
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 | } |