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 DEBUG
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <stdio.h>
32 #endif
33 
34 #define NEED_MAP_READERS
35 #include "Xlibint.h"
36 #include "X11/extensions/XKBgeom.h"
37 #include <X11/extensions/XKBproto.h>
38 #include "XKBlibint.h"
39 
40 #ifndef MINSHORT
41 #define	MINSHORT	-32768
42 #endif
43 #ifndef MAXSHORT
44 #define	MAXSHORT	32767
45 #endif
46 
47 /***====================================================================***/
48 
49 static void
_XkbCheckBounds(XkbBoundsPtr bounds,int x,int y)50 _XkbCheckBounds(XkbBoundsPtr bounds, int x, int y)
51 {
52     if (x < bounds->x1)
53         bounds->x1 = x;
54     if (x > bounds->x2)
55         bounds->x2 = x;
56     if (y < bounds->y1)
57         bounds->y1 = y;
58     if (y > bounds->y2)
59         bounds->y2 = y;
60     return;
61 }
62 
63 Bool
XkbComputeShapeBounds(XkbShapePtr shape)64 XkbComputeShapeBounds(XkbShapePtr shape)
65 {
66     register int o, p;
67     XkbOutlinePtr outline;
68     XkbPointPtr pt;
69 
70     if ((!shape) || (shape->num_outlines < 1))
71         return False;
72     shape->bounds.x1 = shape->bounds.y1 = MAXSHORT;
73     shape->bounds.x2 = shape->bounds.y2 = MINSHORT;
74     for (outline = shape->outlines, o = 0; o < shape->num_outlines;
75          o++, outline++) {
76         for (pt = outline->points, p = 0; p < outline->num_points; p++, pt++) {
77             _XkbCheckBounds(&shape->bounds, pt->x, pt->y);
78         }
79         if (outline->num_points < 2) {
80             _XkbCheckBounds(&shape->bounds, 0, 0);
81         }
82     }
83     return True;
84 }
85 
86 Bool
XkbComputeShapeTop(XkbShapePtr shape,XkbBoundsPtr bounds)87 XkbComputeShapeTop(XkbShapePtr shape, XkbBoundsPtr bounds)
88 {
89     register int p;
90     XkbOutlinePtr outline;
91     XkbPointPtr pt;
92 
93     if ((!shape) || (shape->num_outlines < 1))
94         return False;
95     if (shape->approx)
96         outline = shape->approx;
97     else
98         outline = &shape->outlines[shape->num_outlines - 1];
99     if (outline->num_points < 2) {
100         bounds->x1 = bounds->y1 = 0;
101         bounds->x2 = bounds->y2 = 0;
102     }
103     else {
104         bounds->x1 = bounds->y1 = MAXSHORT;
105         bounds->x2 = bounds->y2 = MINSHORT;
106     }
107     for (pt = outline->points, p = 0; p < outline->num_points; p++, pt++) {
108         _XkbCheckBounds(bounds, pt->x, pt->y);
109     }
110     return True;
111 }
112 
113 Bool
XkbComputeRowBounds(XkbGeometryPtr geom,XkbSectionPtr section,XkbRowPtr row)114 XkbComputeRowBounds(XkbGeometryPtr geom, XkbSectionPtr section, XkbRowPtr row)
115 {
116     register int k, pos;
117     XkbKeyPtr key;
118     XkbBoundsPtr bounds, sbounds;
119 
120     if ((!geom) || (!section) || (!row))
121         return False;
122     bounds = &row->bounds;
123     bzero(bounds, sizeof(XkbBoundsRec));
124     for (key = row->keys, pos = k = 0; k < row->num_keys; k++, key++) {
125         sbounds = &XkbKeyShape(geom, key)->bounds;
126         _XkbCheckBounds(bounds, pos, 0);
127         if (!row->vertical) {
128             if (key->gap != 0) {
129                 pos += key->gap;
130                 _XkbCheckBounds(bounds, pos, 0);
131             }
132             _XkbCheckBounds(bounds, pos + sbounds->x1, sbounds->y1);
133             _XkbCheckBounds(bounds, pos + sbounds->x2, sbounds->y2);
134             pos += sbounds->x2;
135         }
136         else {
137             if (key->gap != 0) {
138                 pos += key->gap;
139                 _XkbCheckBounds(bounds, 0, pos);
140             }
141             _XkbCheckBounds(bounds, pos + sbounds->x1, sbounds->y1);
142             _XkbCheckBounds(bounds, pos + sbounds->x2, sbounds->y2);
143             pos += sbounds->y2;
144         }
145     }
146     return True;
147 }
148 
149 Bool
XkbComputeSectionBounds(XkbGeometryPtr geom,XkbSectionPtr section)150 XkbComputeSectionBounds(XkbGeometryPtr geom, XkbSectionPtr section)
151 {
152     register int i;
153     XkbShapePtr shape;
154     XkbRowPtr row;
155     XkbDoodadPtr doodad;
156     XkbBoundsPtr bounds, rbounds;
157 
158     if ((!geom) || (!section))
159         return False;
160     bounds = &section->bounds;
161     bzero(bounds, sizeof(XkbBoundsRec));
162     for (i = 0, row = section->rows; i < section->num_rows; i++, row++) {
163         if (!XkbComputeRowBounds(geom, section, row))
164             return False;
165         rbounds = &row->bounds;
166         _XkbCheckBounds(bounds, row->left + rbounds->x1,
167                         row->top + rbounds->y1);
168         _XkbCheckBounds(bounds, row->left + rbounds->x2,
169                         row->top + rbounds->y2);
170     }
171     for (i = 0, doodad = section->doodads; i < section->num_doodads;
172          i++, doodad++) {
173         static XkbBoundsRec tbounds;
174 
175         switch (doodad->any.type) {
176         case XkbOutlineDoodad:
177         case XkbSolidDoodad:
178             shape = XkbShapeDoodadShape(geom, &doodad->shape);
179             rbounds = &shape->bounds;
180             break;
181         case XkbTextDoodad:
182             tbounds.x1 = doodad->text.left;
183             tbounds.y1 = doodad->text.top;
184             tbounds.x2 = tbounds.x1 + doodad->text.width;
185             tbounds.y2 = tbounds.y1 + doodad->text.height;
186             rbounds = &tbounds;
187             break;
188         case XkbIndicatorDoodad:
189             shape = XkbIndicatorDoodadShape(geom, &doodad->indicator);
190             rbounds = &shape->bounds;
191             break;
192         case XkbLogoDoodad:
193             shape = XkbLogoDoodadShape(geom, &doodad->logo);
194             rbounds = &shape->bounds;
195             break;
196         default:
197             tbounds.x1 = tbounds.x2 = doodad->any.left;
198             tbounds.y1 = tbounds.y2 = doodad->any.top;
199             rbounds = &tbounds;
200             break;
201         }
202         _XkbCheckBounds(bounds, rbounds->x1, rbounds->y1);
203         _XkbCheckBounds(bounds, rbounds->x2, rbounds->y2);
204     }
205     return True;
206 }
207 
208 /***====================================================================***/
209 
210 char *
XkbFindOverlayForKey(XkbGeometryPtr geom,XkbSectionPtr wanted,char * under)211 XkbFindOverlayForKey(XkbGeometryPtr geom, XkbSectionPtr wanted, char *under)
212 {
213     int s;
214     XkbSectionPtr section;
215 
216     if ((geom == NULL) || (under == NULL) || (geom->num_sections < 1))
217         return NULL;
218 
219     if (wanted)
220         section = wanted;
221     else
222         section = geom->sections;
223 
224     for (s = 0; s < geom->num_sections; s++, section++) {
225         XkbOverlayPtr ol;
226         int o;
227 
228         if (section->num_overlays < 1)
229             continue;
230         for (o = 0, ol = section->overlays; o < section->num_overlays;
231              o++, ol++) {
232             XkbOverlayRowPtr row;
233             int r;
234 
235             for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
236                 XkbOverlayKeyPtr key;
237                 int k;
238 
239                 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
240                     if (strncmp(under, key->under.name, XkbKeyNameLength) == 0)
241                         return key->over.name;
242                 }
243             }
244         }
245         if (wanted != NULL)
246             break;
247     }
248     return NULL;
249 }
250 
251 /***====================================================================***/
252 
253 static Status
_XkbReadGeomProperties(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)254 _XkbReadGeomProperties(XkbReadBufferPtr buf,
255                        XkbGeometryPtr geom,
256                        xkbGetGeometryReply *rep)
257 {
258     Status rtrn;
259 
260     if (rep->nProperties < 1)
261         return Success;
262     if ((rtrn = XkbAllocGeomProps(geom, rep->nProperties)) == Success) {
263         register int i;
264         register Bool ok = True;
265 
266         for (i = 0; (i < rep->nProperties) && ok; i++) {
267             char *name = NULL;
268             char *value = NULL;
269             ok = _XkbGetReadBufferCountedString(buf, &name) && ok;
270             ok = _XkbGetReadBufferCountedString(buf, &value) && ok;
271             ok = ok && (XkbAddGeomProperty(geom, name, value) != NULL);
272 
273 	    _XkbFree(name);
274 	    _XkbFree(value);
275         }
276         if (ok)
277             rtrn = Success;
278         else
279             rtrn = BadLength;
280     }
281     return rtrn;
282 }
283 
284 static Status
_XkbReadGeomKeyAliases(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)285 _XkbReadGeomKeyAliases(XkbReadBufferPtr buf,
286                        XkbGeometryPtr geom,
287                        xkbGetGeometryReply *rep)
288 {
289     Status rtrn;
290 
291     if (rep->nKeyAliases < 1)
292         return Success;
293     if ((rtrn = XkbAllocGeomKeyAliases(geom, rep->nKeyAliases)) == Success) {
294         if (!_XkbCopyFromReadBuffer(buf, (char *) geom->key_aliases,
295                                     (rep->nKeyAliases * XkbKeyNameLength * 2)))
296             return BadLength;
297         geom->num_key_aliases = rep->nKeyAliases;
298         return Success;
299     }
300     else {                      /* alloc failed, just skip the aliases */
301         _XkbSkipReadBufferData(buf, (rep->nKeyAliases * XkbKeyNameLength * 2));
302     }
303     return rtrn;
304 }
305 
306 static Status
_XkbReadGeomColors(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)307 _XkbReadGeomColors(XkbReadBufferPtr buf,
308                    XkbGeometryPtr geom,
309                    xkbGetGeometryReply *rep)
310 {
311     Status rtrn;
312 
313     if (rep->nColors < 1)
314         return Success;
315     if ((rtrn = XkbAllocGeomColors(geom, rep->nColors)) == Success) {
316         register int i;
317 
318         for (i = 0; i < rep->nColors; i++) {
319             char *spec = NULL;
320             if (!_XkbGetReadBufferCountedString(buf, &spec))
321                 rtrn = BadLength;
322             else if (XkbAddGeomColor(geom, spec, geom->num_colors) == NULL)
323                 rtrn = BadAlloc;
324 
325             _XkbFree(spec);
326             if (rtrn != Success)
327                 return rtrn;
328         }
329         return Success;
330     }
331     return rtrn;
332 }
333 
334 static Status
_XkbReadGeomShapes(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)335 _XkbReadGeomShapes(XkbReadBufferPtr buf,
336                    XkbGeometryPtr geom,
337                    xkbGetGeometryReply *rep)
338 {
339     register int i;
340     Status rtrn;
341 
342     if (rep->nShapes < 1)
343         return Success;
344     if ((rtrn = XkbAllocGeomShapes(geom, rep->nShapes)) != Success)
345         return rtrn;
346     for (i = 0; i < rep->nShapes; i++) {
347         xkbShapeWireDesc *shapeWire;
348         XkbShapePtr shape;
349         register int o;
350 
351         shapeWire = (xkbShapeWireDesc *)
352             _XkbGetReadBufferPtr(buf, SIZEOF(xkbShapeWireDesc));
353         if (!shapeWire)
354             return BadLength;
355         shape = XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
356         if (!shape)
357             return BadAlloc;
358         for (o = 0; o < shapeWire->nOutlines; o++) {
359             xkbOutlineWireDesc *olWire;
360             XkbOutlinePtr ol;
361             register int p;
362             XkbPointPtr pt;
363 
364             olWire = (xkbOutlineWireDesc *)
365                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbOutlineWireDesc));
366             if (!olWire)
367                 return BadLength;
368             ol = XkbAddGeomOutline(shape, olWire->nPoints);
369             if (!ol)
370                 return BadAlloc;
371             ol->corner_radius = olWire->cornerRadius;
372             for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
373                 xkbPointWireDesc *ptWire;
374 
375                 ptWire = (xkbPointWireDesc *)
376                     _XkbGetReadBufferPtr(buf, SIZEOF(xkbPointWireDesc));
377                 if (!ptWire)
378                     return BadLength;
379                 pt->x = ptWire->x;
380                 pt->y = ptWire->y;
381             }
382             ol->num_points = olWire->nPoints;
383         }
384         if ((shapeWire->primaryNdx != XkbNoShape) &&
385             (shapeWire->primaryNdx < shapeWire->nOutlines))
386             shape->primary = &shape->outlines[shapeWire->primaryNdx];
387         else
388             shape->primary = NULL;
389         if ((shapeWire->approxNdx != XkbNoShape) &&
390             (shapeWire->approxNdx < shapeWire->nOutlines))
391             shape->approx = &shape->outlines[shapeWire->approxNdx];
392         else
393             shape->approx = NULL;
394         XkbComputeShapeBounds(shape);
395     }
396     return Success;
397 }
398 
399 static Status
_XkbReadGeomDoodad(XkbReadBufferPtr buf,XkbGeometryPtr geom,XkbSectionPtr section)400 _XkbReadGeomDoodad(XkbReadBufferPtr buf,
401                    XkbGeometryPtr geom,
402                    XkbSectionPtr section)
403 {
404     XkbDoodadPtr doodad;
405     xkbDoodadWireDesc *doodadWire;
406 
407     doodadWire = (xkbDoodadWireDesc *)
408         _XkbGetReadBufferPtr(buf, SIZEOF(xkbDoodadWireDesc));
409     if (!doodadWire)
410         return BadLength;
411     doodad = XkbAddGeomDoodad(geom, section, doodadWire->any.name);
412     if (!doodad)
413         return BadAlloc;
414     doodad->any.type = doodadWire->any.type;
415     doodad->any.priority = doodadWire->any.priority;
416     doodad->any.top = doodadWire->any.top;
417     doodad->any.left = doodadWire->any.left;
418     doodad->any.angle = doodadWire->any.angle;
419     switch (doodad->any.type) {
420     case XkbOutlineDoodad:
421     case XkbSolidDoodad:
422         doodad->shape.color_ndx = doodadWire->shape.colorNdx;
423         doodad->shape.shape_ndx = doodadWire->shape.shapeNdx;
424         break;
425     case XkbTextDoodad:
426         doodad->text.width = doodadWire->text.width;
427         doodad->text.height = doodadWire->text.height;
428         doodad->text.color_ndx = doodadWire->text.colorNdx;
429         if (!_XkbGetReadBufferCountedString(buf, &doodad->text.text))
430             return BadLength;
431         if (!_XkbGetReadBufferCountedString(buf, &doodad->text.font))
432             return BadLength;
433         break;
434     case XkbIndicatorDoodad:
435         doodad->indicator.shape_ndx = doodadWire->indicator.shapeNdx;
436         doodad->indicator.on_color_ndx = doodadWire->indicator.onColorNdx;
437         doodad->indicator.off_color_ndx = doodadWire->indicator.offColorNdx;
438         break;
439     case XkbLogoDoodad:
440         doodad->logo.color_ndx = doodadWire->logo.colorNdx;
441         doodad->logo.shape_ndx = doodadWire->logo.shapeNdx;
442         if (!_XkbGetReadBufferCountedString(buf, &doodad->logo.logo_name))
443             return BadLength;
444         break;
445     default:
446         return BadValue;
447     }
448     return Success;
449 }
450 
451 static Status
_XkbReadGeomOverlay(XkbReadBufferPtr buf,XkbGeometryPtr geom,XkbSectionPtr section)452 _XkbReadGeomOverlay(XkbReadBufferPtr buf,
453                     XkbGeometryPtr geom,
454                     XkbSectionPtr section)
455 {
456     XkbOverlayPtr ol;
457     xkbOverlayWireDesc *olWire;
458     register int r;
459 
460     olWire = (xkbOverlayWireDesc *)
461         _XkbGetReadBufferPtr(buf, SIZEOF(xkbOverlayWireDesc));
462     if (olWire == NULL)
463         return BadLength;
464     ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
465     if (ol == NULL)
466         return BadLength;
467     for (r = 0; r < olWire->nRows; r++) {
468         register int k;
469         XkbOverlayRowPtr row;
470         xkbOverlayRowWireDesc *rowWire;
471         xkbOverlayKeyWireDesc *keyWire;
472 
473         rowWire = (xkbOverlayRowWireDesc *)
474             _XkbGetReadBufferPtr(buf, SIZEOF(xkbOverlayRowWireDesc));
475         if (rowWire == NULL)
476             return BadLength;
477         row = XkbAddGeomOverlayRow(ol, rowWire->rowUnder, rowWire->nKeys);
478         if (!row)
479             return BadAlloc;
480         row->row_under = rowWire->rowUnder;
481         if (rowWire->nKeys < 1)
482             continue;
483         keyWire = (xkbOverlayKeyWireDesc *)
484             _XkbGetReadBufferPtr(buf,
485                              SIZEOF(xkbOverlayKeyWireDesc) * rowWire->nKeys);
486         if (keyWire == NULL)
487             return BadLength;
488         for (k = 0; k < rowWire->nKeys; k++, keyWire++, row->num_keys++) {
489             memcpy(row->keys[row->num_keys].over.name, keyWire->over,
490                    XkbKeyNameLength);
491             memcpy(row->keys[row->num_keys].under.name, keyWire->under,
492                    XkbKeyNameLength);
493         }
494     }
495     return Success;
496 }
497 
498 static Status
_XkbReadGeomSections(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)499 _XkbReadGeomSections(XkbReadBufferPtr buf,
500                      XkbGeometryPtr geom,
501                      xkbGetGeometryReply *rep)
502 {
503     register int s;
504     XkbSectionPtr section;
505     xkbSectionWireDesc *sectionWire;
506     Status rtrn;
507 
508     if (rep->nSections < 1)
509         return Success;
510     if ((rtrn = XkbAllocGeomSections(geom, rep->nSections)) != Success)
511         return rtrn;
512     for (s = 0; s < rep->nSections; s++) {
513         sectionWire = (xkbSectionWireDesc *)
514             _XkbGetReadBufferPtr(buf, SIZEOF(xkbSectionWireDesc));
515         if (!sectionWire)
516             return BadLength;
517         section = XkbAddGeomSection(geom, sectionWire->name, sectionWire->nRows,
518                                     sectionWire->nDoodads,
519                                     sectionWire->nOverlays);
520         if (!section)
521             return BadAlloc;
522         section->top = sectionWire->top;
523         section->left = sectionWire->left;
524         section->width = sectionWire->width;
525         section->height = sectionWire->height;
526         section->angle = sectionWire->angle;
527         section->priority = sectionWire->priority;
528         if (sectionWire->nRows > 0) {
529             register int r;
530 
531             for (r = 0; r < sectionWire->nRows; r++) {
532                 XkbRowPtr row;
533                 xkbRowWireDesc *rowWire;
534 
535                 rowWire = (xkbRowWireDesc *)
536                     _XkbGetReadBufferPtr(buf, SIZEOF(xkbRowWireDesc));
537                 if (!rowWire)
538                     return BadLength;
539                 row = XkbAddGeomRow(section, rowWire->nKeys);
540                 if (!row)
541                     return BadAlloc;
542                 row->top = rowWire->top;
543                 row->left = rowWire->left;
544                 row->vertical = rowWire->vertical;
545                 if (rowWire->nKeys > 0) {
546                     register int k;
547 
548                     for (k = 0; k < rowWire->nKeys; k++) {
549                         XkbKeyPtr key;
550                         xkbKeyWireDesc *keyWire;
551 
552                         keyWire = (xkbKeyWireDesc *)
553                             _XkbGetReadBufferPtr(buf, SIZEOF(xkbKeyWireDesc));
554                         if (!keyWire)
555                             return BadLength;
556                         key = XkbAddGeomKey(row);
557                         if (!key)
558                             return BadAlloc;
559                         memcpy(key->name.name, keyWire->name, XkbKeyNameLength);
560                         key->gap = keyWire->gap;
561                         key->shape_ndx = keyWire->shapeNdx;
562                         key->color_ndx = keyWire->colorNdx;
563                     }
564                 }
565             }
566         }
567         if (sectionWire->nDoodads > 0) {
568             register int d;
569 
570             for (d = 0; d < sectionWire->nDoodads; d++) {
571                 if ((rtrn = _XkbReadGeomDoodad(buf, geom, section)) != Success)
572                     return rtrn;
573             }
574         }
575         if (sectionWire->nOverlays > 0) {
576             register int o;
577 
578             for (o = 0; o < sectionWire->nOverlays; o++) {
579                 if ((rtrn = _XkbReadGeomOverlay(buf, geom, section)) != Success)
580                     return rtrn;
581             }
582         }
583     }
584     return Success;
585 }
586 
587 static Status
_XkbReadGeomDoodads(XkbReadBufferPtr buf,XkbGeometryPtr geom,xkbGetGeometryReply * rep)588 _XkbReadGeomDoodads(XkbReadBufferPtr buf,
589                     XkbGeometryPtr geom,
590                     xkbGetGeometryReply *rep)
591 {
592     register int d;
593     Status rtrn;
594 
595     if (rep->nDoodads < 1)
596         return Success;
597     if ((rtrn = XkbAllocGeomDoodads(geom, rep->nDoodads)) != Success)
598         return rtrn;
599     for (d = 0; d < rep->nDoodads; d++) {
600         if ((rtrn = _XkbReadGeomDoodad(buf, geom, NULL)) != Success)
601             return rtrn;
602     }
603     return Success;
604 }
605 
606 Status
_XkbReadGetGeometryReply(Display * dpy,xkbGetGeometryReply * rep,XkbDescPtr xkb,int * nread_rtrn)607 _XkbReadGetGeometryReply(Display *dpy,
608                          xkbGetGeometryReply *rep,
609                          XkbDescPtr xkb,
610                          int *nread_rtrn)
611 {
612     XkbGeometryPtr geom;
613 
614     geom = _XkbTypedCalloc(1, XkbGeometryRec);
615     if (!geom)
616         return BadAlloc;
617     if (xkb->geom)
618         XkbFreeGeometry(xkb->geom, XkbGeomAllMask, True);
619     xkb->geom = geom;
620 
621     geom->name = rep->name;
622     geom->width_mm = rep->widthMM;
623     geom->height_mm = rep->heightMM;
624     if (rep->length) {
625         XkbReadBufferRec buf;
626         int left;
627 
628         if (_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4)) {
629             Status status = Success;
630 
631             if (nread_rtrn)
632                 *nread_rtrn = (int) rep->length * 4;
633             if (!_XkbGetReadBufferCountedString(&buf, &geom->label_font))
634                 status = BadLength;
635             if (status == Success)
636                 status = _XkbReadGeomProperties(&buf, geom, rep);
637             if (status == Success)
638                 status = _XkbReadGeomColors(&buf, geom, rep);
639             if (status == Success)
640                 status = _XkbReadGeomShapes(&buf, geom, rep);
641             if (status == Success)
642                 status = _XkbReadGeomSections(&buf, geom, rep);
643             if (status == Success)
644                 status = _XkbReadGeomDoodads(&buf, geom, rep);
645             if (status == Success)
646                 status = _XkbReadGeomKeyAliases(&buf, geom, rep);
647             left = _XkbFreeReadBuffer(&buf);
648             if ((rep->baseColorNdx > geom->num_colors) ||
649                 (rep->labelColorNdx > geom->num_colors))
650                 status = BadLength;
651             if ((status != Success) || left || buf.error) {
652                 if (status == Success)
653                     status = BadLength;
654                 XkbFreeGeometry(geom, XkbGeomAllMask, True);
655                 xkb->geom = NULL;
656                 return status;
657             }
658             geom->base_color = &geom->colors[rep->baseColorNdx];
659             geom->label_color = &geom->colors[rep->labelColorNdx];
660         }
661         else {
662             XkbFreeGeometry(geom, XkbGeomAllMask, True);
663             xkb->geom = NULL;
664             return BadAlloc;
665         }
666     }
667     return Success;
668 }
669 
670 Status
XkbGetGeometry(Display * dpy,XkbDescPtr xkb)671 XkbGetGeometry(Display *dpy, XkbDescPtr xkb)
672 {
673     xkbGetGeometryReq *req;
674     xkbGetGeometryReply rep;
675     Status status;
676 
677     if ((!xkb) || (dpy->flags & XlibDisplayNoXkb) ||
678         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
679         return BadAccess;
680 
681     LockDisplay(dpy);
682     GetReq(kbGetGeometry, req);
683     req->reqType = dpy->xkb_info->codes->major_opcode;
684     req->xkbReqType = X_kbGetGeometry;
685     req->deviceSpec = xkb->device_spec;
686     req->name = None;
687     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse))
688         status = BadImplementation;
689     else if (!rep.found)
690         status = BadName;
691     else
692         status = _XkbReadGetGeometryReply(dpy, &rep, xkb, NULL);
693     UnlockDisplay(dpy);
694     SyncHandle();
695     return status;
696 }
697 
698 Status
XkbGetNamedGeometry(Display * dpy,XkbDescPtr xkb,Atom name)699 XkbGetNamedGeometry(Display *dpy, XkbDescPtr xkb, Atom name)
700 {
701     xkbGetGeometryReq *req;
702     xkbGetGeometryReply rep;
703     Status status;
704 
705     if ((name == None) || (dpy->flags & XlibDisplayNoXkb) ||
706         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
707         return BadAccess;
708 
709     LockDisplay(dpy);
710     GetReq(kbGetGeometry, req);
711     req->reqType = dpy->xkb_info->codes->major_opcode;
712     req->xkbReqType = X_kbGetGeometry;
713     req->deviceSpec = xkb->device_spec;
714     req->name = (CARD32) name;
715     if ((!_XReply(dpy, (xReply *) &rep, 0, xFalse)) || (!rep.found))
716         status = BadImplementation;
717     else if (!rep.found)
718         status = BadName;
719     else
720         status = _XkbReadGetGeometryReply(dpy, &rep, xkb, NULL);
721     UnlockDisplay(dpy);
722     SyncHandle();
723     return status;
724 }
725