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