xkbUtils.c revision 4642e01f
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 28Copyright © 2008 Red Hat Inc. 29 30Permission is hereby granted, free of charge, to any person obtaining a 31copy of this software and associated documentation files (the "Software"), 32to deal in the Software without restriction, including without limitation 33the rights to use, copy, modify, merge, publish, distribute, sublicense, 34and/or sell copies of the Software, and to permit persons to whom the 35Software is furnished to do so, subject to the following conditions: 36 37The above copyright notice and this permission notice (including the next 38paragraph) shall be included in all copies or substantial portions of the 39Software. 40 41THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 44THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 47DEALINGS IN THE SOFTWARE. 48 49*/ 50 51#ifdef HAVE_DIX_CONFIG_H 52#include <dix-config.h> 53#endif 54 55#include "os.h" 56#include <stdio.h> 57#include <ctype.h> 58#include <math.h> 59#define NEED_EVENTS 1 60#include <X11/X.h> 61#include <X11/Xproto.h> 62#define XK_CYRILLIC 63#include <X11/keysym.h> 64#include "misc.h" 65#include "inputstr.h" 66 67#define XKBSRV_NEED_FILE_FUNCS 68#include <xkbsrv.h> 69#include "xkbgeom.h" 70#include "xkb.h" 71 72int XkbDisableLockActions = 0; 73 74/***====================================================================***/ 75 76int 77_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 78 Mask access_mode, int *xkb_err) 79{ 80 int rc = XkbKeyboardErrorCode; 81 82 if (id == XkbUseCoreKbd) 83 id = PickKeyboard(client)->id; 84 else if (id == XkbUseCorePtr) 85 id = PickPointer(client)->id; 86 87 rc = dixLookupDevice(pDev, id, client, access_mode); 88 if (rc != Success) 89 *xkb_err = XkbErr_BadDevice; 90 91 return rc; 92} 93 94int 95_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client, 96 Mask access_mode, int *xkb_err) 97{ 98 DeviceIntPtr dev; 99 int rc; 100 101 if (id == XkbDfltXIId) 102 id = XkbUseCoreKbd; 103 104 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 105 if (rc != Success) 106 return rc; 107 108 dev = *pDev; 109 if (!dev->key || !dev->key->xkbInfo) { 110 *pDev = NULL; 111 *xkb_err= XkbErr_BadClass; 112 return XkbKeyboardErrorCode; 113 } 114 return Success; 115} 116 117int 118_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 119 Mask access_mode, int *xkb_err) 120{ 121 DeviceIntPtr dev; 122 int rc; 123 124 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 125 if (rc != Success) 126 return rc; 127 128 dev = *pDev; 129 if (!dev->kbdfeed && !dev->bell) { 130 *pDev = NULL; 131 *xkb_err= XkbErr_BadClass; 132 return XkbKeyboardErrorCode; 133 } 134 return Success; 135} 136 137int 138_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 139 Mask access_mode, int *xkb_err) 140{ 141 DeviceIntPtr dev; 142 int rc; 143 144 if (id == XkbDfltXIId) 145 id = XkbUseCorePtr; 146 147 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 148 if (rc != Success) 149 return rc; 150 151 dev = *pDev; 152 if (!dev->kbdfeed && !dev->leds) { 153 *pDev = NULL; 154 *xkb_err= XkbErr_BadClass; 155 return XkbKeyboardErrorCode; 156 } 157 return Success; 158} 159 160int 161_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 162 Mask access_mode, int *xkb_err) 163{ 164 DeviceIntPtr dev; 165 int rc; 166 167 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 168 if (rc != Success) 169 return rc; 170 171 dev = *pDev; 172 if (!dev->button) { 173 *pDev = NULL; 174 *xkb_err= XkbErr_BadClass; 175 return XkbKeyboardErrorCode; 176 } 177 return Success; 178} 179 180void 181XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 182{ 183register unsigned tmp; 184 185 switch (act->type) { 186 case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 187 if (act->mods.flags&XkbSA_UseModMapMods) 188 act->mods.real_mods= act->mods.mask= mods; 189 if ((tmp= XkbModActionVMods(&act->mods))!=0) 190 act->mods.mask|= XkbMaskForVMask(xkb,tmp); 191 break; 192 case XkbSA_ISOLock: 193 if (act->iso.flags&XkbSA_UseModMapMods) 194 act->iso.real_mods= act->iso.mask= mods; 195 if ((tmp= XkbModActionVMods(&act->iso))!=0) 196 act->iso.mask|= XkbMaskForVMask(xkb,tmp); 197 break; 198 } 199 return; 200} 201 202unsigned 203XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask) 204{ 205register int i,bit; 206register unsigned mask; 207 208 for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 209 if (vmask&bit) 210 mask|= xkb->server->vmods[i]; 211 } 212 return mask; 213} 214 215/***====================================================================***/ 216 217void 218XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev, 219 KeyCode first, 220 CARD8 num, 221 XkbChangesPtr changes) 222{ 223XkbDescPtr xkb; 224unsigned key,nG,explicit; 225KeySymsPtr pCore; 226int types[XkbNumKbdGroups]; 227KeySym tsyms[XkbMaxSymsPerKey],*syms; 228XkbMapChangesPtr mc; 229 230 xkb= pXDev->key->xkbInfo->desc; 231 if (first+num-1>xkb->max_key_code) { 232 /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */ 233 num= xkb->max_key_code-first+1; 234 } 235 236 mc= (changes?(&changes->map):NULL); 237 238 pCore= &pXDev->key->curKeySyms; 239 syms= &pCore->map[(first-xkb->min_key_code)*pCore->mapWidth]; 240 for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) { 241 explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; 242 types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 243 types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); 244 types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); 245 types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); 246 nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types, 247 tsyms); 248 XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); 249 memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, 250 XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 251 } 252 if (changes->map.changed&XkbKeySymsMask) { 253 CARD8 oldLast,newLast; 254 oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1; 255 newLast = first+num-1; 256 257 if (first<changes->map.first_key_sym) 258 changes->map.first_key_sym = first; 259 if (oldLast>newLast) 260 newLast= oldLast; 261 changes->map.num_key_syms = newLast-changes->map.first_key_sym+1; 262 } 263 else { 264 changes->map.changed|= XkbKeySymsMask; 265 changes->map.first_key_sym = first; 266 changes->map.num_key_syms = num; 267 } 268 return; 269} 270 271void 272XkbUpdateDescActions( XkbDescPtr xkb, 273 KeyCode first, 274 CARD8 num, 275 XkbChangesPtr changes) 276{ 277register unsigned key; 278 279 for (key=first;key<(first+num);key++) { 280 XkbApplyCompatMapToKey(xkb,key,changes); 281 } 282 283 if (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask)) { 284 unsigned char newVMods[XkbNumVirtualMods]; 285 register unsigned bit,i; 286 unsigned present; 287 288 bzero(newVMods,XkbNumVirtualMods); 289 present= 0; 290 for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { 291 if (xkb->server->vmodmap[key]==0) 292 continue; 293 for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 294 if (bit&xkb->server->vmodmap[key]) { 295 present|= bit; 296 newVMods[i]|= xkb->map->modmap[key]; 297 } 298 } 299 } 300 for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 301 if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { 302 changes->map.changed|= XkbVirtualModsMask; 303 changes->map.vmods|= bit; 304 xkb->server->vmods[i]= newVMods[i]; 305 } 306 } 307 } 308 if (changes->map.changed&XkbVirtualModsMask) 309 XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); 310 311 if (changes->map.changed&XkbKeyActionsMask) { 312 CARD8 oldLast,newLast; 313 oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; 314 newLast = first+num-1; 315 316 if (first<changes->map.first_key_act) 317 changes->map.first_key_act = first; 318 if (newLast>oldLast) 319 newLast= oldLast; 320 changes->map.num_key_acts= newLast-changes->map.first_key_act+1; 321 } 322 else { 323 changes->map.changed|= XkbKeyActionsMask; 324 changes->map.first_key_act = first; 325 changes->map.num_key_acts = num; 326 } 327 return; 328} 329 330void 331XkbUpdateActions( DeviceIntPtr pXDev, 332 KeyCode first, 333 CARD8 num, 334 XkbChangesPtr changes, 335 unsigned * needChecksRtrn, 336 XkbEventCausePtr cause) 337{ 338XkbSrvInfoPtr xkbi; 339XkbDescPtr xkb; 340CARD8 * repeat; 341 342 if (needChecksRtrn) 343 *needChecksRtrn= 0; 344 xkbi= pXDev->key->xkbInfo; 345 xkb= xkbi->desc; 346 repeat= xkb->ctrls->per_key_repeat; 347 348 if (pXDev->kbdfeed) 349 memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,32); 350 351 XkbUpdateDescActions(xkb,first,num,changes); 352 353 if ((pXDev->kbdfeed)&& 354 (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) { 355 memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, 32); 356 (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); 357 } 358 return; 359} 360 361void 362XkbUpdateCoreDescription(DeviceIntPtr keybd,Bool resize) 363{ 364register int key,tmp; 365int maxSymsPerKey,maxKeysPerMod; 366int first,last,firstCommon,lastCommon; 367XkbDescPtr xkb; 368KeyClassPtr keyc; 369CARD8 keysPerMod[XkbNumModifiers]; 370 371 if (!keybd || !keybd->key || !keybd->key->xkbInfo) 372 return; 373 xkb= keybd->key->xkbInfo->desc; 374 keyc= keybd->key; 375 maxSymsPerKey= maxKeysPerMod= 0; 376 bzero(keysPerMod,sizeof(keysPerMod)); 377 memcpy(keyc->modifierMap,xkb->map->modmap,xkb->max_key_code+1); 378 if ((xkb->min_key_code==keyc->curKeySyms.minKeyCode)&& 379 (xkb->max_key_code==keyc->curKeySyms.maxKeyCode)) { 380 first= firstCommon= xkb->min_key_code; 381 last= lastCommon= xkb->max_key_code; 382 } 383 else if (resize) { 384 keyc->curKeySyms.minKeyCode= xkb->min_key_code; 385 keyc->curKeySyms.maxKeyCode= xkb->max_key_code; 386 tmp= keyc->curKeySyms.mapWidth*_XkbCoreNumKeys(keyc); 387 keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); 388 if (!keyc->curKeySyms.map) 389 FatalError("Couldn't allocate keysyms\n"); 390 first= firstCommon= xkb->min_key_code; 391 last= lastCommon= xkb->max_key_code; 392 } 393 else { 394 if (xkb->min_key_code<keyc->curKeySyms.minKeyCode) { 395 first= xkb->min_key_code; 396 firstCommon= keyc->curKeySyms.minKeyCode; 397 } 398 else { 399 firstCommon= xkb->min_key_code; 400 first= keyc->curKeySyms.minKeyCode; 401 } 402 if (xkb->max_key_code>keyc->curKeySyms.maxKeyCode) { 403 lastCommon= keyc->curKeySyms.maxKeyCode; 404 last= xkb->max_key_code; 405 } 406 else { 407 lastCommon= xkb->max_key_code; 408 last= keyc->curKeySyms.maxKeyCode; 409 } 410 } 411 412 /* determine sizes */ 413 for (key=first;key<=last;key++) { 414 if (XkbKeycodeInRange(xkb,key)) { 415 int nGroups; 416 int w; 417 nGroups= XkbKeyNumGroups(xkb,key); 418 tmp= 0; 419 if (nGroups>0) { 420 if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<=2) 421 tmp+= 2; 422 else tmp+= w + 2; 423 } 424 if (nGroups>1) { 425 if (tmp <= 2) { 426 if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2) 427 tmp+= 2; 428 else tmp+= w; 429 } else { 430 if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2) 431 tmp+= w - 2; 432 } 433 } 434 if (nGroups>2) 435 tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index); 436 if (nGroups>3) 437 tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index); 438 if (tmp>maxSymsPerKey) 439 maxSymsPerKey= tmp; 440 } 441 if (_XkbCoreKeycodeInRange(keyc,key)) { 442 if (keyc->modifierMap[key]!=0) { 443 register unsigned bit,i,mask; 444 mask= keyc->modifierMap[key]; 445 for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { 446 if (mask&bit) { 447 keysPerMod[i]++; 448 if (keysPerMod[i]>maxKeysPerMod) 449 maxKeysPerMod= keysPerMod[i]; 450 } 451 } 452 } 453 } 454 } 455 456 if (maxKeysPerMod>0) { 457 tmp= maxKeysPerMod*XkbNumModifiers; 458 if (keyc->modifierKeyMap==NULL) 459 keyc->modifierKeyMap= (KeyCode *)_XkbCalloc(1, tmp); 460 else if (keyc->maxKeysPerModifier<maxKeysPerMod) 461 keyc->modifierKeyMap= (KeyCode *)_XkbRealloc(keyc->modifierKeyMap,tmp); 462 if (keyc->modifierKeyMap==NULL) 463 FatalError("Couldn't allocate modifierKeyMap in UpdateCore\n"); 464 bzero(keyc->modifierKeyMap,tmp); 465 } 466 else if ((keyc->maxKeysPerModifier>0)&&(keyc->modifierKeyMap!=NULL)) { 467 _XkbFree(keyc->modifierKeyMap); 468 keyc->modifierKeyMap= NULL; 469 } 470 keyc->maxKeysPerModifier= maxKeysPerMod; 471 472 if (maxSymsPerKey>0) { 473 tmp= maxSymsPerKey*_XkbCoreNumKeys(keyc); 474 keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); 475 if (keyc->curKeySyms.map==NULL) 476 FatalError("Couldn't allocate symbols map in UpdateCore\n"); 477 } 478 else if ((keyc->curKeySyms.mapWidth>0)&&(keyc->curKeySyms.map!=NULL)) { 479 _XkbFree(keyc->curKeySyms.map); 480 keyc->curKeySyms.map= NULL; 481 } 482 keyc->curKeySyms.mapWidth= maxSymsPerKey; 483 484 bzero(keysPerMod,sizeof(keysPerMod)); 485 for (key=firstCommon;key<=lastCommon;key++) { 486 if (keyc->curKeySyms.map!=NULL) { 487 KeySym *pCore,*pXKB; 488 unsigned nGroups,groupWidth,n,nOut; 489 490 nGroups= XkbKeyNumGroups(xkb,key); 491 n= (key-keyc->curKeySyms.minKeyCode)*maxSymsPerKey; 492 pCore= &keyc->curKeySyms.map[n]; 493 bzero(pCore,maxSymsPerKey*sizeof(KeySym)); 494 pXKB= XkbKeySymsPtr(xkb,key); 495 nOut= 2; 496 if (nGroups>0) { 497 groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index); 498 if (groupWidth>0) pCore[0]= pXKB[0]; 499 if (groupWidth>1) pCore[1]= pXKB[1]; 500 for (n=2;n<groupWidth;n++) { 501 pCore[2+n]= pXKB[n]; 502 } 503 if (groupWidth>2) 504 nOut= groupWidth; 505 } 506 507 /* See XKB Protocol Sec, Section 12.4. 508 A 1-group key with ABCDE on a 2 group keyboard must be 509 duplicated across all groups as ABABCDECDE. 510 */ 511 if (nGroups == 1) 512 { 513 int idx; 514 515 groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index); 516 517 /* AB..CDE... -> ABABCDE... */ 518 if (groupWidth > 0 && maxSymsPerKey >= 3) 519 pCore[2] = pCore[0]; 520 if (groupWidth > 1 && maxSymsPerKey >= 4) 521 pCore[3] = pCore[1]; 522 523 /* ABABCDE... -> ABABCDECDE */ 524 idx = 2 + groupWidth; 525 while (groupWidth > 2 && 526 idx < maxSymsPerKey && 527 idx < groupWidth * 2) 528 { 529 pCore[idx] = pCore[idx - groupWidth + 2]; 530 idx++; 531 } 532 idx = 2 * groupWidth; 533 if (idx < 4) 534 idx = 4; 535 /* 3 or more groups: ABABCDECDEABCDEABCDE */ 536 for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++) 537 pCore[idx++] = pXKB[n]; 538 } 539 540 pXKB+= XkbKeyGroupsWidth(xkb,key); 541 nOut+= 2; 542 if (nGroups>1) { 543 groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); 544 if (groupWidth>0) pCore[2]= pXKB[0]; 545 if (groupWidth>1) pCore[3]= pXKB[1]; 546 for (n=2;n<groupWidth;n++) { 547 pCore[nOut+(n-2)]= pXKB[n]; 548 } 549 if (groupWidth>2) 550 nOut+= (groupWidth-2); 551 } 552 pXKB+= XkbKeyGroupsWidth(xkb,key); 553 for (n=XkbGroup3Index;n<nGroups;n++) { 554 register int s; 555 groupWidth= XkbKeyGroupWidth(xkb,key,n); 556 for (s=0;s<groupWidth;s++) { 557 pCore[nOut++]= pXKB[s]; 558 } 559 pXKB+= XkbKeyGroupsWidth(xkb,key); 560 } 561 } 562 if (keyc->modifierMap[key]!=0) { 563 register unsigned bit,i,mask; 564 mask= keyc->modifierMap[key]; 565 for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { 566 if (mask&bit) { 567 tmp= i*maxKeysPerMod+keysPerMod[i]; 568 keyc->modifierKeyMap[tmp]= key; 569 keysPerMod[i]++; 570 } 571 } 572 } 573 } 574 return; 575} 576 577void 578XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) 579{ 580 if (pXDev && pXDev->key && pXDev->key->xkbInfo) { 581 xkbControlsNotify cn; 582 XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls; 583 XkbControlsRec old; 584 old = *ctrls; 585 586 if (key== -1) { /* global autorepeat setting changed */ 587 if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask; 588 else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask; 589 } 590 else if (pXDev->kbdfeed) { 591 ctrls->per_key_repeat[key/8] = 592 pXDev->kbdfeed->ctrl.autoRepeats[key/8]; 593 } 594 595 if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,True)) 596 XkbSendControlsNotify(pXDev,&cn); 597 } 598 return; 599} 600 601void 602XkbApplyMappingChange( DeviceIntPtr kbd, 603 CARD8 request, 604 KeyCode firstKey, 605 CARD8 num, 606 ClientPtr client) 607{ 608XkbEventCauseRec cause; 609XkbChangesRec changes; 610unsigned check; 611 612 if (kbd->key->xkbInfo==NULL) 613 XkbInitDevice(kbd); 614 bzero(&changes,sizeof(XkbChangesRec)); 615 check= 0; 616 if (request==MappingKeyboard) { 617 XkbSetCauseCoreReq(&cause,X_ChangeKeyboardMapping,client); 618 XkbUpdateKeyTypesFromCore(kbd,firstKey,num,&changes); 619 XkbUpdateActions(kbd,firstKey,num,&changes,&check,&cause); 620 if (check) 621 XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); 622 } 623 else if (request==MappingModifier) { 624 XkbDescPtr xkb= kbd->key->xkbInfo->desc; 625 626 XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); 627 628 num = xkb->max_key_code-xkb->min_key_code+1; 629 memcpy(xkb->map->modmap,kbd->key->modifierMap,xkb->max_key_code+1); 630 631 changes.map.changed|= XkbModifierMapMask; 632 changes.map.first_modmap_key= xkb->min_key_code; 633 changes.map.num_modmap_keys= num; 634 XkbUpdateActions(kbd,xkb->min_key_code,num,&changes,&check,&cause); 635 if (check) 636 XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); 637 } 638 /* 3/26/94 (ef) -- XXX! Doesn't deal with input extension requests */ 639 XkbSendNotification(kbd,&changes,&cause); 640 return; 641} 642 643void 644XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key) 645{ 646XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 647xkbMapNotify mn; 648 649 xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask; 650 bzero(&mn,sizeof(mn)); 651 mn.changed= XkbExplicitComponentsMask; 652 mn.firstKeyExplicit= key; 653 mn.nKeyExplicit= 1; 654 XkbSendMapNotify(dev,&mn); 655 return; 656} 657 658unsigned 659XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new) 660{ 661int changed; 662 663 changed=(old->group!=new->group?XkbGroupStateMask:0); 664 changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0); 665 changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0); 666 changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0); 667 changed|=(old->mods!=new->mods?XkbModifierStateMask:0); 668 changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0); 669 changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0); 670 changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0); 671 changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0); 672 changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0); 673 if (old->compat_grab_mods!=new->compat_grab_mods) 674 changed|= XkbCompatGrabModsMask; 675 changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0); 676 if (old->compat_lookup_mods!=new->compat_lookup_mods) 677 changed|= XkbCompatLookupModsMask; 678 changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0); 679 return changed; 680} 681 682static void 683XkbComputeCompatState(XkbSrvInfoPtr xkbi) 684{ 685CARD16 grp_mask; 686XkbStatePtr state= &xkbi->state; 687XkbCompatMapPtr map; 688 689 if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat) 690 return; 691 692 map= xkbi->desc->compat; 693 grp_mask= map->groups[state->group].mask; 694 state->compat_state = state->mods|grp_mask; 695 state->compat_lookup_mods= state->lookup_mods|grp_mask; 696 697 if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask) 698 grp_mask= map->groups[state->base_group].mask; 699 state->compat_grab_mods= state->grab_mods|grp_mask; 700 return; 701} 702 703unsigned 704XkbAdjustGroup(int group,XkbControlsPtr ctrls) 705{ 706unsigned act; 707 708 act= XkbOutOfRangeGroupAction(ctrls->groups_wrap); 709 if (group<0) { 710 while ( group < 0 ) { 711 if (act==XkbClampIntoRange) { 712 group= XkbGroup1Index; 713 } 714 else if (act==XkbRedirectIntoRange) { 715 int newGroup; 716 newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); 717 if (newGroup>=ctrls->num_groups) 718 group= XkbGroup1Index; 719 else group= newGroup; 720 } 721 else { 722 group+= ctrls->num_groups; 723 } 724 } 725 } 726 else if (group>=ctrls->num_groups) { 727 if (act==XkbClampIntoRange) { 728 group= ctrls->num_groups-1; 729 } 730 else if (act==XkbRedirectIntoRange) { 731 int newGroup; 732 newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); 733 if (newGroup>=ctrls->num_groups) 734 group= XkbGroup1Index; 735 else group= newGroup; 736 } 737 else { 738 group%= ctrls->num_groups; 739 } 740 } 741 return group; 742} 743 744void 745XkbComputeDerivedState(XkbSrvInfoPtr xkbi) 746{ 747XkbStatePtr state= &xkbi->state; 748XkbControlsPtr ctrls= xkbi->desc->ctrls; 749unsigned char grp; 750 751 if (!state || !ctrls) 752 return; 753 754 state->mods= (state->base_mods|state->latched_mods); 755 state->mods|= state->locked_mods; 756 state->lookup_mods= state->mods&(~ctrls->internal.mask); 757 state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask); 758 state->grab_mods|= 759 ((state->base_mods|state->latched_mods)&ctrls->ignore_lock.mask); 760 761 762 grp= state->locked_group; 763 if (grp>=ctrls->num_groups) 764 state->locked_group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); 765 766 grp= state->locked_group+state->base_group+state->latched_group; 767 if (grp>=ctrls->num_groups) 768 state->group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); 769 else state->group= grp; 770 XkbComputeCompatState(xkbi); 771 return; 772} 773 774/***====================================================================***/ 775 776void 777XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi, 778 unsigned which, 779 XkbChangesPtr changes, 780 XkbEventCausePtr cause) 781{ 782 if (which&XkbStateNotifyMask) { 783 XkbStateRec old; 784 old= xkbi->state; 785 changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state); 786 XkbComputeDerivedState(xkbi); 787 } 788 if (which&XkbIndicatorStateNotifyMask) 789 XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,True,changes, 790 cause); 791 return; 792} 793 794/***====================================================================***/ 795 796Bool 797XkbEnableDisableControls( XkbSrvInfoPtr xkbi, 798 unsigned long change, 799 unsigned long newValues, 800 XkbChangesPtr changes, 801 XkbEventCausePtr cause) 802{ 803XkbControlsPtr ctrls; 804unsigned old; 805XkbSrvLedInfoPtr sli; 806 807 ctrls= xkbi->desc->ctrls; 808 old= ctrls->enabled_ctrls; 809 ctrls->enabled_ctrls&= ~change; 810 ctrls->enabled_ctrls|= (change&newValues); 811 if (old==ctrls->enabled_ctrls) 812 return False; 813 if (cause!=NULL) { 814 xkbControlsNotify cn; 815 cn.numGroups= ctrls->num_groups; 816 cn.changedControls|= XkbControlsEnabledMask; 817 cn.enabledControls= ctrls->enabled_ctrls; 818 cn.enabledControlChanges= (ctrls->enabled_ctrls^old); 819 cn.keycode= cause->kc; 820 cn.eventType= cause->event; 821 cn.requestMajor= cause->mjr; 822 cn.requestMinor= cause->mnr; 823 XkbSendControlsNotify(xkbi->device,&cn); 824 } 825 else { 826 /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/ 827 /* is non-zero, the controls in question changed already in "this" */ 828 /* request and this change merely undoes the previous one. By the */ 829 /* same token, we have to figure out whether or not ControlsEnabled */ 830 /* should be set or not in the changes structure */ 831 changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old); 832 if (changes->ctrls.enabled_ctrls_changes) 833 changes->ctrls.changed_ctrls|= XkbControlsEnabledMask; 834 else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask; 835 } 836 sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); 837 XkbUpdateIndicators(xkbi->device,sli->usesControls,True,changes,cause); 838 return True; 839} 840 841/***====================================================================***/ 842 843#define MAX_TOC 16 844 845XkbGeometryPtr 846XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree) 847{ 848XkbSrvInfoPtr xkbi= dev->key->xkbInfo; 849XkbDescPtr xkb= xkbi->desc; 850 851 *shouldFree= 0; 852 if (name==None) { 853 if (xkb->geom!=NULL) 854 return xkb->geom; 855 name= xkb->names->geometry; 856 } 857 if ((xkb->geom!=NULL)&&(xkb->geom->name==name)) 858 return xkb->geom; 859 *shouldFree= 1; 860 return NULL; 861} 862 863void 864XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper) 865{ 866 *lower = sym; 867 *upper = sym; 868 switch(sym >> 8) { 869 case 0: /* Latin 1 */ 870 if ((sym >= XK_A) && (sym <= XK_Z)) 871 *lower += (XK_a - XK_A); 872 else if ((sym >= XK_a) && (sym <= XK_z)) 873 *upper -= (XK_a - XK_A); 874 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) 875 *lower += (XK_agrave - XK_Agrave); 876 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) 877 *upper -= (XK_agrave - XK_Agrave); 878 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) 879 *lower += (XK_oslash - XK_Ooblique); 880 else if ((sym >= XK_oslash) && (sym <= XK_thorn)) 881 *upper -= (XK_oslash - XK_Ooblique); 882 break; 883 case 1: /* Latin 2 */ 884 /* Assume the KeySym is a legal value (ignore discontinuities) */ 885 if (sym == XK_Aogonek) 886 *lower = XK_aogonek; 887 else if (sym >= XK_Lstroke && sym <= XK_Sacute) 888 *lower += (XK_lstroke - XK_Lstroke); 889 else if (sym >= XK_Scaron && sym <= XK_Zacute) 890 *lower += (XK_scaron - XK_Scaron); 891 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) 892 *lower += (XK_zcaron - XK_Zcaron); 893 else if (sym == XK_aogonek) 894 *upper = XK_Aogonek; 895 else if (sym >= XK_lstroke && sym <= XK_sacute) 896 *upper -= (XK_lstroke - XK_Lstroke); 897 else if (sym >= XK_scaron && sym <= XK_zacute) 898 *upper -= (XK_scaron - XK_Scaron); 899 else if (sym >= XK_zcaron && sym <= XK_zabovedot) 900 *upper -= (XK_zcaron - XK_Zcaron); 901 else if (sym >= XK_Racute && sym <= XK_Tcedilla) 902 *lower += (XK_racute - XK_Racute); 903 else if (sym >= XK_racute && sym <= XK_tcedilla) 904 *upper -= (XK_racute - XK_Racute); 905 break; 906 case 2: /* Latin 3 */ 907 /* Assume the KeySym is a legal value (ignore discontinuities) */ 908 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) 909 *lower += (XK_hstroke - XK_Hstroke); 910 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) 911 *lower += (XK_gbreve - XK_Gbreve); 912 else if (sym >= XK_hstroke && sym <= XK_hcircumflex) 913 *upper -= (XK_hstroke - XK_Hstroke); 914 else if (sym >= XK_gbreve && sym <= XK_jcircumflex) 915 *upper -= (XK_gbreve - XK_Gbreve); 916 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) 917 *lower += (XK_cabovedot - XK_Cabovedot); 918 else if (sym >= XK_cabovedot && sym <= XK_scircumflex) 919 *upper -= (XK_cabovedot - XK_Cabovedot); 920 break; 921 case 3: /* Latin 4 */ 922 /* Assume the KeySym is a legal value (ignore discontinuities) */ 923 if (sym >= XK_Rcedilla && sym <= XK_Tslash) 924 *lower += (XK_rcedilla - XK_Rcedilla); 925 else if (sym >= XK_rcedilla && sym <= XK_tslash) 926 *upper -= (XK_rcedilla - XK_Rcedilla); 927 else if (sym == XK_ENG) 928 *lower = XK_eng; 929 else if (sym == XK_eng) 930 *upper = XK_ENG; 931 else if (sym >= XK_Amacron && sym <= XK_Umacron) 932 *lower += (XK_amacron - XK_Amacron); 933 else if (sym >= XK_amacron && sym <= XK_umacron) 934 *upper -= (XK_amacron - XK_Amacron); 935 break; 936 case 6: /* Cyrillic */ 937 /* Assume the KeySym is a legal value (ignore discontinuities) */ 938 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) 939 *lower -= (XK_Serbian_DJE - XK_Serbian_dje); 940 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) 941 *upper += (XK_Serbian_DJE - XK_Serbian_dje); 942 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) 943 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); 944 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) 945 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); 946 break; 947 case 7: /* Greek */ 948 /* Assume the KeySym is a legal value (ignore discontinuities) */ 949 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) 950 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 951 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && 952 sym != XK_Greek_iotaaccentdieresis && 953 sym != XK_Greek_upsilonaccentdieresis) 954 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 955 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) 956 *lower += (XK_Greek_alpha - XK_Greek_ALPHA); 957 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && 958 sym != XK_Greek_finalsmallsigma) 959 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); 960 break; 961 } 962} 963 964static Bool 965_XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst) 966{ 967 void *tmp = NULL; 968 int i; 969 XkbKeyTypePtr stype = NULL, dtype = NULL; 970 971 /* client map */ 972 if (src->map) { 973 if (!dst->map) { 974 tmp = xcalloc(1, sizeof(XkbClientMapRec)); 975 if (!tmp) 976 return FALSE; 977 dst->map = tmp; 978 } 979 980 if (src->map->syms) { 981 if (src->map->size_syms != dst->map->size_syms) { 982 if (dst->map->syms) 983 tmp = xrealloc(dst->map->syms, 984 src->map->size_syms * sizeof(KeySym)); 985 else 986 tmp = xalloc(src->map->size_syms * sizeof(KeySym)); 987 if (!tmp) 988 return FALSE; 989 dst->map->syms = tmp; 990 991 } 992 memcpy(dst->map->syms, src->map->syms, 993 src->map->size_syms * sizeof(KeySym)); 994 } 995 else { 996 if (dst->map->syms) { 997 xfree(dst->map->syms); 998 dst->map->syms = NULL; 999 } 1000 } 1001 dst->map->num_syms = src->map->num_syms; 1002 dst->map->size_syms = src->map->size_syms; 1003 1004 if (src->map->key_sym_map) { 1005 if (src->max_key_code != dst->max_key_code) { 1006 if (dst->map->key_sym_map) 1007 tmp = xrealloc(dst->map->key_sym_map, 1008 (src->max_key_code + 1) * 1009 sizeof(XkbSymMapRec)); 1010 else 1011 tmp = xalloc((src->max_key_code + 1) * 1012 sizeof(XkbSymMapRec)); 1013 if (!tmp) 1014 return FALSE; 1015 dst->map->key_sym_map = tmp; 1016 } 1017 memcpy(dst->map->key_sym_map, src->map->key_sym_map, 1018 (src->max_key_code + 1) * sizeof(XkbSymMapRec)); 1019 } 1020 else { 1021 if (dst->map->key_sym_map) { 1022 xfree(dst->map->key_sym_map); 1023 dst->map->key_sym_map = NULL; 1024 } 1025 } 1026 1027 if (src->map->types && src->map->num_types) { 1028 if (src->map->num_types > dst->map->size_types || 1029 !dst->map->types || !dst->map->size_types) { 1030 if (dst->map->types && dst->map->size_types) { 1031 tmp = xrealloc(dst->map->types, 1032 src->map->num_types * sizeof(XkbKeyTypeRec)); 1033 if (!tmp) 1034 return FALSE; 1035 dst->map->types = tmp; 1036 bzero(dst->map->types + dst->map->num_types, 1037 (src->map->num_types - dst->map->num_types) * 1038 sizeof(XkbKeyTypeRec)); 1039 } 1040 else { 1041 tmp = xcalloc(src->map->num_types, sizeof(XkbKeyTypeRec)); 1042 if (!tmp) 1043 return FALSE; 1044 dst->map->types = tmp; 1045 } 1046 } 1047 else if (src->map->num_types < dst->map->num_types && 1048 dst->map->types) { 1049 for (i = src->map->num_types, dtype = (dst->map->types + i); 1050 i < dst->map->num_types; i++, dtype++) { 1051 if (dtype->level_names) 1052 xfree(dtype->level_names); 1053 dtype->level_names = NULL; 1054 dtype->num_levels = 0; 1055 if (dtype->map_count) { 1056 if (dtype->map) 1057 xfree(dtype->map); 1058 if (dtype->preserve) 1059 xfree(dtype->preserve); 1060 } 1061 } 1062 } 1063 1064 stype = src->map->types; 1065 dtype = dst->map->types; 1066 for (i = 0; i < src->map->num_types; i++, dtype++, stype++) { 1067 if (stype->num_levels && stype->level_names) { 1068 if (stype->num_levels != dtype->num_levels && 1069 dtype->num_levels && dtype->level_names && 1070 i < dst->map->num_types) { 1071 tmp = xrealloc(dtype->level_names, 1072 stype->num_levels * sizeof(Atom)); 1073 if (!tmp) 1074 continue; 1075 dtype->level_names = tmp; 1076 } 1077 else if (!dtype->num_levels || !dtype->level_names || 1078 i >= dst->map->num_types) { 1079 tmp = xalloc(stype->num_levels * sizeof(Atom)); 1080 if (!tmp) 1081 continue; 1082 dtype->level_names = tmp; 1083 } 1084 dtype->num_levels = stype->num_levels; 1085 memcpy(dtype->level_names, stype->level_names, 1086 stype->num_levels * sizeof(Atom)); 1087 } 1088 else { 1089 if (dtype->num_levels && dtype->level_names && 1090 i < dst->map->num_types) 1091 xfree(dtype->level_names); 1092 dtype->num_levels = 0; 1093 dtype->level_names = NULL; 1094 } 1095 1096 dtype->name = stype->name; 1097 memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec)); 1098 1099 if (stype->map_count) { 1100 if (stype->map) { 1101 if (stype->map_count != dtype->map_count && 1102 dtype->map_count && dtype->map && 1103 i < dst->map->num_types) { 1104 tmp = xrealloc(dtype->map, 1105 stype->map_count * 1106 sizeof(XkbKTMapEntryRec)); 1107 if (!tmp) 1108 return FALSE; 1109 dtype->map = tmp; 1110 } 1111 else if (!dtype->map_count || !dtype->map || 1112 i >= dst->map->num_types) { 1113 tmp = xalloc(stype->map_count * 1114 sizeof(XkbKTMapEntryRec)); 1115 if (!tmp) 1116 return FALSE; 1117 dtype->map = tmp; 1118 } 1119 1120 memcpy(dtype->map, stype->map, 1121 stype->map_count * sizeof(XkbKTMapEntryRec)); 1122 } 1123 else { 1124 if (dtype->map && i < dst->map->num_types) 1125 xfree(dtype->map); 1126 dtype->map = NULL; 1127 } 1128 1129 if (stype->preserve) { 1130 if (stype->map_count != dtype->map_count && 1131 dtype->map_count && dtype->preserve && 1132 i < dst->map->num_types) { 1133 tmp = xrealloc(dtype->preserve, 1134 stype->map_count * 1135 sizeof(XkbModsRec)); 1136 if (!tmp) 1137 return FALSE; 1138 dtype->preserve = tmp; 1139 } 1140 else if (!dtype->preserve || !dtype->map_count || 1141 i >= dst->map->num_types) { 1142 tmp = xalloc(stype->map_count * 1143 sizeof(XkbModsRec)); 1144 if (!tmp) 1145 return FALSE; 1146 dtype->preserve = tmp; 1147 } 1148 1149 memcpy(dtype->preserve, stype->preserve, 1150 stype->map_count * sizeof(XkbModsRec)); 1151 } 1152 else { 1153 if (dtype->preserve && i < dst->map->num_types) 1154 xfree(dtype->preserve); 1155 dtype->preserve = NULL; 1156 } 1157 1158 dtype->map_count = stype->map_count; 1159 } 1160 else { 1161 if (dtype->map_count && i < dst->map->num_types) { 1162 if (dtype->map) 1163 xfree(dtype->map); 1164 if (dtype->preserve) 1165 xfree(dtype->preserve); 1166 } 1167 dtype->map_count = 0; 1168 dtype->map = NULL; 1169 dtype->preserve = NULL; 1170 } 1171 } 1172 1173 dst->map->size_types = src->map->num_types; 1174 dst->map->num_types = src->map->num_types; 1175 } 1176 else { 1177 if (dst->map->types) { 1178 for (i = 0, dtype = dst->map->types; i < dst->map->num_types; 1179 i++, dtype++) { 1180 if (dtype->level_names) 1181 xfree(dtype->level_names); 1182 if (dtype->map && dtype->map_count) 1183 xfree(dtype->map); 1184 if (dtype->preserve && dtype->map_count) 1185 xfree(dtype->preserve); 1186 } 1187 xfree(dst->map->types); 1188 dst->map->types = NULL; 1189 } 1190 dst->map->num_types = 0; 1191 dst->map->size_types = 0; 1192 } 1193 1194 if (src->map->modmap) { 1195 if (src->max_key_code != dst->max_key_code) { 1196 if (dst->map->modmap) 1197 tmp = xrealloc(dst->map->modmap, src->max_key_code + 1); 1198 else 1199 tmp = xalloc(src->max_key_code + 1); 1200 if (!tmp) 1201 return FALSE; 1202 dst->map->modmap = tmp; 1203 } 1204 memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1); 1205 } 1206 else { 1207 if (dst->map->modmap) { 1208 xfree(dst->map->modmap); 1209 dst->map->modmap = NULL; 1210 } 1211 } 1212 } 1213 else { 1214 if (dst->map) 1215 XkbFreeClientMap(dst, XkbAllClientInfoMask, True); 1216 } 1217 1218 return TRUE; 1219} 1220 1221static Bool 1222_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst) 1223{ 1224 void *tmp = NULL; 1225 1226 /* server map */ 1227 if (src->server) { 1228 if (!dst->server) { 1229 tmp = xcalloc(1, sizeof(XkbServerMapRec)); 1230 if (!tmp) 1231 return FALSE; 1232 dst->server = tmp; 1233 } 1234 1235 if (src->server->explicit) { 1236 if (src->max_key_code != dst->max_key_code) { 1237 if (dst->server->explicit) 1238 tmp = xrealloc(dst->server->explicit, src->max_key_code + 1); 1239 else 1240 tmp = xalloc(src->max_key_code + 1); 1241 if (!tmp) 1242 return FALSE; 1243 dst->server->explicit = tmp; 1244 } 1245 memcpy(dst->server->explicit, src->server->explicit, 1246 src->max_key_code + 1); 1247 } 1248 else { 1249 if (dst->server->explicit) { 1250 xfree(dst->server->explicit); 1251 dst->server->explicit = NULL; 1252 } 1253 } 1254 1255 if (src->server->acts) { 1256 if (src->server->size_acts != dst->server->size_acts) { 1257 if (dst->server->acts) 1258 tmp = xrealloc(dst->server->acts, 1259 src->server->size_acts * sizeof(XkbAction)); 1260 else 1261 tmp = xalloc(src->server->size_acts * sizeof(XkbAction)); 1262 if (!tmp) 1263 return FALSE; 1264 dst->server->acts = tmp; 1265 } 1266 memcpy(dst->server->acts, src->server->acts, 1267 src->server->size_acts * sizeof(XkbAction)); 1268 } 1269 else { 1270 if (dst->server->acts) { 1271 xfree(dst->server->acts); 1272 dst->server->acts = NULL; 1273 } 1274 } 1275 dst->server->size_acts = src->server->size_acts; 1276 dst->server->num_acts = src->server->num_acts; 1277 1278 if (src->server->key_acts) { 1279 if (src->max_key_code != dst->max_key_code) { 1280 if (dst->server->key_acts) 1281 tmp = xrealloc(dst->server->key_acts, 1282 (src->max_key_code + 1) * 1283 sizeof(unsigned short)); 1284 else 1285 tmp = xalloc((src->max_key_code + 1) * 1286 sizeof(unsigned short)); 1287 if (!tmp) 1288 return FALSE; 1289 dst->server->key_acts = tmp; 1290 } 1291 memcpy(dst->server->key_acts, src->server->key_acts, 1292 (src->max_key_code + 1) * sizeof(unsigned short)); 1293 } 1294 else { 1295 if (dst->server->key_acts) { 1296 xfree(dst->server->key_acts); 1297 dst->server->key_acts = NULL; 1298 } 1299 } 1300 1301 if (src->server->behaviors) { 1302 if (src->max_key_code != dst->max_key_code) { 1303 if (dst->server->behaviors) 1304 tmp = xrealloc(dst->server->behaviors, 1305 (src->max_key_code + 1) * 1306 sizeof(XkbBehavior)); 1307 else 1308 tmp = xalloc((src->max_key_code + 1) * 1309 sizeof(XkbBehavior)); 1310 if (!tmp) 1311 return FALSE; 1312 dst->server->behaviors = tmp; 1313 } 1314 memcpy(dst->server->behaviors, src->server->behaviors, 1315 (src->max_key_code + 1) * sizeof(XkbBehavior)); 1316 } 1317 else { 1318 if (dst->server->behaviors) { 1319 xfree(dst->server->behaviors); 1320 dst->server->behaviors = NULL; 1321 } 1322 } 1323 1324 memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods); 1325 1326 if (src->server->vmodmap) { 1327 if (src->max_key_code != dst->max_key_code) { 1328 if (dst->server->vmodmap) 1329 tmp = xrealloc(dst->server->vmodmap, 1330 (src->max_key_code + 1) * 1331 sizeof(unsigned short)); 1332 else 1333 tmp = xalloc((src->max_key_code + 1) * 1334 sizeof(unsigned short)); 1335 if (!tmp) 1336 return FALSE; 1337 dst->server->vmodmap = tmp; 1338 } 1339 memcpy(dst->server->vmodmap, src->server->vmodmap, 1340 (src->max_key_code + 1) * sizeof(unsigned short)); 1341 } 1342 else { 1343 if (dst->server->vmodmap) { 1344 xfree(dst->server->vmodmap); 1345 dst->server->vmodmap = NULL; 1346 } 1347 } 1348 } 1349 else { 1350 if (dst->server) 1351 XkbFreeServerMap(dst, XkbAllServerInfoMask, True); 1352 } 1353 1354 return TRUE; 1355} 1356 1357static Bool 1358_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst) 1359{ 1360 void *tmp = NULL; 1361 1362 /* names */ 1363 if (src->names) { 1364 if (!dst->names) { 1365 dst->names = xcalloc(1, sizeof(XkbNamesRec)); 1366 if (!dst->names) 1367 return FALSE; 1368 } 1369 1370 if (src->names->keys) { 1371 if (src->max_key_code != dst->max_key_code) { 1372 if (dst->names->keys) 1373 tmp = xrealloc(dst->names->keys, (src->max_key_code + 1) * 1374 sizeof(XkbKeyNameRec)); 1375 else 1376 tmp = xalloc((src->max_key_code + 1) * 1377 sizeof(XkbKeyNameRec)); 1378 if (!tmp) 1379 return FALSE; 1380 dst->names->keys = tmp; 1381 } 1382 memcpy(dst->names->keys, src->names->keys, 1383 (src->max_key_code + 1) * sizeof(XkbKeyNameRec)); 1384 } 1385 else { 1386 if (dst->names->keys) { 1387 xfree(dst->names->keys); 1388 dst->names->keys = NULL; 1389 } 1390 } 1391 1392 if (src->names->num_key_aliases) { 1393 if (src->names->num_key_aliases != dst->names->num_key_aliases) { 1394 if (dst->names->key_aliases) 1395 tmp = xrealloc(dst->names->key_aliases, 1396 src->names->num_key_aliases * 1397 sizeof(XkbKeyAliasRec)); 1398 else 1399 tmp = xalloc(src->names->num_key_aliases * 1400 sizeof(XkbKeyAliasRec)); 1401 if (!tmp) 1402 return FALSE; 1403 dst->names->key_aliases = tmp; 1404 } 1405 memcpy(dst->names->key_aliases, src->names->key_aliases, 1406 src->names->num_key_aliases * sizeof(XkbKeyAliasRec)); 1407 } 1408 else { 1409 if (dst->names->key_aliases) { 1410 xfree(dst->names->key_aliases); 1411 dst->names->key_aliases = NULL; 1412 } 1413 } 1414 dst->names->num_key_aliases = src->names->num_key_aliases; 1415 1416 if (src->names->num_rg) { 1417 if (src->names->num_rg != dst->names->num_rg) { 1418 if (dst->names->radio_groups) 1419 tmp = xrealloc(dst->names->radio_groups, 1420 src->names->num_rg * sizeof(Atom)); 1421 else 1422 tmp = xalloc(src->names->num_rg * sizeof(Atom)); 1423 if (!tmp) 1424 return FALSE; 1425 dst->names->radio_groups = tmp; 1426 } 1427 memcpy(dst->names->radio_groups, src->names->radio_groups, 1428 src->names->num_rg * sizeof(Atom)); 1429 } 1430 else { 1431 if (dst->names->radio_groups) 1432 xfree(dst->names->radio_groups); 1433 } 1434 dst->names->num_rg = src->names->num_rg; 1435 1436 dst->names->keycodes = src->names->keycodes; 1437 dst->names->geometry = src->names->geometry; 1438 dst->names->symbols = src->names->symbols; 1439 dst->names->types = src->names->types; 1440 dst->names->compat = src->names->compat; 1441 dst->names->phys_symbols = src->names->phys_symbols; 1442 1443 memcpy(dst->names->vmods, src->names->vmods, 1444 XkbNumVirtualMods * sizeof(Atom)); 1445 memcpy(dst->names->indicators, src->names->indicators, 1446 XkbNumIndicators * sizeof(Atom)); 1447 memcpy(dst->names->groups, src->names->groups, 1448 XkbNumKbdGroups * sizeof(Atom)); 1449 } 1450 else { 1451 if (dst->names) 1452 XkbFreeNames(dst, XkbAllNamesMask, True); 1453 } 1454 1455 return TRUE; 1456} 1457 1458static Bool 1459_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst) 1460{ 1461 void *tmp = NULL; 1462 1463 /* compat */ 1464 if (src->compat) { 1465 if (!dst->compat) { 1466 dst->compat = xcalloc(1, sizeof(XkbCompatMapRec)); 1467 if (!dst->compat) 1468 return FALSE; 1469 } 1470 1471 if (src->compat->sym_interpret && src->compat->num_si) { 1472 if (src->compat->num_si != dst->compat->size_si) { 1473 if (dst->compat->sym_interpret) 1474 tmp = xrealloc(dst->compat->sym_interpret, 1475 src->compat->num_si * 1476 sizeof(XkbSymInterpretRec)); 1477 else 1478 tmp = xalloc(src->compat->num_si * 1479 sizeof(XkbSymInterpretRec)); 1480 if (!tmp) 1481 return FALSE; 1482 dst->compat->sym_interpret = tmp; 1483 } 1484 memcpy(dst->compat->sym_interpret, src->compat->sym_interpret, 1485 src->compat->num_si * sizeof(XkbSymInterpretRec)); 1486 1487 dst->compat->num_si = src->compat->num_si; 1488 dst->compat->size_si = src->compat->num_si; 1489 } 1490 else { 1491 if (dst->compat->sym_interpret && dst->compat->size_si) 1492 xfree(dst->compat->sym_interpret); 1493 1494 dst->compat->sym_interpret = NULL; 1495 dst->compat->num_si = 0; 1496 dst->compat->size_si = 0; 1497 } 1498 1499 memcpy(dst->compat->groups, src->compat->groups, 1500 XkbNumKbdGroups * sizeof(XkbModsRec)); 1501 } 1502 else { 1503 if (dst->compat) 1504 XkbFreeCompatMap(dst, XkbAllCompatMask, True); 1505 } 1506 1507 return TRUE; 1508} 1509 1510static Bool 1511_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst) 1512{ 1513 void *tmp = NULL; 1514 int i = 0, j = 0, k = 0; 1515 XkbColorPtr scolor = NULL, dcolor = NULL; 1516 XkbDoodadPtr sdoodad = NULL, ddoodad = NULL; 1517 XkbOutlinePtr soutline = NULL, doutline = NULL; 1518 XkbPropertyPtr sprop = NULL, dprop = NULL; 1519 XkbRowPtr srow = NULL, drow = NULL; 1520 XkbSectionPtr ssection = NULL, dsection = NULL; 1521 XkbShapePtr sshape = NULL, dshape = NULL; 1522 1523 /* geometry */ 1524 if (src->geom) { 1525 if (!dst->geom) { 1526 dst->geom = xcalloc(sizeof(XkbGeometryRec), 1); 1527 if (!dst->geom) 1528 return FALSE; 1529 } 1530 1531 /* properties */ 1532 if (src->geom->num_properties) { 1533 if (src->geom->num_properties != dst->geom->sz_properties) { 1534 /* If we've got more properties in the destination than 1535 * the source, run through and free all the excess ones 1536 * first. */ 1537 if (src->geom->num_properties < dst->geom->sz_properties) { 1538 for (i = src->geom->num_properties, 1539 dprop = dst->geom->properties + i; 1540 i < dst->geom->num_properties; 1541 i++, dprop++) { 1542 xfree(dprop->name); 1543 xfree(dprop->value); 1544 } 1545 } 1546 1547 if (dst->geom->sz_properties) 1548 tmp = xrealloc(dst->geom->properties, 1549 src->geom->num_properties * 1550 sizeof(XkbPropertyRec)); 1551 else 1552 tmp = xalloc(src->geom->num_properties * 1553 sizeof(XkbPropertyRec)); 1554 if (!tmp) 1555 return FALSE; 1556 dst->geom->properties = tmp; 1557 } 1558 1559 /* We don't set num_properties as we need it to try and avoid 1560 * too much reallocing. */ 1561 dst->geom->sz_properties = src->geom->num_properties; 1562 1563 if (dst->geom->sz_properties > dst->geom->num_properties) { 1564 bzero(dst->geom->properties + dst->geom->num_properties, 1565 (dst->geom->sz_properties - dst->geom->num_properties) * 1566 sizeof(XkbPropertyRec)); 1567 } 1568 1569 for (i = 0, 1570 sprop = src->geom->properties, 1571 dprop = dst->geom->properties; 1572 i < src->geom->num_properties; 1573 i++, sprop++, dprop++) { 1574 if (i < dst->geom->num_properties) { 1575 if (strlen(sprop->name) != strlen(dprop->name)) { 1576 tmp = xrealloc(dprop->name, strlen(sprop->name) + 1); 1577 if (!tmp) 1578 return FALSE; 1579 dprop->name = tmp; 1580 } 1581 if (strlen(sprop->value) != strlen(dprop->value)) { 1582 tmp = xrealloc(dprop->value, strlen(sprop->value) + 1); 1583 if (!tmp) 1584 return FALSE; 1585 dprop->value = tmp; 1586 } 1587 strcpy(dprop->name, sprop->name); 1588 strcpy(dprop->value, sprop->value); 1589 } 1590 else { 1591 dprop->name = xstrdup(sprop->name); 1592 dprop->value = xstrdup(sprop->value); 1593 } 1594 } 1595 1596 /* ... which is already src->geom->num_properties. */ 1597 dst->geom->num_properties = dst->geom->sz_properties; 1598 } 1599 else { 1600 if (dst->geom->sz_properties) { 1601 for (i = 0, dprop = dst->geom->properties; 1602 i < dst->geom->num_properties; 1603 i++, dprop++) { 1604 xfree(dprop->name); 1605 xfree(dprop->value); 1606 } 1607 xfree(dst->geom->properties); 1608 dst->geom->properties = NULL; 1609 } 1610 1611 dst->geom->num_properties = 0; 1612 dst->geom->sz_properties = 0; 1613 } 1614 1615 /* colors */ 1616 if (src->geom->num_colors) { 1617 if (src->geom->num_colors != dst->geom->sz_colors) { 1618 if (src->geom->num_colors < dst->geom->sz_colors) { 1619 for (i = src->geom->num_colors, 1620 dcolor = dst->geom->colors + i; 1621 i < dst->geom->num_colors; 1622 i++, dcolor++) { 1623 xfree(dcolor->spec); 1624 } 1625 } 1626 1627 if (dst->geom->sz_colors) 1628 tmp = xrealloc(dst->geom->colors, 1629 src->geom->num_colors * 1630 sizeof(XkbColorRec)); 1631 else 1632 tmp = xalloc(src->geom->num_colors * 1633 sizeof(XkbColorRec)); 1634 if (!tmp) 1635 return FALSE; 1636 dst->geom->colors = tmp; 1637 } 1638 1639 dst->geom->sz_colors = src->geom->num_colors; 1640 1641 if (dst->geom->sz_colors > dst->geom->num_colors) { 1642 bzero(dst->geom->colors + dst->geom->num_colors, 1643 (dst->geom->sz_colors - dst->geom->num_colors) * 1644 sizeof(XkbColorRec)); 1645 } 1646 1647 for (i = 0, 1648 scolor = src->geom->colors, 1649 dcolor = dst->geom->colors; 1650 i < src->geom->num_colors; 1651 i++, scolor++, dcolor++) { 1652 if (i < dst->geom->num_colors) { 1653 if (strlen(scolor->spec) != strlen(dcolor->spec)) { 1654 tmp = xrealloc(dcolor->spec, strlen(scolor->spec) + 1); 1655 if (!tmp) 1656 return FALSE; 1657 dcolor->spec = tmp; 1658 } 1659 strcpy(dcolor->spec, scolor->spec); 1660 } 1661 else { 1662 dcolor->spec = xstrdup(scolor->spec); 1663 } 1664 } 1665 1666 dst->geom->num_colors = dst->geom->sz_colors; 1667 } 1668 else { 1669 if (dst->geom->sz_colors) { 1670 for (i = 0, dcolor = dst->geom->colors; 1671 i < dst->geom->num_colors; 1672 i++, dcolor++) { 1673 xfree(dcolor->spec); 1674 } 1675 xfree(dst->geom->colors); 1676 dst->geom->colors = NULL; 1677 } 1678 1679 dst->geom->num_colors = 0; 1680 dst->geom->sz_colors = 0; 1681 } 1682 1683 /* shapes */ 1684 /* shapes break down into outlines, which break down into points. */ 1685 if (dst->geom->num_shapes) { 1686 for (i = 0, dshape = dst->geom->shapes; 1687 i < dst->geom->num_shapes; 1688 i++, dshape++) { 1689 for (j = 0, doutline = dshape->outlines; 1690 j < dshape->num_outlines; 1691 j++, doutline++) { 1692 if (doutline->sz_points) 1693 xfree(doutline->points); 1694 } 1695 1696 if (dshape->sz_outlines) { 1697 xfree(dshape->outlines); 1698 dshape->outlines = NULL; 1699 } 1700 1701 dshape->num_outlines = 0; 1702 dshape->sz_outlines = 0; 1703 } 1704 } 1705 1706 if (src->geom->num_shapes) { 1707 tmp = xcalloc(src->geom->num_shapes, sizeof(XkbShapeRec)); 1708 if (!tmp) 1709 return FALSE; 1710 dst->geom->shapes = tmp; 1711 1712 for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes; 1713 i < src->geom->num_shapes; 1714 i++, sshape++, dshape++) { 1715 if (sshape->num_outlines) { 1716 tmp = xcalloc(sshape->num_outlines, sizeof(XkbOutlineRec)); 1717 if (!tmp) 1718 return FALSE; 1719 dshape->outlines = tmp; 1720 1721 for (j = 0, 1722 soutline = sshape->outlines, 1723 doutline = dshape->outlines; 1724 j < sshape->num_outlines; 1725 j++, soutline++, doutline++) { 1726 if (soutline->num_points) { 1727 tmp = xalloc(soutline->num_points * 1728 sizeof(XkbPointRec)); 1729 if (!tmp) 1730 return FALSE; 1731 doutline->points = tmp; 1732 1733 memcpy(doutline->points, soutline->points, 1734 soutline->num_points * sizeof(XkbPointRec)); 1735 } 1736 1737 doutline->num_points = soutline->num_points; 1738 doutline->sz_points = soutline->num_points; 1739 } 1740 } 1741 1742 dshape->num_outlines = sshape->num_outlines; 1743 dshape->sz_outlines = sshape->num_outlines; 1744 } 1745 1746 dst->geom->num_shapes = src->geom->num_shapes; 1747 dst->geom->sz_shapes = src->geom->num_shapes; 1748 } 1749 else { 1750 if (dst->geom->sz_shapes) { 1751 xfree(dst->geom->shapes); 1752 } 1753 dst->geom->shapes = NULL; 1754 dst->geom->num_shapes = 0; 1755 dst->geom->sz_shapes = 0; 1756 } 1757 1758 /* sections */ 1759 /* sections break down into doodads, and also into rows, which break 1760 * down into keys. */ 1761 if (dst->geom->num_sections) { 1762 for (i = 0, dsection = dst->geom->sections; 1763 i < dst->geom->num_sections; 1764 i++, dsection++) { 1765 for (j = 0, drow = dsection->rows; 1766 j < dsection->num_rows; 1767 j++, drow++) { 1768 if (drow->num_keys) 1769 xfree(drow->keys); 1770 } 1771 1772 if (dsection->num_rows) 1773 xfree(dsection->rows); 1774 1775 /* cut and waste from geom/doodad below. */ 1776 for (j = 0, ddoodad = dsection->doodads; 1777 j < dsection->num_doodads; 1778 j++, ddoodad++) { 1779 if (ddoodad->any.type == XkbTextDoodad) { 1780 if (ddoodad->text.text) { 1781 xfree(ddoodad->text.text); 1782 ddoodad->text.text = NULL; 1783 } 1784 if (ddoodad->text.font) { 1785 xfree(ddoodad->text.font); 1786 ddoodad->text.font = NULL; 1787 } 1788 } 1789 else if (ddoodad->any.type == XkbLogoDoodad) { 1790 if (ddoodad->logo.logo_name) { 1791 xfree(ddoodad->logo.logo_name); 1792 ddoodad->logo.logo_name = NULL; 1793 } 1794 } 1795 } 1796 1797 if (dsection->num_doodads) 1798 xfree(dsection->doodads); 1799 } 1800 1801 dst->geom->num_sections = 0; 1802 dst->geom->sections = NULL; 1803 } 1804 1805 if (src->geom->num_sections) { 1806 if (dst->geom->sz_sections) 1807 tmp = xrealloc(dst->geom->sections, 1808 src->geom->num_sections * 1809 sizeof(XkbSectionRec)); 1810 else 1811 tmp = xalloc(src->geom->num_sections * sizeof(XkbSectionRec)); 1812 if (!tmp) 1813 return FALSE; 1814 memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec)); 1815 dst->geom->sections = tmp; 1816 dst->geom->num_sections = src->geom->num_sections; 1817 dst->geom->sz_sections = src->geom->num_sections; 1818 1819 for (i = 0, 1820 ssection = src->geom->sections, 1821 dsection = dst->geom->sections; 1822 i < src->geom->num_sections; 1823 i++, ssection++, dsection++) { 1824 *dsection = *ssection; 1825 if (ssection->num_rows) { 1826 tmp = xcalloc(ssection->num_rows, sizeof(XkbRowRec)); 1827 if (!tmp) 1828 return FALSE; 1829 dsection->rows = tmp; 1830 } 1831 dsection->num_rows = ssection->num_rows; 1832 dsection->sz_rows = ssection->num_rows; 1833 1834 for (j = 0, srow = ssection->rows, drow = dsection->rows; 1835 j < ssection->num_rows; 1836 j++, srow++, drow++) { 1837 if (srow->num_keys) { 1838 tmp = xalloc(srow->num_keys * sizeof(XkbKeyRec)); 1839 if (!tmp) 1840 return FALSE; 1841 drow->keys = tmp; 1842 memcpy(drow->keys, srow->keys, 1843 srow->num_keys * sizeof(XkbKeyRec)); 1844 } 1845 drow->num_keys = srow->num_keys; 1846 drow->sz_keys = srow->num_keys; 1847 } 1848 1849 if (ssection->num_doodads) { 1850 tmp = xcalloc(ssection->num_doodads, sizeof(XkbDoodadRec)); 1851 if (!tmp) 1852 return FALSE; 1853 dsection->doodads = tmp; 1854 } 1855 else { 1856 dsection->doodads = NULL; 1857 } 1858 1859 dsection->sz_doodads = ssection->num_doodads; 1860 for (k = 0, 1861 sdoodad = ssection->doodads, 1862 ddoodad = dsection->doodads; 1863 k < ssection->num_doodads; 1864 k++, sdoodad++, ddoodad++) { 1865 if (sdoodad->any.type == XkbTextDoodad) { 1866 if (sdoodad->text.text) 1867 ddoodad->text.text = 1868 xstrdup(sdoodad->text.text); 1869 if (sdoodad->text.font) 1870 ddoodad->text.font = 1871 xstrdup(sdoodad->text.font); 1872 } 1873 else if (sdoodad->any.type == XkbLogoDoodad) { 1874 if (sdoodad->logo.logo_name) 1875 ddoodad->logo.logo_name = 1876 xstrdup(sdoodad->logo.logo_name); 1877 } 1878 ddoodad->any.type = sdoodad->any.type; 1879 } 1880 dsection->overlays = NULL; 1881 dsection->sz_overlays = 0; 1882 dsection->num_overlays = 0; 1883 } 1884 } 1885 else { 1886 if (dst->geom->sz_sections) { 1887 xfree(dst->geom->sections); 1888 } 1889 1890 dst->geom->sections = NULL; 1891 dst->geom->num_sections = 0; 1892 dst->geom->sz_sections = 0; 1893 } 1894 1895 /* doodads */ 1896 if (dst->geom->num_doodads) { 1897 for (i = src->geom->num_doodads, 1898 ddoodad = dst->geom->doodads + 1899 src->geom->num_doodads; 1900 i < dst->geom->num_doodads; 1901 i++, ddoodad++) { 1902 if (ddoodad->any.type == XkbTextDoodad) { 1903 if (ddoodad->text.text) { 1904 xfree(ddoodad->text.text); 1905 ddoodad->text.text = NULL; 1906 } 1907 if (ddoodad->text.font) { 1908 xfree(ddoodad->text.font); 1909 ddoodad->text.font = NULL; 1910 } 1911 } 1912 else if (ddoodad->any.type == XkbLogoDoodad) { 1913 if (ddoodad->logo.logo_name) { 1914 xfree(ddoodad->logo.logo_name); 1915 ddoodad->logo.logo_name = NULL; 1916 } 1917 } 1918 } 1919 dst->geom->num_doodads = 0; 1920 dst->geom->doodads = NULL; 1921 } 1922 1923 if (src->geom->num_doodads) { 1924 if (dst->geom->sz_doodads) 1925 tmp = xrealloc(dst->geom->doodads, 1926 src->geom->num_doodads * 1927 sizeof(XkbDoodadRec)); 1928 else 1929 tmp = xalloc(src->geom->num_doodads * 1930 sizeof(XkbDoodadRec)); 1931 if (!tmp) 1932 return FALSE; 1933 memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec)); 1934 dst->geom->doodads = tmp; 1935 1936 dst->geom->sz_doodads = src->geom->num_doodads; 1937 1938 for (i = 0, 1939 sdoodad = src->geom->doodads, 1940 ddoodad = dst->geom->doodads; 1941 i < src->geom->num_doodads; 1942 i++, sdoodad++, ddoodad++) { 1943 ddoodad->any.type = sdoodad->any.type; 1944 if (sdoodad->any.type == XkbTextDoodad) { 1945 if (sdoodad->text.text) 1946 ddoodad->text.text = xstrdup(sdoodad->text.text); 1947 if (sdoodad->text.font) 1948 ddoodad->text.font = xstrdup(sdoodad->text.font); 1949 } 1950 else if (sdoodad->any.type == XkbLogoDoodad) { 1951 if (sdoodad->logo.logo_name) 1952 ddoodad->logo.logo_name = 1953 xstrdup(sdoodad->logo.logo_name); 1954 } 1955 } 1956 1957 dst->geom->num_doodads = dst->geom->sz_doodads; 1958 } 1959 else { 1960 if (dst->geom->sz_doodads) { 1961 xfree(dst->geom->doodads); 1962 } 1963 1964 dst->geom->doodads = NULL; 1965 dst->geom->num_doodads = 0; 1966 dst->geom->sz_doodads = 0; 1967 } 1968 1969 /* key aliases */ 1970 if (src->geom->num_key_aliases) { 1971 if (src->geom->num_key_aliases != dst->geom->sz_key_aliases) { 1972 if (dst->geom->sz_key_aliases) 1973 tmp = xrealloc(dst->geom->key_aliases, 1974 src->geom->num_key_aliases * 1975 2 * XkbKeyNameLength); 1976 else 1977 tmp = xalloc(src->geom->num_key_aliases * 1978 2 * XkbKeyNameLength); 1979 if (!tmp) 1980 return FALSE; 1981 dst->geom->key_aliases = tmp; 1982 1983 dst->geom->sz_key_aliases = src->geom->num_key_aliases; 1984 } 1985 1986 memcpy(dst->geom->key_aliases, src->geom->key_aliases, 1987 src->geom->num_key_aliases * 2 * XkbKeyNameLength); 1988 1989 dst->geom->num_key_aliases = dst->geom->sz_key_aliases; 1990 } 1991 else { 1992 if (dst->geom->key_aliases) { 1993 xfree(dst->geom->key_aliases); 1994 } 1995 dst->geom->key_aliases = NULL; 1996 dst->geom->num_key_aliases = 0; 1997 dst->geom->sz_key_aliases = 0; 1998 } 1999 2000 /* font */ 2001 if (src->geom->label_font) { 2002 if (!dst->geom->label_font) { 2003 tmp = xalloc(strlen(src->geom->label_font)); 2004 if (!tmp) 2005 return FALSE; 2006 dst->geom->label_font = tmp; 2007 } 2008 else if (strlen(src->geom->label_font) != 2009 strlen(dst->geom->label_font)) { 2010 tmp = xrealloc(dst->geom->label_font, 2011 strlen(src->geom->label_font)); 2012 if (!tmp) 2013 return FALSE; 2014 dst->geom->label_font = tmp; 2015 } 2016 2017 strcpy(dst->geom->label_font, src->geom->label_font); 2018 i = XkbGeomColorIndex(src->geom, src->geom->label_color); 2019 dst->geom->label_color = &(dst->geom->colors[i]); 2020 i = XkbGeomColorIndex(src->geom, src->geom->base_color); 2021 dst->geom->base_color = &(dst->geom->colors[i]); 2022 } 2023 else { 2024 if (dst->geom->label_font) { 2025 xfree(dst->geom->label_font); 2026 } 2027 dst->geom->label_font = NULL; 2028 dst->geom->label_color = NULL; 2029 dst->geom->base_color = NULL; 2030 } 2031 2032 dst->geom->name = src->geom->name; 2033 dst->geom->width_mm = src->geom->width_mm; 2034 dst->geom->height_mm = src->geom->height_mm; 2035 } 2036 else 2037 { 2038 if (dst->geom) { 2039 /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */ 2040 XkbFreeGeometry(dst->geom, XkbGeomAllMask, True); 2041 dst->geom = NULL; 2042 } 2043 } 2044 2045 return TRUE; 2046} 2047 2048static Bool 2049_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst) 2050{ 2051 /* indicators */ 2052 if (src->indicators) { 2053 if (!dst->indicators) { 2054 dst->indicators = xalloc(sizeof(XkbIndicatorRec)); 2055 if (!dst->indicators) 2056 return FALSE; 2057 } 2058 memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec)); 2059 } 2060 else { 2061 if (dst->indicators) { 2062 xfree(dst->indicators); 2063 dst->indicators = NULL; 2064 } 2065 } 2066 return TRUE; 2067} 2068 2069static Bool 2070_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst) 2071{ 2072 /* controls */ 2073 if (src->ctrls) { 2074 if (!dst->ctrls) { 2075 dst->ctrls = xalloc(sizeof(XkbControlsRec)); 2076 if (!dst->ctrls) 2077 return FALSE; 2078 } 2079 memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec)); 2080 } 2081 else { 2082 if (dst->ctrls) { 2083 xfree(dst->ctrls); 2084 dst->ctrls = NULL; 2085 } 2086 } 2087 return TRUE; 2088} 2089 2090/** 2091 * Copy an XKB map from src to dst, reallocating when necessary: if some 2092 * map components are present in one, but not in the other, the destination 2093 * components will be allocated or freed as necessary. 2094 * 2095 * Basic map consistency is assumed on both sides, so maps with random 2096 * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19) 2097 * _will_ cause failures. You've been warned. 2098 * 2099 * Returns TRUE on success, or FALSE on failure. If this function fails, 2100 * dst may be in an inconsistent state: all its pointers are guaranteed 2101 * to remain valid, but part of the map may be from src and part from dst. 2102 * 2103 */ 2104 2105Bool 2106XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) 2107{ 2108 DeviceIntPtr pDev = NULL, tmpDev = NULL; 2109 xkbMapNotify mn; 2110 xkbNewKeyboardNotify nkn; 2111 2112 if (!src || !dst || src == dst) 2113 return FALSE; 2114 2115 if (!_XkbCopyClientMap(src, dst)) 2116 return FALSE; 2117 if (!_XkbCopyServerMap(src, dst)) 2118 return FALSE; 2119 if (!_XkbCopyIndicators(src, dst)) 2120 return FALSE; 2121 if (!_XkbCopyControls(src, dst)) 2122 return FALSE; 2123 if (!_XkbCopyNames(src, dst)) 2124 return FALSE; 2125 if (!_XkbCopyCompat(src, dst)) 2126 return FALSE; 2127 if (!_XkbCopyGeom(src, dst)) 2128 return FALSE; 2129 2130 if (inputInfo.keyboard->key->xkbInfo && 2131 inputInfo.keyboard->key->xkbInfo->desc == dst) { 2132 pDev = inputInfo.keyboard; 2133 } 2134 else { 2135 for (tmpDev = inputInfo.devices; tmpDev && !pDev; 2136 tmpDev = tmpDev->next) { 2137 if (tmpDev->key && tmpDev->key->xkbInfo && 2138 tmpDev->key->xkbInfo->desc == dst) { 2139 pDev = tmpDev; 2140 break; 2141 } 2142 } 2143 for (tmpDev = inputInfo.off_devices; tmpDev && !pDev; 2144 tmpDev = tmpDev->next) { 2145 if (tmpDev->key && tmpDev->key->xkbInfo && 2146 tmpDev->key->xkbInfo->desc == dst) { 2147 pDev = tmpDev; 2148 break; 2149 } 2150 } 2151 } 2152 2153 if (sendNotifies) { 2154 if (!pDev) { 2155 ErrorF("[xkb] XkbCopyKeymap: asked for notifies, but can't find device!\n"); 2156 } 2157 else { 2158 /* send NewKeyboardNotify if the keycode range changed, else 2159 * just MapNotify. we also need to send NKN if the geometry 2160 * changed (obviously ...). */ 2161 if ((src->min_key_code != dst->min_key_code || 2162 src->max_key_code != dst->max_key_code)) { 2163 nkn.oldMinKeyCode = dst->min_key_code; 2164 nkn.oldMaxKeyCode = dst->max_key_code; 2165 nkn.deviceID = nkn.oldDeviceID = pDev->id; 2166 nkn.minKeyCode = src->min_key_code; 2167 nkn.maxKeyCode = src->max_key_code; 2168 nkn.requestMajor = XkbReqCode; 2169 nkn.requestMinor = X_kbSetMap; /* XXX bare-faced lie */ 2170 nkn.changed = XkbAllNewKeyboardEventsMask; 2171 XkbSendNewKeyboardNotify(pDev, &nkn); 2172 } else 2173 { 2174 mn.deviceID = pDev->id; 2175 mn.minKeyCode = src->min_key_code; 2176 mn.maxKeyCode = src->max_key_code; 2177 mn.firstType = 0; 2178 mn.nTypes = src->map->num_types; 2179 mn.firstKeySym = src->min_key_code; 2180 mn.nKeySyms = XkbNumKeys(src); 2181 mn.firstKeyAct = src->min_key_code; 2182 mn.nKeyActs = XkbNumKeys(src); 2183 /* Cargo-culted from ProcXkbGetMap. */ 2184 mn.firstKeyBehavior = src->min_key_code; 2185 mn.nKeyBehaviors = XkbNumKeys(src); 2186 mn.firstKeyExplicit = src->min_key_code; 2187 mn.nKeyExplicit = XkbNumKeys(src); 2188 mn.firstModMapKey = src->min_key_code; 2189 mn.nModMapKeys = XkbNumKeys(src); 2190 mn.firstVModMapKey = src->min_key_code; 2191 mn.nVModMapKeys = XkbNumKeys(src); 2192 mn.virtualMods = ~0; /* ??? */ 2193 mn.changed = XkbAllMapComponentsMask; 2194 XkbSendMapNotify(pDev, &mn); 2195 } 2196 } 2197 } 2198 2199 dst->min_key_code = src->min_key_code; 2200 dst->max_key_code = src->max_key_code; 2201 2202 return TRUE; 2203} 2204