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 HAVE_CONFIG_H 28#include <config.h> 29#endif 30#include <stdio.h> 31#include "Xlibint.h" 32#include <X11/extensions/XKBproto.h> 33#include "XKBlibint.h" 34 35static int 36_XkbSizeKeyTypes(XkbDescPtr xkb, xkbSetMapReq *req) 37{ 38 XkbKeyTypePtr map; 39 int i, len; 40 41 if (((req->present & XkbKeyTypesMask) == 0) || (req->nTypes == 0)) { 42 req->present &= ~XkbKeyTypesMask; 43 req->firstType = req->nTypes = 0; 44 return 0; 45 } 46 len = 0; 47 map = &xkb->map->types[req->firstType]; 48 for (i = 0; i < req->nTypes; i++, map++) { 49 len += SIZEOF(xkbKeyTypeWireDesc); 50 len += map->map_count * SIZEOF(xkbKTSetMapEntryWireDesc); 51 if (map->preserve) 52 len += map->map_count * SIZEOF(xkbModsWireDesc); 53 } 54 return len; 55} 56 57static void 58_XkbWriteKeyTypes(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 59{ 60 char *buf; 61 XkbKeyTypePtr type; 62 int i, n; 63 xkbKeyTypeWireDesc *desc; 64 65 if ((req->present & XkbKeyTypesMask) == 0) 66 return; 67 type = &xkb->map->types[req->firstType]; 68 for (i = 0; i < req->nTypes; i++, type++) { 69 int sz = SIZEOF(xkbKeyTypeWireDesc); 70 sz += type->map_count * SIZEOF(xkbKTSetMapEntryWireDesc); 71 if (type->preserve) 72 sz += type->map_count * SIZEOF(xkbModsWireDesc); 73 BufAlloc(xkbKeyTypeWireDesc *, desc, sz); 74 desc->mask = type->mods.mask; 75 desc->realMods = type->mods.real_mods; 76 desc->virtualMods = type->mods.vmods; 77 desc->numLevels = type->num_levels; 78 desc->nMapEntries = type->map_count; 79 desc->preserve = (type->preserve != NULL); 80 buf = (char *) &desc[1]; 81 if (desc->nMapEntries > 0) { 82 xkbKTSetMapEntryWireDesc *wire = (xkbKTSetMapEntryWireDesc *) buf; 83 84 for (n = 0; n < type->map_count; n++, wire++) { 85 wire->level = type->map[n].level; 86 wire->realMods = type->map[n].mods.real_mods; 87 wire->virtualMods = type->map[n].mods.vmods; 88 } 89 buf = (char *) wire; 90 if (type->preserve) { 91 xkbModsWireDesc *pwire = (xkbModsWireDesc *) buf; 92 93 for (n = 0; n < type->map_count; n++, pwire++) { 94 pwire->realMods = type->preserve[n].real_mods; 95 pwire->virtualMods = type->preserve[n].vmods; 96 } 97 } 98 } 99 } 100 return; 101} 102 103static int 104_XkbSizeKeySyms(XkbDescPtr xkb, xkbSetMapReq *req) 105{ 106 int i, len; 107 unsigned nSyms; 108 109 if (((req->present & XkbKeySymsMask) == 0) || (req->nKeySyms == 0)) { 110 req->present &= ~XkbKeySymsMask; 111 req->firstKeySym = req->nKeySyms = 0; 112 req->totalSyms = 0; 113 return 0; 114 } 115 len = (int) (req->nKeySyms * sizeof(XkbSymMapRec)); 116 for (i = nSyms = 0; i < req->nKeySyms; i++) { 117 nSyms += XkbKeyNumSyms(xkb, i + req->firstKeySym); 118 } 119 len += nSyms * sizeof(CARD32); 120 req->totalSyms = nSyms; 121 return len; 122} 123 124static void 125_XkbWriteKeySyms(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 126{ 127 register KeySym *pSym; 128 CARD32 *outSym; 129 XkbSymMapPtr symMap; 130 xkbSymMapWireDesc *desc; 131 register int i; 132 133 if ((req->present & XkbKeySymsMask) == 0) 134 return; 135 symMap = &xkb->map->key_sym_map[req->firstKeySym]; 136 for (i = 0; i < req->nKeySyms; i++, symMap++) { 137 BufAlloc(xkbSymMapWireDesc *, desc, 138 SIZEOF(xkbSymMapWireDesc) + 139 (XkbKeyNumSyms(xkb, i + req->firstKeySym) * sizeof(CARD32))); 140 desc->ktIndex[0] = symMap->kt_index[0]; 141 desc->ktIndex[1] = symMap->kt_index[1]; 142 desc->ktIndex[2] = symMap->kt_index[2]; 143 desc->ktIndex[3] = symMap->kt_index[3]; 144 desc->groupInfo = symMap->group_info; 145 desc->width = symMap->width; 146 desc->nSyms = XkbKeyNumSyms(xkb, i + req->firstKeySym); 147 outSym = (CARD32 *) &desc[1]; 148 if (desc->nSyms > 0) { 149 pSym = XkbKeySymsPtr(xkb, i + req->firstKeySym); 150 _XkbWriteCopyKeySyms(pSym, outSym, desc->nSyms); 151 } 152 } 153 return; 154} 155 156static int 157_XkbSizeKeyActions(XkbDescPtr xkb, xkbSetMapReq *req) 158{ 159 int i, len, nActs; 160 161 if (((req->present & XkbKeyActionsMask) == 0) || (req->nKeyActs == 0)) { 162 req->present &= ~XkbKeyActionsMask; 163 req->firstKeyAct = req->nKeyActs = 0; 164 req->totalActs = 0; 165 return 0; 166 } 167 for (nActs = i = 0; i < req->nKeyActs; i++) { 168 if (xkb->server->key_acts[i + req->firstKeyAct] != 0) 169 nActs += XkbKeyNumActions(xkb, i + req->firstKeyAct); 170 } 171 len = XkbPaddedSize(req->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc)); 172 req->totalActs = nActs; 173 return len; 174} 175 176static void 177_XkbWriteKeyActions(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 178{ 179 register int i; 180 int n; 181 CARD8 *numDesc; 182 XkbAction *actDesc; 183 184 if ((req->present & XkbKeyActionsMask) == 0) 185 return; 186 n = XkbPaddedSize(req->nKeyActs); 187 n += (req->totalActs * SIZEOF(xkbActionWireDesc)); 188 189 BufAlloc(CARD8 *, numDesc, n); 190 for (i = 0; i < req->nKeyActs; i++) { 191 if (xkb->server->key_acts[i + req->firstKeyAct] == 0) 192 numDesc[i] = 0; 193 else 194 numDesc[i] = XkbKeyNumActions(xkb, (i + req->firstKeyAct)); 195 } 196 actDesc = (XkbAction *) &numDesc[XkbPaddedSize(req->nKeyActs)]; 197 for (i = 0; i < req->nKeyActs; i++) { 198 if (xkb->server->key_acts[i + req->firstKeyAct] != 0) { 199 n = XkbKeyNumActions(xkb, (i + req->firstKeyAct)); 200 memcpy(actDesc, XkbKeyActionsPtr(xkb, (i + req->firstKeyAct)), 201 n * SIZEOF(xkbActionWireDesc)); 202 actDesc += n; 203 } 204 } 205 return; 206} 207 208static int 209_XkbSizeKeyBehaviors(XkbDescPtr xkb, xkbSetMapReq *req) 210{ 211 register int i, first, last, nFound; 212 213 if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) { 214 req->present &= ~XkbKeyBehaviorsMask; 215 req->firstKeyBehavior = req->nKeyBehaviors = 0; 216 req->totalKeyBehaviors = 0; 217 return 0; 218 } 219 first = req->firstKeyBehavior; 220 last = first + req->nKeyBehaviors - 1; 221 for (i = first, nFound = 0; i <= last; i++) { 222 if (xkb->server->behaviors[i].type != XkbKB_Default) 223 nFound++; 224 } 225 req->totalKeyBehaviors = nFound; 226 return (nFound * SIZEOF(xkbBehaviorWireDesc)); 227} 228 229static void 230_XkbWriteKeyBehaviors(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 231{ 232 register int i, first, last; 233 xkbBehaviorWireDesc *wire; 234 char *buf; 235 236 if ((req->present & XkbKeyBehaviorsMask) == 0) 237 return; 238 first = req->firstKeyBehavior; 239 last = first + req->nKeyBehaviors - 1; 240 241 i = req->totalKeyBehaviors * SIZEOF(xkbBehaviorWireDesc); 242 BufAlloc(char *, buf, i); 243 wire = (xkbBehaviorWireDesc *) buf; 244 for (i = first; i <= last; i++) { 245 if (xkb->server->behaviors[i].type != XkbKB_Default) { 246 wire->key = i; 247 wire->type = xkb->server->behaviors[i].type; 248 wire->data = xkb->server->behaviors[i].data; 249 buf += SIZEOF(xkbBehaviorWireDesc); 250 wire = (xkbBehaviorWireDesc *) buf; 251 } 252 } 253 return; 254} 255 256static unsigned 257_XkbSizeVirtualMods(xkbSetMapReq *req) 258{ 259 register int i, bit, nMods; 260 261 if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) { 262 req->present &= ~XkbVirtualModsMask; 263 req->virtualMods = 0; 264 return 0; 265 } 266 for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 267 if (req->virtualMods & bit) 268 nMods++; 269 } 270 return XkbPaddedSize(nMods); 271} 272 273static void 274_XkbWriteVirtualMods(Display *dpy, 275 XkbDescPtr xkb, 276 xkbSetMapReq *req, 277 unsigned size) 278{ 279 register int i, bit; 280 CARD8 *vmods; 281 282 /* This was req->present&XkbVirtualModsMask==0, and '==' beats '&' */ 283 if (((req->present & XkbVirtualModsMask) == 0) || (size < 1)) 284 return; 285 BufAlloc(CARD8 *, vmods, size); 286 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 287 if (req->virtualMods & bit) 288 *vmods++ = xkb->server->vmods[i]; 289 } 290 return; 291} 292 293static int 294_XkbSizeKeyExplicit(XkbDescPtr xkb, xkbSetMapReq *req) 295{ 296 register int i, first, last, nFound; 297 298 if (((req->present & XkbExplicitComponentsMask) == 0) || 299 (req->nKeyExplicit == 0)) { 300 req->present &= ~XkbExplicitComponentsMask; 301 req->firstKeyExplicit = req->nKeyExplicit = 0; 302 req->totalKeyExplicit = 0; 303 return 0; 304 } 305 first = req->firstKeyExplicit; 306 last = first + req->nKeyExplicit - 1; 307 308 for (i = first, nFound = 0; i <= last; i++) { 309 if (xkb->server->explicit[i] != 0) 310 nFound++; 311 } 312 req->totalKeyExplicit = nFound; 313 return XkbPaddedSize((nFound * 2)); 314} 315 316static void 317_XkbWriteKeyExplicit(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 318{ 319 register int i, first, last; 320 CARD8 *wire; 321 322 if ((req->present & XkbExplicitComponentsMask) == 0) 323 return; 324 first = req->firstKeyExplicit; 325 last = first + req->nKeyExplicit - 1; 326 i = XkbPaddedSize((req->totalKeyExplicit * 2)); 327 BufAlloc(CARD8 *, wire, i); 328 for (i = first; i <= last; i++) { 329 if (xkb->server->explicit[i] != 0) { 330 wire[0] = i; 331 wire[1] = xkb->server->explicit[i]; 332 wire += 2; 333 } 334 } 335 return; 336} 337 338static int 339_XkbSizeModifierMap(XkbDescPtr xkb, xkbSetMapReq *req) 340{ 341 register int i, first, last, nFound; 342 343 if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys == 0)) { 344 req->present &= ~XkbModifierMapMask; 345 req->firstModMapKey = req->nModMapKeys = 0; 346 req->totalModMapKeys = 0; 347 return 0; 348 } 349 first = req->firstModMapKey; 350 last = first + req->nModMapKeys - 1; 351 352 for (i = first, nFound = 0; i <= last; i++) { 353 if (xkb->map->modmap[i] != 0) 354 nFound++; 355 } 356 req->totalModMapKeys = nFound; 357 return XkbPaddedSize((nFound * 2)); 358} 359 360static void 361_XkbWriteModifierMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 362{ 363 register int i, first, last; 364 CARD8 *wire; 365 366 if ((req->present & XkbModifierMapMask) == 0) 367 return; 368 first = req->firstModMapKey; 369 last = first + req->nModMapKeys - 1; 370 if (req->totalModMapKeys > 0) { 371 i = XkbPaddedSize((req->totalModMapKeys * 2)); 372 BufAlloc(CARD8 *, wire, i); 373 374 for (i = first; i <= last; i++) { 375 if (xkb->map->modmap[i] != 0) { 376 wire[0] = i; 377 wire[1] = xkb->map->modmap[i]; 378 wire += 2; 379 } 380 } 381 } 382 return; 383} 384 385static int 386_XkbSizeVirtualModMap(XkbDescPtr xkb, xkbSetMapReq *req) 387{ 388 register int i, first, last, nFound; 389 390 if (((req->present & XkbVirtualModMapMask) == 0) || 391 (req->nVModMapKeys == 0)) { 392 req->present &= ~XkbVirtualModMapMask; 393 req->firstVModMapKey = req->nVModMapKeys = 0; 394 req->totalVModMapKeys = 0; 395 return 0; 396 } 397 first = req->firstVModMapKey; 398 last = first + req->nVModMapKeys - 1; 399 400 for (i = first, nFound = 0; i <= last; i++) { 401 if (xkb->server->vmodmap[i] != 0) 402 nFound++; 403 } 404 req->totalVModMapKeys = nFound; 405 return nFound * SIZEOF(xkbVModMapWireDesc); 406} 407 408static void 409_XkbWriteVirtualModMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 410{ 411 register int i, first, last; 412 xkbVModMapWireDesc *wire; 413 414 if ((req->present & XkbVirtualModMapMask) == 0) 415 return; 416 first = req->firstVModMapKey; 417 last = first + req->nVModMapKeys - 1; 418 if (req->totalVModMapKeys > 0) { 419 i = req->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc); 420 BufAlloc(xkbVModMapWireDesc *, wire, i); 421 for (i = first; i <= last; i++) { 422 if (xkb->server->vmodmap[i] != 0) { 423 wire->key = i; 424 wire->vmods = xkb->server->vmodmap[i]; 425 wire++; 426 } 427 } 428 } 429 return; 430} 431 432static void 433SendSetMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req) 434{ 435 xkbSetMapReq tmp; 436 unsigned szMods; 437 438 req->length += _XkbSizeKeyTypes(xkb, req) / 4; 439 req->length += _XkbSizeKeySyms(xkb, req) / 4; 440 req->length += _XkbSizeKeyActions(xkb, req) / 4; 441 req->length += _XkbSizeKeyBehaviors(xkb, req) / 4; 442 szMods = _XkbSizeVirtualMods(req); 443 req->length += szMods / 4; 444 req->length += _XkbSizeKeyExplicit(xkb, req) / 4; 445 req->length += _XkbSizeModifierMap(xkb, req) / 4; 446 req->length += _XkbSizeVirtualModMap(xkb, req) / 4; 447 448 tmp = *req; 449 if (tmp.nTypes > 0) 450 _XkbWriteKeyTypes(dpy, xkb, &tmp); 451 if (tmp.nKeySyms > 0) 452 _XkbWriteKeySyms(dpy, xkb, &tmp); 453 if (tmp.nKeyActs) 454 _XkbWriteKeyActions(dpy, xkb, &tmp); 455 if (tmp.totalKeyBehaviors > 0) 456 _XkbWriteKeyBehaviors(dpy, xkb, &tmp); 457 if (tmp.virtualMods) 458 _XkbWriteVirtualMods(dpy, xkb, &tmp, szMods); 459 if (tmp.totalKeyExplicit > 0) 460 _XkbWriteKeyExplicit(dpy, xkb, &tmp); 461 if (tmp.totalModMapKeys > 0) 462 _XkbWriteModifierMap(dpy, xkb, &tmp); 463 if (tmp.totalVModMapKeys > 0) 464 _XkbWriteVirtualModMap(dpy, xkb, &tmp); 465 return; 466} 467 468Bool 469XkbSetMap(Display *dpy, unsigned which, XkbDescPtr xkb) 470{ 471 register xkbSetMapReq *req; 472 XkbInfoPtr xkbi; 473 XkbServerMapPtr srv; 474 XkbClientMapPtr map; 475 476 if ((dpy->flags & XlibDisplayNoXkb) || 477 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) || (!xkb)) 478 return False; 479 map = xkb->map; 480 srv = xkb->server; 481 482 if (((which & XkbKeyTypesMask) && ((!map) || (!map->types))) || 483 ((which & XkbKeySymsMask) && 484 ((!map) || (!map->syms) || (!map->key_sym_map))) || 485 ((which & XkbKeyActionsMask) && ((!srv) || (!srv->key_acts))) || 486 ((which & XkbKeyBehaviorsMask) && ((!srv) || (!srv->behaviors))) || 487 ((which & XkbVirtualModsMask) && (!srv)) || 488 ((which & XkbExplicitComponentsMask) && ((!srv) || (!srv->explicit))) || 489 ((which & XkbModifierMapMask) && ((!map) || (!map->modmap))) || 490 ((which & XkbVirtualModMapMask) && ((!srv) || (!srv->vmodmap)))) 491 return False; 492 493 LockDisplay(dpy); 494 xkbi = dpy->xkb_info; 495 GetReq(kbSetMap, req); 496 req->reqType = xkbi->codes->major_opcode; 497 req->xkbReqType = X_kbSetMap; 498 req->deviceSpec = xkb->device_spec; 499 req->present = which; 500 req->flags = XkbSetMapAllFlags; 501 req->minKeyCode = xkb->min_key_code; 502 req->maxKeyCode = xkb->max_key_code; 503 req->firstType = 0; 504 if (which & XkbKeyTypesMask) 505 req->nTypes = map->num_types; 506 else 507 req->nTypes = 0; 508 if (which & XkbKeySymsMask) { 509 req->firstKeySym = xkb->min_key_code; 510 req->nKeySyms = XkbNumKeys(xkb); 511 } 512 if (which & XkbKeyActionsMask) { 513 req->firstKeyAct = xkb->min_key_code; 514 req->nKeyActs = XkbNumKeys(xkb); 515 } 516 if (which & XkbKeyBehaviorsMask) { 517 req->firstKeyBehavior = xkb->min_key_code; 518 req->nKeyBehaviors = XkbNumKeys(xkb); 519 } 520 if (which & XkbVirtualModsMask) 521 req->virtualMods = ~0; 522 if (which & XkbExplicitComponentsMask) { 523 req->firstKeyExplicit = xkb->min_key_code; 524 req->nKeyExplicit = XkbNumKeys(xkb); 525 } 526 if (which & XkbModifierMapMask) { 527 req->firstModMapKey = xkb->min_key_code; 528 req->nModMapKeys = XkbNumKeys(xkb); 529 } 530 if (which & XkbVirtualModMapMask) { 531 req->firstVModMapKey = xkb->min_key_code; 532 req->nVModMapKeys = XkbNumKeys(xkb); 533 } 534 SendSetMap(dpy, xkb, req); 535 UnlockDisplay(dpy); 536 SyncHandle(); 537 return True; 538} 539 540Bool 541XkbChangeMap(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes) 542{ 543 register xkbSetMapReq *req; 544 XkbInfoPtr xkbi; 545 XkbServerMapPtr srv; 546 XkbClientMapPtr map; 547 548 if ((dpy->flags & XlibDisplayNoXkb) || 549 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) || 550 (!xkb) || (!changes)) 551 return False; 552 srv = xkb->server; 553 map = xkb->map; 554 555 if (((changes->changed & XkbKeyTypesMask) && ((!map) || (!map->types))) || 556 ((changes->changed & XkbKeySymsMask) && ((!map) || (!map->syms) || 557 (!map->key_sym_map))) || 558 ((changes->changed & XkbKeyActionsMask) && ((!srv) || (!srv->key_acts))) 559 || ((changes->changed & XkbKeyBehaviorsMask) && 560 ((!srv) || (!srv->behaviors))) || 561 ((changes->changed & XkbVirtualModsMask) && (!srv)) || 562 ((changes->changed & XkbExplicitComponentsMask) && 563 ((!srv) || (!srv->explicit))) || 564 ((changes->changed & XkbModifierMapMask) && ((!map) || (!map->modmap))) 565 || ((changes->changed & XkbVirtualModMapMask) && 566 ((!srv) || (!srv->vmodmap)))) 567 return False; 568 569 LockDisplay(dpy); 570 xkbi = dpy->xkb_info; 571 GetReq(kbSetMap, req); 572 req->reqType = xkbi->codes->major_opcode; 573 req->xkbReqType = X_kbSetMap; 574 req->deviceSpec = xkb->device_spec; 575 req->present = changes->changed; 576 req->flags = XkbSetMapRecomputeActions; 577 req->minKeyCode = xkb->min_key_code; 578 req->maxKeyCode = xkb->max_key_code; 579 req->firstType = changes->first_type; 580 req->nTypes = changes->num_types; 581 req->firstKeySym = changes->first_key_sym; 582 req->nKeySyms = changes->num_key_syms; 583 req->firstKeyAct = changes->first_key_act; 584 req->nKeyActs = changes->num_key_acts; 585 req->firstKeyBehavior = changes->first_key_behavior; 586 req->nKeyBehaviors = changes->num_key_behaviors; 587 req->virtualMods = changes->vmods; 588 req->firstKeyExplicit = changes->first_key_explicit; 589 req->nKeyExplicit = changes->num_key_explicit; 590 req->firstModMapKey = changes->first_modmap_key; 591 req->nModMapKeys = changes->num_modmap_keys; 592 req->firstVModMapKey = changes->first_vmodmap_key; 593 req->nVModMapKeys = changes->num_vmodmap_keys; 594 SendSetMap(dpy, xkb, req); 595 UnlockDisplay(dpy); 596 SyncHandle(); 597 return True; 598} 599