1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE 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#include "Xlibint.h" 35#include "XKBlibint.h" 36#include "X11/extensions/XKBgeom.h" 37#include <X11/extensions/XKBproto.h> 38 39#ifndef MINSHORT 40#define MINSHORT -32768 41#endif 42#ifndef MAXSHORT 43#define MAXSHORT 32767 44#endif 45 46/***====================================================================***/ 47 48#define _SizeCountedString(s) ((s)?XkbPaddedSize(2+strlen(s)):4) 49 50static char * 51_WriteCountedString(char *wire, char *str) 52{ 53 CARD16 len, *pLen; 54 55 len = (CARD16) (str ? strlen(str) : 0); 56 pLen = (CARD16 *) wire; 57 *pLen = len; 58 if (len && str) 59 memcpy(&wire[2], str, len); 60 wire += XkbPaddedSize(len + 2); 61 return wire; 62} 63 64static int 65_SizeGeomProperties(XkbGeometryPtr geom) 66{ 67 register int i, size; 68 XkbPropertyPtr prop; 69 70 for (size = i = 0, prop = geom->properties; i < geom->num_properties; 71 i++, prop++) { 72 size = (int) ((unsigned) size + _SizeCountedString(prop->name)); 73 size = (int) ((unsigned) size + _SizeCountedString(prop->value)); 74 } 75 return size; 76} 77 78static int 79_SizeGeomColors(XkbGeometryPtr geom) 80{ 81 register int i, size; 82 register XkbColorPtr color; 83 84 for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 85 size = (int) ((unsigned) size + _SizeCountedString(color->spec)); 86 } 87 return size; 88} 89 90static int 91_SizeGeomShapes(XkbGeometryPtr geom) 92{ 93 register int i, size; 94 register XkbShapePtr shape; 95 96 for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 97 register int n; 98 register XkbOutlinePtr ol; 99 100 size += SIZEOF(xkbShapeWireDesc); 101 for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) { 102 size += SIZEOF(xkbOutlineWireDesc); 103 size += ol->num_points * SIZEOF(xkbPointWireDesc); 104 } 105 } 106 return size; 107} 108 109static int 110_SizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad) 111{ 112 register int i, size; 113 114 for (i = size = 0; i < num_doodads; i++, doodad++) { 115 size += SIZEOF(xkbAnyDoodadWireDesc); 116 if (doodad->any.type == XkbTextDoodad) { 117 size = (int) ((unsigned) size + _SizeCountedString(doodad->text.text)); 118 size = (int) ((unsigned) size + _SizeCountedString(doodad->text.font)); 119 } 120 else if (doodad->any.type == XkbLogoDoodad) { 121 size = (int) ((unsigned) size + _SizeCountedString(doodad->logo.logo_name)); 122 } 123 } 124 return size; 125} 126 127static int 128_SizeGeomSections(XkbGeometryPtr geom) 129{ 130 register int i, size; 131 XkbSectionPtr section; 132 133 for (i = size = 0, section = geom->sections; i < geom->num_sections; 134 i++, section++) { 135 size += SIZEOF(xkbSectionWireDesc); 136 if (section->rows) { 137 int r; 138 XkbRowPtr row; 139 140 for (r = 0, row = section->rows; r < section->num_rows; row++, r++) { 141 size += SIZEOF(xkbRowWireDesc); 142 size += row->num_keys * SIZEOF(xkbKeyWireDesc); 143 } 144 } 145 if (section->doodads) 146 size += _SizeGeomDoodads(section->num_doodads, section->doodads); 147 if (section->overlays) { 148 int o; 149 XkbOverlayPtr ol; 150 151 for (o = 0, ol = section->overlays; o < section->num_overlays; 152 o++, ol++) { 153 int r; 154 XkbOverlayRowPtr row; 155 156 size += SIZEOF(xkbOverlayWireDesc); 157 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 158 size += SIZEOF(xkbOverlayRowWireDesc); 159 size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc); 160 } 161 } 162 } 163 } 164 return size; 165} 166 167static int 168_SizeGeomKeyAliases(XkbGeometryPtr geom) 169{ 170 return geom->num_key_aliases * (2 * XkbKeyNameLength); 171} 172 173/***====================================================================***/ 174 175static char * 176_WriteGeomProperties(char *wire, XkbGeometryPtr geom) 177{ 178 register int i; 179 register XkbPropertyPtr prop; 180 181 for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) { 182 wire = _WriteCountedString(wire, prop->name); 183 wire = _WriteCountedString(wire, prop->value); 184 } 185 return wire; 186} 187 188static char * 189_WriteGeomColors(char *wire, XkbGeometryPtr geom) 190{ 191 register int i; 192 register XkbColorPtr color; 193 194 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 195 wire = _WriteCountedString(wire, color->spec); 196 } 197 return wire; 198} 199 200static char * 201_WriteGeomShapes(char *wire, XkbGeometryPtr geom) 202{ 203 int i; 204 XkbShapePtr shape; 205 xkbShapeWireDesc *shapeWire; 206 207 for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 208 register int o; 209 XkbOutlinePtr ol; 210 xkbOutlineWireDesc *olWire; 211 212 shapeWire = (xkbShapeWireDesc *) wire; 213 shapeWire->name = shape->name; 214 shapeWire->nOutlines = shape->num_outlines; 215 if (shape->primary != NULL) 216 shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary); 217 else 218 shapeWire->primaryNdx = XkbNoShape; 219 if (shape->approx != NULL) 220 shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx); 221 else 222 shapeWire->approxNdx = XkbNoShape; 223 wire = (char *) &shapeWire[1]; 224 for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 225 register int p; 226 XkbPointPtr pt; 227 xkbPointWireDesc *ptWire; 228 229 olWire = (xkbOutlineWireDesc *) wire; 230 olWire->nPoints = ol->num_points; 231 olWire->cornerRadius = ol->corner_radius; 232 wire = (char *) &olWire[1]; 233 ptWire = (xkbPointWireDesc *) wire; 234 for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) { 235 ptWire[p].x = pt->x; 236 ptWire[p].y = pt->y; 237 } 238 wire = (char *) &ptWire[ol->num_points]; 239 } 240 } 241 return wire; 242} 243 244static char * 245_WriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad) 246{ 247 register int i; 248 249 for (i = 0; i < num_doodads; i++, doodad++) { 250 xkbDoodadWireDesc *doodadWire = (xkbDoodadWireDesc *) wire; 251 252 wire = (char *) &doodadWire[1]; 253 bzero(doodadWire, SIZEOF(xkbDoodadWireDesc)); 254 doodadWire->any.name = doodad->any.name; 255 doodadWire->any.type = doodad->any.type; 256 doodadWire->any.priority = doodad->any.priority; 257 doodadWire->any.top = doodad->any.top; 258 doodadWire->any.left = doodad->any.left; 259 doodadWire->any.angle = doodad->any.angle; 260 switch (doodad->any.type) { 261 case XkbOutlineDoodad: 262 case XkbSolidDoodad: 263 doodadWire->shape.colorNdx = doodad->shape.color_ndx; 264 doodadWire->shape.shapeNdx = doodad->shape.shape_ndx; 265 break; 266 case XkbTextDoodad: 267 doodadWire->text.width = doodad->text.width; 268 doodadWire->text.height = doodad->text.height; 269 doodadWire->text.colorNdx = doodad->text.color_ndx; 270 wire = _WriteCountedString(wire, doodad->text.text); 271 wire = _WriteCountedString(wire, doodad->text.font); 272 break; 273 case XkbIndicatorDoodad: 274 doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx; 275 doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx; 276 doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx; 277 break; 278 case XkbLogoDoodad: 279 doodadWire->logo.colorNdx = doodad->logo.color_ndx; 280 doodadWire->logo.shapeNdx = doodad->logo.shape_ndx; 281 wire = _WriteCountedString(wire, doodad->logo.logo_name); 282 break; 283 default: 284 break; 285 } 286 } 287 return wire; 288} 289 290static char * 291_WriteGeomOverlay(char *wire, XkbOverlayPtr ol) 292{ 293 register int r; 294 XkbOverlayRowPtr row; 295 xkbOverlayWireDesc *olWire = (xkbOverlayWireDesc *) wire; 296 297 olWire->name = ol->name; 298 olWire->nRows = ol->num_rows; 299 wire = (char *) &olWire[1]; 300 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 301 unsigned int k; 302 XkbOverlayKeyPtr key; 303 xkbOverlayRowWireDesc *rowWire = (xkbOverlayRowWireDesc *) wire; 304 305 rowWire->rowUnder = row->row_under; 306 rowWire->nKeys = row->num_keys; 307 wire = (char *) &rowWire[1]; 308 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 309 xkbOverlayKeyWireDesc *keyWire = (xkbOverlayKeyWireDesc *) wire; 310 311 memcpy(keyWire->over, key->over.name, XkbKeyNameLength); 312 memcpy(keyWire->under, key->under.name, XkbKeyNameLength); 313 wire = (char *) &keyWire[1]; 314 } 315 } 316 return wire; 317} 318 319static char * 320_WriteGeomSections(char *wire, XkbGeometryPtr geom) 321{ 322 register int i; 323 XkbSectionPtr section; 324 325 for (i = 0, section = geom->sections; i < geom->num_sections; 326 i++, section++) { 327 xkbSectionWireDesc *sectionWire = (xkbSectionWireDesc *) wire; 328 329 sectionWire->name = section->name; 330 sectionWire->top = section->top; 331 sectionWire->left = section->left; 332 sectionWire->width = section->width; 333 sectionWire->height = section->height; 334 sectionWire->angle = section->angle; 335 sectionWire->priority = section->priority; 336 sectionWire->nRows = section->num_rows; 337 sectionWire->nDoodads = section->num_doodads; 338 sectionWire->nOverlays = section->num_overlays; 339 sectionWire->pad = 0; 340 wire = (char *) §ionWire[1]; 341 if (section->rows) { 342 int r; 343 XkbRowPtr row; 344 345 for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 346 xkbRowWireDesc *rowWire = (xkbRowWireDesc *) wire; 347 348 rowWire->top = row->top; 349 rowWire->left = row->left; 350 rowWire->nKeys = row->num_keys; 351 rowWire->vertical = row->vertical; 352 rowWire->pad = 0; 353 wire = (char *) &rowWire[1]; 354 if (row->keys) { 355 int k; 356 XkbKeyPtr key; 357 xkbKeyWireDesc *keyWire = (xkbKeyWireDesc *) wire; 358 359 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 360 memcpy(keyWire[k].name, key->name.name, 361 XkbKeyNameLength); 362 keyWire[k].gap = key->gap; 363 keyWire[k].shapeNdx = key->shape_ndx; 364 keyWire[k].colorNdx = key->color_ndx; 365 } 366 wire = (char *) &keyWire[row->num_keys]; 367 } 368 } 369 } 370 if (section->doodads) { 371 wire = _WriteGeomDoodads(wire, 372 section->num_doodads, section->doodads); 373 } 374 if (section->overlays) { 375 register int o; 376 377 for (o = 0; o < section->num_overlays; o++) { 378 wire = _WriteGeomOverlay(wire, §ion->overlays[o]); 379 } 380 } 381 } 382 return wire; 383} 384 385static char * 386_WriteGeomKeyAliases(char *wire, XkbGeometryPtr geom) 387{ 388 register int sz; 389 390 sz = geom->num_key_aliases * (XkbKeyNameLength * 2); 391 if (sz > 0) { 392 memcpy(wire, (char *) geom->key_aliases, (size_t)sz); 393 wire += sz; 394 } 395 return wire; 396} 397 398/***====================================================================***/ 399 400static Status 401_SendSetGeometry(Display *dpy, XkbGeometryPtr geom, xkbSetGeometryReq *req) 402{ 403 int sz; 404 char *wire, *tbuf; 405 406 sz = 0; 407 sz = (int) ((unsigned) (sz + _SizeCountedString(geom->label_font))); 408 sz += _SizeGeomProperties(geom); 409 sz += _SizeGeomColors(geom); 410 sz += _SizeGeomShapes(geom); 411 sz += _SizeGeomSections(geom); 412 sz += _SizeGeomDoodads(geom->num_doodads, geom->doodads); 413 sz += _SizeGeomKeyAliases(geom); 414 req->length += (sz / 4); 415 if (sz < (dpy->bufmax - dpy->buffer)) { 416 BufAlloc(char *, wire, sz); 417 tbuf = NULL; 418 } 419 else { 420 tbuf = _XAllocTemp(dpy, sz); 421 if (!tbuf) 422 return BadAlloc; 423 wire = tbuf; 424 } 425 wire = _WriteCountedString(wire, geom->label_font); 426 if (geom->num_properties > 0) 427 wire = _WriteGeomProperties(wire, geom); 428 if (geom->num_colors > 0) 429 wire = _WriteGeomColors(wire, geom); 430 if (geom->num_shapes > 0) 431 wire = _WriteGeomShapes(wire, geom); 432 if (geom->num_sections > 0) 433 wire = _WriteGeomSections(wire, geom); 434 if (geom->num_doodads > 0) 435 wire = _WriteGeomDoodads(wire, geom->num_doodads, geom->doodads); 436 if (geom->num_key_aliases > 0) 437 wire = _WriteGeomKeyAliases(wire, geom); 438 if (tbuf != NULL) { 439 Data(dpy, tbuf, sz); 440 _XFreeTemp(dpy, tbuf, sz); 441 } 442 return Success; 443} 444 445/***====================================================================***/ 446 447Status 448XkbSetGeometry(Display *dpy, unsigned deviceSpec, XkbGeometryPtr geom) 449{ 450 xkbSetGeometryReq *req; 451 Status ret; 452 453 if ((!geom) || (dpy->flags & XlibDisplayNoXkb) || 454 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 455 return BadAccess; 456 457 LockDisplay(dpy); 458 GetReq(kbSetGeometry, req); 459 req->reqType = dpy->xkb_info->codes->major_opcode; 460 req->xkbReqType = X_kbSetGeometry; 461 req->deviceSpec = deviceSpec; 462 req->nShapes = geom->num_shapes; 463 req->nSections = geom->num_sections; 464 req->name = geom->name; 465 req->widthMM = geom->width_mm; 466 req->heightMM = geom->height_mm; 467 req->nProperties = geom->num_properties; 468 req->nColors = geom->num_colors; 469 req->nDoodads = geom->num_doodads; 470 req->nKeyAliases = geom->num_key_aliases; 471 req->baseColorNdx = (geom->base_color - geom->colors); 472 req->labelColorNdx = (geom->label_color - geom->colors); 473 474 ret = _SendSetGeometry(dpy, geom, req); 475 UnlockDisplay(dpy); 476 SyncHandle(); 477 return ret; 478} 479