XKBSetMap.c revision e9fcaa8a
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,sz; 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 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; 83 wire= (xkbKTSetMapEntryWireDesc *)buf; 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; 92 pwire= (xkbModsWireDesc *)buf; 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{ 127register KeySym * pSym; 128CARD32 * outSym; 129XkbSymMapPtr symMap; 130xkbSymMapWireDesc *desc; 131register 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 numDesc[i] = XkbKeyNumActions(xkb,(i+req->firstKeyAct)); 194 } 195 actDesc = (XkbAction *)&numDesc[XkbPaddedSize(req->nKeyActs)]; 196 for (i=0;i<req->nKeyActs;i++) { 197 if (xkb->server->key_acts[i+req->firstKeyAct]!=0) { 198 n = XkbKeyNumActions(xkb,(i+req->firstKeyAct)); 199 memcpy(actDesc,XkbKeyActionsPtr(xkb,(i+req->firstKeyAct)), 200 n*SIZEOF(xkbActionWireDesc)); 201 actDesc+= n; 202 } 203 } 204 return; 205} 206 207static int 208_XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbSetMapReq *req) 209{ 210register int i,first,last,nFound; 211 212 if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) { 213 req->present&= ~XkbKeyBehaviorsMask; 214 req->firstKeyBehavior= req->nKeyBehaviors= 0; 215 req->totalKeyBehaviors= 0; 216 return 0; 217 } 218 first= req->firstKeyBehavior; 219 last= first+req->nKeyBehaviors-1; 220 for (i=first,nFound=0;i<=last;i++) { 221 if (xkb->server->behaviors[i].type!=XkbKB_Default) 222 nFound++; 223 } 224 req->totalKeyBehaviors= nFound; 225 return (nFound*SIZEOF(xkbBehaviorWireDesc)); 226} 227 228static void 229_XkbWriteKeyBehaviors(Display *dpy,XkbDescPtr xkb,xkbSetMapReq *req) 230{ 231register int i,first,last; 232xkbBehaviorWireDesc * wire; 233char * buf; 234 235 if ((req->present&XkbKeyBehaviorsMask)==0) 236 return; 237 first= req->firstKeyBehavior; 238 last= first+req->nKeyBehaviors-1; 239 240 i= req->totalKeyBehaviors*SIZEOF(xkbBehaviorWireDesc); 241 BufAlloc(char *,buf,i); 242 wire= (xkbBehaviorWireDesc *)buf; 243 for (i=first;i<=last;i++) { 244 if (xkb->server->behaviors[i].type!=XkbKB_Default) { 245 wire->key= i; 246 wire->type= xkb->server->behaviors[i].type; 247 wire->data= xkb->server->behaviors[i].data; 248 buf+= SIZEOF(xkbBehaviorWireDesc); 249 wire= (xkbBehaviorWireDesc *)buf; 250 } 251 } 252 return; 253} 254 255static unsigned 256_XkbSizeVirtualMods(xkbSetMapReq *req) 257{ 258register int i,bit,nMods; 259 260 if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) { 261 req->present&= ~XkbVirtualModsMask; 262 req->virtualMods= 0; 263 return 0; 264 } 265 for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 266 if (req->virtualMods&bit) 267 nMods++; 268 } 269 return XkbPaddedSize(nMods); 270} 271 272static void 273_XkbWriteVirtualMods( Display * dpy, 274 XkbDescPtr xkb, 275 xkbSetMapReq * req, 276 unsigned size) 277{ 278 register int i,bit; 279 CARD8 *vmods; 280 281 /* This was req->present&XkbVirtualModsMask==0, and '==' beats '&' */ 282 if (((req->present & XkbVirtualModsMask) == 0) || (size < 1)) 283 return; 284 BufAlloc(CARD8 *,vmods,size); 285 for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 286 if (req->virtualMods&bit) 287 *vmods++= xkb->server->vmods[i]; 288 } 289 return; 290} 291 292static int 293_XkbSizeKeyExplicit(XkbDescPtr xkb,xkbSetMapReq *req) 294{ 295register int i,first,last,nFound; 296 297 if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit==0)) { 298 req->present&= ~XkbExplicitComponentsMask; 299 req->firstKeyExplicit= req->nKeyExplicit= 0; 300 req->totalKeyExplicit= 0; 301 return 0; 302 } 303 first= req->firstKeyExplicit; 304 last= first+req->nKeyExplicit-1; 305 306 for (i=first,nFound=0;i<=last;i++) { 307 if (xkb->server->explicit[i]!=0) 308 nFound++; 309 } 310 req->totalKeyExplicit= nFound; 311 return XkbPaddedSize((nFound*2)); 312} 313 314static void 315_XkbWriteKeyExplicit(Display *dpy,XkbDescPtr xkb,xkbSetMapReq *req) 316{ 317register int i,first,last; 318CARD8 * wire; 319 320 if ((req->present&XkbExplicitComponentsMask)==0) 321 return; 322 first= req->firstKeyExplicit; 323 last= first+req->nKeyExplicit - 1; 324 i= XkbPaddedSize((req->totalKeyExplicit*2)); 325 BufAlloc(CARD8 *,wire,i); 326 for (i=first;i<=last;i++) { 327 if (xkb->server->explicit[i]!=0) { 328 wire[0]= i; 329 wire[1]= xkb->server->explicit[i]; 330 wire+= 2; 331 } 332 } 333 return; 334} 335 336static int 337_XkbSizeModifierMap(XkbDescPtr xkb,xkbSetMapReq *req) 338{ 339register int i,first,last,nFound; 340 341 if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys==0)) { 342 req->present&= ~XkbModifierMapMask; 343 req->firstModMapKey= req->nModMapKeys= 0; 344 req->totalModMapKeys= 0; 345 return 0; 346 } 347 first= req->firstModMapKey; 348 last= first+req->nModMapKeys-1; 349 350 for (i=first,nFound=0;i<=last;i++) { 351 if (xkb->map->modmap[i]!=0) 352 nFound++; 353 } 354 req->totalModMapKeys= nFound; 355 return XkbPaddedSize((nFound*2)); 356} 357 358static void 359_XkbWriteModifierMap(Display *dpy,XkbDescPtr xkb,xkbSetMapReq *req) 360{ 361register int i,first,last; 362CARD8 * wire; 363 364 if ((req->present&XkbModifierMapMask)==0) 365 return; 366 first= req->firstModMapKey; 367 last= first+req->nModMapKeys-1; 368 if (req->totalModMapKeys>0) { 369 i= XkbPaddedSize((req->totalModMapKeys*2)); 370 BufAlloc(CARD8 *,wire,i); 371 for (i=first;i<=last;i++) { 372 if (xkb->map->modmap[i]!=0) { 373 wire[0]= i; 374 wire[1]= xkb->map->modmap[i]; 375 wire+= 2; 376 } 377 } 378 } 379 return; 380} 381 382static int 383_XkbSizeVirtualModMap(XkbDescPtr xkb,xkbSetMapReq *req) 384{ 385register int i,first,last,nFound; 386 387 if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys==0)) { 388 req->present&= ~XkbVirtualModMapMask; 389 req->firstVModMapKey= req->nVModMapKeys= 0; 390 req->totalVModMapKeys= 0; 391 return 0; 392 } 393 first= req->firstVModMapKey; 394 last= first+req->nVModMapKeys-1; 395 396 for (i=first,nFound=0;i<=last;i++) { 397 if (xkb->server->vmodmap[i]!=0) 398 nFound++; 399 } 400 req->totalVModMapKeys= nFound; 401 return nFound*SIZEOF(xkbVModMapWireDesc); 402} 403 404static void 405_XkbWriteVirtualModMap(Display *dpy,XkbDescPtr xkb,xkbSetMapReq *req) 406{ 407register int i,first,last; 408xkbVModMapWireDesc * wire; 409 410 if ((req->present&XkbVirtualModMapMask)==0) 411 return; 412 first= req->firstVModMapKey; 413 last= first+req->nVModMapKeys-1; 414 if (req->totalVModMapKeys>0) { 415 i= req->totalVModMapKeys*SIZEOF(xkbVModMapWireDesc); 416 BufAlloc(xkbVModMapWireDesc *,wire,i); 417 for (i=first;i<=last;i++) { 418 if (xkb->server->vmodmap[i]!=0) { 419 wire->key= i; 420 wire->vmods= xkb->server->vmodmap[i]; 421 wire++; 422 } 423 } 424 } 425 return; 426} 427 428static void 429SendSetMap(Display *dpy,XkbDescPtr xkb,xkbSetMapReq *req) 430{ 431xkbSetMapReq tmp; 432unsigned szMods; 433 434 req->length+= _XkbSizeKeyTypes(xkb,req)/4; 435 req->length+= _XkbSizeKeySyms(xkb,req)/4; 436 req->length+= _XkbSizeKeyActions(xkb,req)/4; 437 req->length+= _XkbSizeKeyBehaviors(xkb,req)/4; 438 szMods= _XkbSizeVirtualMods(req); 439 req->length+= szMods/4; 440 req->length+= _XkbSizeKeyExplicit(xkb,req)/4; 441 req->length+= _XkbSizeModifierMap(xkb,req)/4; 442 req->length+= _XkbSizeVirtualModMap(xkb,req)/4; 443 444 tmp= *req; 445 if ( tmp.nTypes>0 ) 446 _XkbWriteKeyTypes(dpy,xkb,&tmp); 447 if ( tmp.nKeySyms>0 ) 448 _XkbWriteKeySyms(dpy,xkb,&tmp); 449 if ( tmp.nKeyActs ) 450 _XkbWriteKeyActions(dpy,xkb,&tmp); 451 if ( tmp.totalKeyBehaviors>0 ) 452 _XkbWriteKeyBehaviors(dpy,xkb,&tmp); 453 if ( tmp.virtualMods ) 454 _XkbWriteVirtualMods(dpy,xkb,&tmp,szMods); 455 if ( tmp.totalKeyExplicit>0) 456 _XkbWriteKeyExplicit(dpy,xkb,&tmp); 457 if ( tmp.totalModMapKeys>0) 458 _XkbWriteModifierMap(dpy,xkb,&tmp); 459 if ( tmp.totalVModMapKeys>0) 460 _XkbWriteVirtualModMap(dpy,xkb,&tmp); 461 return; 462} 463 464Bool 465XkbSetMap(Display *dpy,unsigned which,XkbDescPtr xkb) 466{ 467register xkbSetMapReq * req; 468XkbInfoPtr xkbi; 469XkbServerMapPtr srv; 470XkbClientMapPtr map; 471 472 if ((dpy->flags & XlibDisplayNoXkb) || 473 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))|| 474 (!xkb)) 475 return False; 476 map= xkb->map; 477 srv= xkb->server; 478 479 if (((which&XkbKeyTypesMask)&&((!map)||(!map->types)))|| 480 ((which&XkbKeySymsMask)&&((!map)||(!map->syms)||(!map->key_sym_map)))|| 481 ((which&XkbKeyActionsMask)&&((!srv)||(!srv->key_acts)))|| 482 ((which&XkbKeyBehaviorsMask)&&((!srv)||(!srv->behaviors)))|| 483 ((which&XkbVirtualModsMask)&&(!srv))|| 484 ((which&XkbExplicitComponentsMask)&&((!srv)||(!srv->explicit)))|| 485 ((which&XkbModifierMapMask)&&((!map)||(!map->modmap)))|| 486 ((which&XkbVirtualModMapMask)&&((!srv)||(!srv->vmodmap)))) 487 return False; 488 489 LockDisplay(dpy); 490 xkbi = dpy->xkb_info; 491 GetReq(kbSetMap, req); 492 req->reqType = xkbi->codes->major_opcode; 493 req->xkbReqType = X_kbSetMap; 494 req->deviceSpec = xkb->device_spec; 495 req->present = which; 496 req->flags = XkbSetMapAllFlags; 497 req->minKeyCode= xkb->min_key_code; 498 req->maxKeyCode= xkb->max_key_code; 499 req->firstType = 0; 500 if (which&XkbKeyTypesMask) req->nTypes = map->num_types; 501 else req->nTypes = 0; 502 if (which&XkbKeySymsMask) { 503 req->firstKeySym = xkb->min_key_code; 504 req->nKeySyms = XkbNumKeys(xkb); 505 } 506 if (which&XkbKeyActionsMask) { 507 req->firstKeyAct = xkb->min_key_code; 508 req->nKeyActs = XkbNumKeys(xkb); 509 } 510 if (which&XkbKeyBehaviorsMask) { 511 req->firstKeyBehavior = xkb->min_key_code; 512 req->nKeyBehaviors = XkbNumKeys(xkb); 513 } 514 if (which&XkbVirtualModsMask) 515 req->virtualMods= ~0; 516 if (which&XkbExplicitComponentsMask) { 517 req->firstKeyExplicit= xkb->min_key_code; 518 req->nKeyExplicit = XkbNumKeys(xkb); 519 } 520 if (which&XkbModifierMapMask) { 521 req->firstModMapKey= xkb->min_key_code; 522 req->nModMapKeys = XkbNumKeys(xkb); 523 } 524 if (which&XkbVirtualModMapMask) { 525 req->firstVModMapKey= xkb->min_key_code; 526 req->nVModMapKeys = XkbNumKeys(xkb); 527 } 528 SendSetMap(dpy,xkb,req); 529 UnlockDisplay(dpy); 530 SyncHandle(); 531 return True; 532} 533 534Bool 535XkbChangeMap(Display *dpy,XkbDescPtr xkb,XkbMapChangesPtr changes) 536{ 537register xkbSetMapReq * req; 538XkbInfoPtr xkbi; 539XkbServerMapPtr srv; 540XkbClientMapPtr map; 541 542 if ((dpy->flags & XlibDisplayNoXkb) || 543 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))|| 544 (!xkb)||(!changes)) 545 return False; 546 srv= xkb->server; 547 map= xkb->map; 548 549 if (((changes->changed&XkbKeyTypesMask)&&((!map)||(!map->types)))|| 550 ((changes->changed&XkbKeySymsMask)&&((!map)||(!map->syms)|| 551 (!map->key_sym_map)))|| 552 ((changes->changed&XkbKeyActionsMask)&&((!srv)||(!srv->key_acts)))|| 553 ((changes->changed&XkbKeyBehaviorsMask)&&((!srv)||(!srv->behaviors)))|| 554 ((changes->changed&XkbVirtualModsMask)&&(!srv))|| 555 ((changes->changed&XkbExplicitComponentsMask)&& 556 ((!srv)||(!srv->explicit)))|| 557 ((changes->changed&XkbModifierMapMask)&&((!map)||(!map->modmap)))|| 558 ((changes->changed&XkbVirtualModMapMask)&&((!srv)||(!srv->vmodmap)))) 559 return False; 560 561 LockDisplay(dpy); 562 xkbi = dpy->xkb_info; 563 GetReq(kbSetMap, req); 564 req->reqType = xkbi->codes->major_opcode; 565 req->xkbReqType = X_kbSetMap; 566 req->deviceSpec = xkb->device_spec; 567 req->present = changes->changed; 568 req->flags = XkbSetMapRecomputeActions; 569 req->minKeyCode= xkb->min_key_code; 570 req->maxKeyCode= xkb->max_key_code; 571 req->firstType = changes->first_type; 572 req->nTypes = changes->num_types; 573 req->firstKeySym = changes->first_key_sym; 574 req->nKeySyms = changes->num_key_syms; 575 req->firstKeyAct = changes->first_key_act; 576 req->nKeyActs = changes->num_key_acts; 577 req->firstKeyBehavior = changes->first_key_behavior; 578 req->nKeyBehaviors = changes->num_key_behaviors; 579 req->virtualMods = changes->vmods; 580 req->firstKeyExplicit = changes->first_key_explicit; 581 req->nKeyExplicit = changes->num_key_explicit; 582 req->firstModMapKey = changes->first_modmap_key; 583 req->nModMapKeys = changes->num_modmap_keys; 584 req->firstVModMapKey = changes->first_vmodmap_key; 585 req->nVModMapKeys = changes->num_vmodmap_keys; 586 SendSetMap(dpy,xkb,req); 587 UnlockDisplay(dpy); 588 SyncHandle(); 589 return True; 590} 591 592