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