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