xkbUtils.c revision f2346221
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] = {NoSymbol}, *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_Cyrillic_DZHE) 906 *lower -= (XK_Serbian_DJE - XK_Serbian_dje); 907 else if (sym >= XK_Serbian_dje && sym <= XK_Cyrillic_dzhe) 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 int gap; 937 XkbKeyTypePtr stype = NULL, dtype = NULL; 938 939 /* client map */ 940 if (src->map) { 941 if (!dst->map) { 942 tmp = calloc(1, sizeof(XkbClientMapRec)); 943 if (!tmp) 944 return FALSE; 945 dst->map = tmp; 946 } 947 948 if (src->map->syms) { 949 if (src->map->size_syms != dst->map->size_syms) { 950 tmp = reallocarray(dst->map->syms, 951 src->map->size_syms, sizeof(KeySym)); 952 if (!tmp) 953 return FALSE; 954 dst->map->syms = tmp; 955 956 } 957 memcpy(dst->map->syms, src->map->syms, 958 src->map->size_syms * sizeof(KeySym)); 959 } 960 else { 961 free(dst->map->syms); 962 dst->map->syms = NULL; 963 } 964 dst->map->num_syms = src->map->num_syms; 965 dst->map->size_syms = src->map->size_syms; 966 gap = MAP_LENGTH - (src->max_key_code + 1); 967 968 if (src->map->key_sym_map) { 969 if (!dst->map->key_sym_map) { 970 tmp = reallocarray(dst->map->key_sym_map, 971 MAP_LENGTH, sizeof(XkbSymMapRec)); 972 if (!tmp) 973 return FALSE; 974 dst->map->key_sym_map = tmp; 975 } 976 if (gap > 0) { 977 memset((char *) &dst->map->key_sym_map[gap], 0, 978 gap * sizeof(XkbSymMapRec)); 979 } 980 memcpy(dst->map->key_sym_map, src->map->key_sym_map, 981 (src->max_key_code + 1) * sizeof(XkbSymMapRec)); 982 } 983 else { 984 free(dst->map->key_sym_map); 985 dst->map->key_sym_map = NULL; 986 } 987 988 if (src->map->types && src->map->num_types) { 989 if (src->map->num_types > dst->map->size_types || 990 !dst->map->types || !dst->map->size_types) { 991 if (dst->map->types && dst->map->size_types) { 992 tmp = reallocarray(dst->map->types, src->map->num_types, 993 sizeof(XkbKeyTypeRec)); 994 if (!tmp) 995 return FALSE; 996 dst->map->types = tmp; 997 memset(dst->map->types + dst->map->num_types, 0, 998 (src->map->num_types - dst->map->num_types) * 999 sizeof(XkbKeyTypeRec)); 1000 } 1001 else { 1002 tmp = calloc(src->map->num_types, sizeof(XkbKeyTypeRec)); 1003 if (!tmp) 1004 return FALSE; 1005 dst->map->types = tmp; 1006 } 1007 } 1008 else if (src->map->num_types < dst->map->num_types && 1009 dst->map->types) { 1010 for (i = src->map->num_types, dtype = (dst->map->types + i); 1011 i < dst->map->num_types; i++, dtype++) { 1012 free(dtype->level_names); 1013 dtype->level_names = NULL; 1014 dtype->num_levels = 0; 1015 if (dtype->map_count) { 1016 free(dtype->map); 1017 free(dtype->preserve); 1018 } 1019 } 1020 } 1021 1022 stype = src->map->types; 1023 dtype = dst->map->types; 1024 for (i = 0; i < src->map->num_types; i++, dtype++, stype++) { 1025 if (stype->num_levels && stype->level_names) { 1026 if (stype->num_levels != dtype->num_levels && 1027 dtype->num_levels && dtype->level_names && 1028 i < dst->map->num_types) { 1029 tmp = reallocarray(dtype->level_names, 1030 stype->num_levels, sizeof(Atom)); 1031 if (!tmp) 1032 continue; 1033 dtype->level_names = tmp; 1034 } 1035 else if (!dtype->num_levels || !dtype->level_names || 1036 i >= dst->map->num_types) { 1037 tmp = malloc(stype->num_levels * sizeof(Atom)); 1038 if (!tmp) 1039 continue; 1040 dtype->level_names = tmp; 1041 } 1042 dtype->num_levels = stype->num_levels; 1043 memcpy(dtype->level_names, stype->level_names, 1044 stype->num_levels * sizeof(Atom)); 1045 } 1046 else { 1047 if (dtype->num_levels && dtype->level_names && 1048 i < dst->map->num_types) 1049 free(dtype->level_names); 1050 dtype->num_levels = 0; 1051 dtype->level_names = NULL; 1052 } 1053 1054 dtype->name = stype->name; 1055 memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec)); 1056 1057 if (stype->map_count) { 1058 if (stype->map) { 1059 if (stype->map_count != dtype->map_count && 1060 dtype->map_count && dtype->map && 1061 i < dst->map->num_types) { 1062 tmp = reallocarray(dtype->map, 1063 stype->map_count, 1064 sizeof(XkbKTMapEntryRec)); 1065 if (!tmp) 1066 return FALSE; 1067 dtype->map = tmp; 1068 } 1069 else if (!dtype->map_count || !dtype->map || 1070 i >= dst->map->num_types) { 1071 tmp = xallocarray(stype->map_count, 1072 sizeof(XkbKTMapEntryRec)); 1073 if (!tmp) 1074 return FALSE; 1075 dtype->map = tmp; 1076 } 1077 1078 memcpy(dtype->map, stype->map, 1079 stype->map_count * sizeof(XkbKTMapEntryRec)); 1080 } 1081 else { 1082 if (dtype->map && i < dst->map->num_types) 1083 free(dtype->map); 1084 dtype->map = NULL; 1085 } 1086 1087 if (stype->preserve) { 1088 if (stype->map_count != dtype->map_count && 1089 dtype->map_count && dtype->preserve && 1090 i < dst->map->num_types) { 1091 tmp = reallocarray(dtype->preserve, 1092 stype->map_count, 1093 sizeof(XkbModsRec)); 1094 if (!tmp) 1095 return FALSE; 1096 dtype->preserve = tmp; 1097 } 1098 else if (!dtype->preserve || !dtype->map_count || 1099 i >= dst->map->num_types) { 1100 tmp = xallocarray(stype->map_count, 1101 sizeof(XkbModsRec)); 1102 if (!tmp) 1103 return FALSE; 1104 dtype->preserve = tmp; 1105 } 1106 1107 memcpy(dtype->preserve, stype->preserve, 1108 stype->map_count * sizeof(XkbModsRec)); 1109 } 1110 else { 1111 if (dtype->preserve && i < dst->map->num_types) 1112 free(dtype->preserve); 1113 dtype->preserve = NULL; 1114 } 1115 1116 dtype->map_count = stype->map_count; 1117 } 1118 else { 1119 if (dtype->map_count && i < dst->map->num_types) { 1120 free(dtype->map); 1121 free(dtype->preserve); 1122 } 1123 dtype->map_count = 0; 1124 dtype->map = NULL; 1125 dtype->preserve = NULL; 1126 } 1127 } 1128 1129 dst->map->size_types = src->map->num_types; 1130 dst->map->num_types = src->map->num_types; 1131 } 1132 else { 1133 if (dst->map->types) { 1134 for (i = 0, dtype = dst->map->types; i < dst->map->num_types; 1135 i++, dtype++) { 1136 free(dtype->level_names); 1137 if (dtype->map && dtype->map_count) 1138 free(dtype->map); 1139 if (dtype->preserve && dtype->map_count) 1140 free(dtype->preserve); 1141 } 1142 } 1143 free(dst->map->types); 1144 dst->map->types = NULL; 1145 dst->map->num_types = 0; 1146 dst->map->size_types = 0; 1147 } 1148 1149 if (src->map->modmap) { 1150 if (!dst->map->modmap) { 1151 tmp = realloc(dst->map->modmap, MAP_LENGTH); 1152 if (!tmp) 1153 return FALSE; 1154 dst->map->modmap = tmp; 1155 } 1156 if (gap > 0) { 1157 memset(dst->map->modmap + gap, 0, gap); 1158 } 1159 memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1); 1160 } 1161 else { 1162 free(dst->map->modmap); 1163 dst->map->modmap = NULL; 1164 } 1165 } 1166 else { 1167 if (dst->map) 1168 XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE); 1169 } 1170 1171 return TRUE; 1172} 1173 1174static Bool 1175_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst) 1176{ 1177 void *tmp = NULL; 1178 int gap; 1179 1180 /* server map */ 1181 if (src->server) { 1182 if (!dst->server) { 1183 tmp = calloc(1, sizeof(XkbServerMapRec)); 1184 if (!tmp) 1185 return FALSE; 1186 dst->server = tmp; 1187 } 1188 1189 gap = MAP_LENGTH - (src->max_key_code + 1); 1190 if (src->server->explicit) { 1191 if (!dst->server->explicit) { 1192 tmp = realloc(dst->server->explicit, MAP_LENGTH); 1193 if (!tmp) 1194 return FALSE; 1195 dst->server->explicit = tmp; 1196 } 1197 if (gap > 0) 1198 memset(dst->server->explicit + gap, 0, gap); 1199 memcpy(dst->server->explicit, src->server->explicit, 1200 src->max_key_code + 1); 1201 } 1202 else { 1203 free(dst->server->explicit); 1204 dst->server->explicit = NULL; 1205 } 1206 1207 if (src->server->acts) { 1208 if (src->server->size_acts != dst->server->size_acts) { 1209 tmp = reallocarray(dst->server->acts, 1210 src->server->size_acts, sizeof(XkbAction)); 1211 if (!tmp) 1212 return FALSE; 1213 dst->server->acts = tmp; 1214 } 1215 memcpy(dst->server->acts, src->server->acts, 1216 src->server->size_acts * sizeof(XkbAction)); 1217 } 1218 else { 1219 free(dst->server->acts); 1220 dst->server->acts = NULL; 1221 } 1222 dst->server->size_acts = src->server->size_acts; 1223 dst->server->num_acts = src->server->num_acts; 1224 1225 if (src->server->key_acts) { 1226 if (!dst->server->key_acts) { 1227 tmp = reallocarray(dst->server->key_acts, 1228 MAP_LENGTH, sizeof(unsigned short)); 1229 if (!tmp) 1230 return FALSE; 1231 dst->server->key_acts = tmp; 1232 } 1233 if (gap > 0) 1234 memset((char *) &dst->server->key_acts[gap], 0, gap * sizeof(unsigned short)); 1235 memcpy(dst->server->key_acts, src->server->key_acts, 1236 (src->max_key_code + 1) * sizeof(unsigned short)); 1237 } 1238 else { 1239 free(dst->server->key_acts); 1240 dst->server->key_acts = NULL; 1241 } 1242 1243 if (src->server->behaviors) { 1244 if (!dst->server->behaviors) { 1245 tmp = reallocarray(dst->server->behaviors, 1246 MAP_LENGTH, sizeof(XkbBehavior)); 1247 if (!tmp) 1248 return FALSE; 1249 dst->server->behaviors = tmp; 1250 } 1251 if (gap > 0) 1252 memset((char *) &dst->server->behaviors[gap], 0, gap * sizeof(XkbBehavior)); 1253 memcpy(dst->server->behaviors, src->server->behaviors, 1254 (src->max_key_code + 1) * sizeof(XkbBehavior)); 1255 } 1256 else { 1257 free(dst->server->behaviors); 1258 dst->server->behaviors = NULL; 1259 } 1260 1261 memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods); 1262 1263 if (src->server->vmodmap) { 1264 if (!dst->server->vmodmap) { 1265 tmp = reallocarray(dst->server->vmodmap, 1266 MAP_LENGTH, sizeof(unsigned short)); 1267 if (!tmp) 1268 return FALSE; 1269 dst->server->vmodmap = tmp; 1270 } 1271 if (gap > 0) 1272 memset((char *) &dst->server->vmodmap[gap], 0, gap * sizeof(unsigned short)); 1273 memcpy(dst->server->vmodmap, src->server->vmodmap, 1274 (src->max_key_code + 1) * sizeof(unsigned short)); 1275 } 1276 else { 1277 free(dst->server->vmodmap); 1278 dst->server->vmodmap = NULL; 1279 } 1280 } 1281 else { 1282 if (dst->server) 1283 XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE); 1284 } 1285 1286 return TRUE; 1287} 1288 1289static Bool 1290_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst) 1291{ 1292 void *tmp = NULL; 1293 int gap; 1294 1295 /* names */ 1296 if (src->names) { 1297 if (!dst->names) { 1298 dst->names = calloc(1, sizeof(XkbNamesRec)); 1299 if (!dst->names) 1300 return FALSE; 1301 } 1302 1303 gap = MAP_LENGTH - (src->max_key_code + 1); 1304 if (src->names->keys) { 1305 if (!dst->names->keys) { 1306 tmp = reallocarray(dst->names->keys, MAP_LENGTH, 1307 sizeof(XkbKeyNameRec)); 1308 if (!tmp) 1309 return FALSE; 1310 dst->names->keys = tmp; 1311 } 1312 if (gap > 0) 1313 memset((char *) &dst->names->keys[gap], 0, gap * sizeof(XkbKeyNameRec)); 1314 memcpy(dst->names->keys, src->names->keys, 1315 (src->max_key_code + 1) * sizeof(XkbKeyNameRec)); 1316 } 1317 else { 1318 free(dst->names->keys); 1319 dst->names->keys = NULL; 1320 } 1321 1322 if (src->names->num_key_aliases) { 1323 if (src->names->num_key_aliases != dst->names->num_key_aliases) { 1324 tmp = reallocarray(dst->names->key_aliases, 1325 src->names->num_key_aliases, 1326 sizeof(XkbKeyAliasRec)); 1327 if (!tmp) 1328 return FALSE; 1329 dst->names->key_aliases = tmp; 1330 } 1331 memcpy(dst->names->key_aliases, src->names->key_aliases, 1332 src->names->num_key_aliases * sizeof(XkbKeyAliasRec)); 1333 } 1334 else { 1335 free(dst->names->key_aliases); 1336 dst->names->key_aliases = NULL; 1337 } 1338 dst->names->num_key_aliases = src->names->num_key_aliases; 1339 1340 if (src->names->num_rg) { 1341 if (src->names->num_rg != dst->names->num_rg) { 1342 tmp = reallocarray(dst->names->radio_groups, 1343 src->names->num_rg, sizeof(Atom)); 1344 if (!tmp) 1345 return FALSE; 1346 dst->names->radio_groups = tmp; 1347 } 1348 memcpy(dst->names->radio_groups, src->names->radio_groups, 1349 src->names->num_rg * sizeof(Atom)); 1350 } 1351 else { 1352 free(dst->names->radio_groups); 1353 dst->names->radio_groups = NULL; 1354 } 1355 dst->names->num_rg = src->names->num_rg; 1356 1357 dst->names->keycodes = src->names->keycodes; 1358 dst->names->geometry = src->names->geometry; 1359 dst->names->symbols = src->names->symbols; 1360 dst->names->types = src->names->types; 1361 dst->names->compat = src->names->compat; 1362 dst->names->phys_symbols = src->names->phys_symbols; 1363 1364 memcpy(dst->names->vmods, src->names->vmods, 1365 XkbNumVirtualMods * sizeof(Atom)); 1366 memcpy(dst->names->indicators, src->names->indicators, 1367 XkbNumIndicators * sizeof(Atom)); 1368 memcpy(dst->names->groups, src->names->groups, 1369 XkbNumKbdGroups * sizeof(Atom)); 1370 } 1371 else { 1372 if (dst->names) 1373 XkbFreeNames(dst, XkbAllNamesMask, TRUE); 1374 } 1375 1376 return TRUE; 1377} 1378 1379static Bool 1380_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst) 1381{ 1382 void *tmp = NULL; 1383 1384 /* compat */ 1385 if (src->compat) { 1386 if (!dst->compat) { 1387 dst->compat = calloc(1, sizeof(XkbCompatMapRec)); 1388 if (!dst->compat) 1389 return FALSE; 1390 } 1391 1392 if (src->compat->sym_interpret && src->compat->num_si) { 1393 if (src->compat->num_si != dst->compat->size_si) { 1394 tmp = reallocarray(dst->compat->sym_interpret, 1395 src->compat->num_si, 1396 sizeof(XkbSymInterpretRec)); 1397 if (!tmp) 1398 return FALSE; 1399 dst->compat->sym_interpret = tmp; 1400 } 1401 memcpy(dst->compat->sym_interpret, src->compat->sym_interpret, 1402 src->compat->num_si * sizeof(XkbSymInterpretRec)); 1403 1404 dst->compat->num_si = src->compat->num_si; 1405 dst->compat->size_si = src->compat->num_si; 1406 } 1407 else { 1408 if (dst->compat->sym_interpret && dst->compat->size_si) 1409 free(dst->compat->sym_interpret); 1410 1411 dst->compat->sym_interpret = NULL; 1412 dst->compat->num_si = 0; 1413 dst->compat->size_si = 0; 1414 } 1415 1416 memcpy(dst->compat->groups, src->compat->groups, 1417 XkbNumKbdGroups * sizeof(XkbModsRec)); 1418 } 1419 else { 1420 if (dst->compat) 1421 XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE); 1422 } 1423 1424 return TRUE; 1425} 1426 1427static Bool 1428_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst) 1429{ 1430 void *tmp = NULL; 1431 int i = 0, j = 0, k = 0; 1432 XkbColorPtr scolor = NULL, dcolor = NULL; 1433 XkbDoodadPtr sdoodad = NULL, ddoodad = NULL; 1434 XkbOutlinePtr soutline = NULL, doutline = NULL; 1435 XkbPropertyPtr sprop = NULL, dprop = NULL; 1436 XkbRowPtr srow = NULL, drow = NULL; 1437 XkbSectionPtr ssection = NULL, dsection = NULL; 1438 XkbShapePtr sshape = NULL, dshape = NULL; 1439 1440 /* geometry */ 1441 if (src->geom) { 1442 if (!dst->geom) { 1443 dst->geom = calloc(sizeof(XkbGeometryRec), 1); 1444 if (!dst->geom) 1445 return FALSE; 1446 } 1447 1448 /* properties */ 1449 if (src->geom->num_properties) { 1450 /* If we've got more properties in the destination than 1451 * the source, run through and free all the excess ones 1452 * first. */ 1453 if (src->geom->num_properties < dst->geom->sz_properties) { 1454 for (i = src->geom->num_properties, dprop = 1455 dst->geom->properties + i; i < dst->geom->num_properties; 1456 i++, dprop++) { 1457 free(dprop->name); 1458 free(dprop->value); 1459 } 1460 } 1461 1462 /* Reallocate and clear all new items if the buffer grows. */ 1463 if (!XkbGeomRealloc 1464 ((void **) &dst->geom->properties, dst->geom->sz_properties, 1465 src->geom->num_properties, sizeof(XkbPropertyRec), 1466 XKB_GEOM_CLEAR_EXCESS)) 1467 return FALSE; 1468 /* We don't set num_properties as we need it to try and avoid 1469 * too much reallocing. */ 1470 dst->geom->sz_properties = src->geom->num_properties; 1471 1472 for (i = 0, 1473 sprop = src->geom->properties, 1474 dprop = dst->geom->properties; 1475 i < src->geom->num_properties; i++, sprop++, dprop++) { 1476 if (i < dst->geom->num_properties) { 1477 if (strlen(sprop->name) != strlen(dprop->name)) { 1478 tmp = realloc(dprop->name, strlen(sprop->name) + 1); 1479 if (!tmp) 1480 return FALSE; 1481 dprop->name = tmp; 1482 } 1483 if (strlen(sprop->value) != strlen(dprop->value)) { 1484 tmp = realloc(dprop->value, strlen(sprop->value) + 1); 1485 if (!tmp) 1486 return FALSE; 1487 dprop->value = tmp; 1488 } 1489 strcpy(dprop->name, sprop->name); 1490 strcpy(dprop->value, sprop->value); 1491 } 1492 else { 1493 dprop->name = xstrdup(sprop->name); 1494 dprop->value = xstrdup(sprop->value); 1495 } 1496 } 1497 1498 /* ... which is already src->geom->num_properties. */ 1499 dst->geom->num_properties = dst->geom->sz_properties; 1500 } 1501 else { 1502 if (dst->geom->sz_properties) { 1503 for (i = 0, dprop = dst->geom->properties; 1504 i < dst->geom->num_properties; i++, dprop++) { 1505 free(dprop->name); 1506 free(dprop->value); 1507 } 1508 free(dst->geom->properties); 1509 dst->geom->properties = NULL; 1510 } 1511 1512 dst->geom->num_properties = 0; 1513 dst->geom->sz_properties = 0; 1514 } 1515 1516 /* colors */ 1517 if (src->geom->num_colors) { 1518 if (src->geom->num_colors < dst->geom->sz_colors) { 1519 for (i = src->geom->num_colors, dcolor = dst->geom->colors + i; 1520 i < dst->geom->num_colors; i++, dcolor++) { 1521 free(dcolor->spec); 1522 } 1523 } 1524 1525 /* Reallocate and clear all new items if the buffer grows. */ 1526 if (!XkbGeomRealloc 1527 ((void **) &dst->geom->colors, dst->geom->sz_colors, 1528 src->geom->num_colors, sizeof(XkbColorRec), 1529 XKB_GEOM_CLEAR_EXCESS)) 1530 return FALSE; 1531 dst->geom->sz_colors = src->geom->num_colors; 1532 1533 for (i = 0, 1534 scolor = src->geom->colors, 1535 dcolor = dst->geom->colors; 1536 i < src->geom->num_colors; i++, scolor++, dcolor++) { 1537 if (i < dst->geom->num_colors) { 1538 if (strlen(scolor->spec) != strlen(dcolor->spec)) { 1539 tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1); 1540 if (!tmp) 1541 return FALSE; 1542 dcolor->spec = tmp; 1543 } 1544 strcpy(dcolor->spec, scolor->spec); 1545 } 1546 else { 1547 dcolor->spec = xstrdup(scolor->spec); 1548 } 1549 dcolor->pixel = scolor->pixel; 1550 } 1551 1552 dst->geom->num_colors = dst->geom->sz_colors; 1553 } 1554 else { 1555 if (dst->geom->sz_colors) { 1556 for (i = 0, dcolor = dst->geom->colors; 1557 i < dst->geom->num_colors; i++, dcolor++) { 1558 free(dcolor->spec); 1559 } 1560 free(dst->geom->colors); 1561 dst->geom->colors = NULL; 1562 } 1563 1564 dst->geom->num_colors = 0; 1565 dst->geom->sz_colors = 0; 1566 } 1567 1568 /* shapes */ 1569 /* shapes break down into outlines, which break down into points. */ 1570 if (dst->geom->num_shapes) { 1571 for (i = 0, dshape = dst->geom->shapes; 1572 i < dst->geom->num_shapes; i++, dshape++) { 1573 for (j = 0, doutline = dshape->outlines; 1574 j < dshape->num_outlines; j++, doutline++) { 1575 if (doutline->sz_points) 1576 free(doutline->points); 1577 } 1578 1579 if (dshape->sz_outlines) { 1580 free(dshape->outlines); 1581 dshape->outlines = NULL; 1582 } 1583 1584 dshape->num_outlines = 0; 1585 dshape->sz_outlines = 0; 1586 } 1587 } 1588 1589 if (src->geom->num_shapes) { 1590 /* Reallocate and clear all items. */ 1591 if (!XkbGeomRealloc 1592 ((void **) &dst->geom->shapes, dst->geom->sz_shapes, 1593 src->geom->num_shapes, sizeof(XkbShapeRec), 1594 XKB_GEOM_CLEAR_ALL)) 1595 return FALSE; 1596 1597 for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes; 1598 i < src->geom->num_shapes; i++, sshape++, dshape++) { 1599 if (sshape->num_outlines) { 1600 tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec)); 1601 if (!tmp) 1602 return FALSE; 1603 dshape->outlines = tmp; 1604 1605 for (j = 0, 1606 soutline = sshape->outlines, 1607 doutline = dshape->outlines; 1608 j < sshape->num_outlines; 1609 j++, soutline++, doutline++) { 1610 if (soutline->num_points) { 1611 tmp = xallocarray(soutline->num_points, 1612 sizeof(XkbPointRec)); 1613 if (!tmp) 1614 return FALSE; 1615 doutline->points = tmp; 1616 1617 memcpy(doutline->points, soutline->points, 1618 soutline->num_points * sizeof(XkbPointRec)); 1619 1620 doutline->corner_radius = soutline->corner_radius; 1621 } 1622 1623 doutline->num_points = soutline->num_points; 1624 doutline->sz_points = soutline->num_points; 1625 } 1626 } 1627 1628 dshape->num_outlines = sshape->num_outlines; 1629 dshape->sz_outlines = sshape->num_outlines; 1630 dshape->name = sshape->name; 1631 dshape->bounds = sshape->bounds; 1632 1633 dshape->approx = NULL; 1634 if (sshape->approx && sshape->num_outlines > 0) { 1635 1636 const ptrdiff_t approx_idx = 1637 sshape->approx - sshape->outlines; 1638 1639 if (approx_idx < dshape->num_outlines) { 1640 dshape->approx = dshape->outlines + approx_idx; 1641 } 1642 else { 1643 LogMessage(X_WARNING, "XKB: approx outline " 1644 "index is out of range\n"); 1645 } 1646 } 1647 1648 dshape->primary = NULL; 1649 if (sshape->primary && sshape->num_outlines > 0) { 1650 1651 const ptrdiff_t primary_idx = 1652 sshape->primary - sshape->outlines; 1653 1654 if (primary_idx < dshape->num_outlines) { 1655 dshape->primary = dshape->outlines + primary_idx; 1656 } 1657 else { 1658 LogMessage(X_WARNING, "XKB: primary outline " 1659 "index is out of range\n"); 1660 } 1661 } 1662 } 1663 1664 dst->geom->num_shapes = src->geom->num_shapes; 1665 dst->geom->sz_shapes = src->geom->num_shapes; 1666 } 1667 else { 1668 if (dst->geom->sz_shapes) { 1669 free(dst->geom->shapes); 1670 } 1671 dst->geom->shapes = NULL; 1672 dst->geom->num_shapes = 0; 1673 dst->geom->sz_shapes = 0; 1674 } 1675 1676 /* sections */ 1677 /* sections break down into doodads, and also into rows, which break 1678 * down into keys. */ 1679 if (dst->geom->num_sections) { 1680 for (i = 0, dsection = dst->geom->sections; 1681 i < dst->geom->num_sections; i++, dsection++) { 1682 for (j = 0, drow = dsection->rows; 1683 j < dsection->num_rows; j++, drow++) { 1684 if (drow->num_keys) 1685 free(drow->keys); 1686 } 1687 1688 if (dsection->num_rows) 1689 free(dsection->rows); 1690 1691 /* cut and waste from geom/doodad below. */ 1692 for (j = 0, ddoodad = dsection->doodads; 1693 j < dsection->num_doodads; j++, ddoodad++) { 1694 if (ddoodad->any.type == XkbTextDoodad) { 1695 free(ddoodad->text.text); 1696 ddoodad->text.text = NULL; 1697 free(ddoodad->text.font); 1698 ddoodad->text.font = NULL; 1699 } 1700 else if (ddoodad->any.type == XkbLogoDoodad) { 1701 free(ddoodad->logo.logo_name); 1702 ddoodad->logo.logo_name = NULL; 1703 } 1704 } 1705 1706 free(dsection->doodads); 1707 } 1708 1709 dst->geom->num_sections = 0; 1710 } 1711 1712 if (src->geom->num_sections) { 1713 /* Reallocate and clear all items. */ 1714 if (!XkbGeomRealloc 1715 ((void **) &dst->geom->sections, dst->geom->sz_sections, 1716 src->geom->num_sections, sizeof(XkbSectionRec), 1717 XKB_GEOM_CLEAR_ALL)) 1718 return FALSE; 1719 dst->geom->num_sections = src->geom->num_sections; 1720 dst->geom->sz_sections = src->geom->num_sections; 1721 1722 for (i = 0, 1723 ssection = src->geom->sections, 1724 dsection = dst->geom->sections; 1725 i < src->geom->num_sections; i++, ssection++, dsection++) { 1726 *dsection = *ssection; 1727 if (ssection->num_rows) { 1728 tmp = calloc(ssection->num_rows, sizeof(XkbRowRec)); 1729 if (!tmp) 1730 return FALSE; 1731 dsection->rows = tmp; 1732 } 1733 dsection->num_rows = ssection->num_rows; 1734 dsection->sz_rows = ssection->num_rows; 1735 1736 for (j = 0, srow = ssection->rows, drow = dsection->rows; 1737 j < ssection->num_rows; j++, srow++, drow++) { 1738 if (srow->num_keys) { 1739 tmp = xallocarray(srow->num_keys, sizeof(XkbKeyRec)); 1740 if (!tmp) 1741 return FALSE; 1742 drow->keys = tmp; 1743 memcpy(drow->keys, srow->keys, 1744 srow->num_keys * sizeof(XkbKeyRec)); 1745 } 1746 drow->num_keys = srow->num_keys; 1747 drow->sz_keys = srow->num_keys; 1748 drow->top = srow->top; 1749 drow->left = srow->left; 1750 drow->vertical = srow->vertical; 1751 drow->bounds = srow->bounds; 1752 } 1753 1754 if (ssection->num_doodads) { 1755 tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec)); 1756 if (!tmp) 1757 return FALSE; 1758 dsection->doodads = tmp; 1759 } 1760 else { 1761 dsection->doodads = NULL; 1762 } 1763 1764 dsection->sz_doodads = ssection->num_doodads; 1765 for (k = 0, 1766 sdoodad = ssection->doodads, 1767 ddoodad = dsection->doodads; 1768 k < ssection->num_doodads; k++, sdoodad++, ddoodad++) { 1769 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec)); 1770 if (sdoodad->any.type == XkbTextDoodad) { 1771 if (sdoodad->text.text) 1772 ddoodad->text.text = strdup(sdoodad->text.text); 1773 if (sdoodad->text.font) 1774 ddoodad->text.font = strdup(sdoodad->text.font); 1775 } 1776 else if (sdoodad->any.type == XkbLogoDoodad) { 1777 if (sdoodad->logo.logo_name) 1778 ddoodad->logo.logo_name = 1779 strdup(sdoodad->logo.logo_name); 1780 } 1781 } 1782 dsection->overlays = NULL; 1783 dsection->sz_overlays = 0; 1784 dsection->num_overlays = 0; 1785 } 1786 } 1787 else { 1788 if (dst->geom->sz_sections) { 1789 free(dst->geom->sections); 1790 } 1791 1792 dst->geom->sections = NULL; 1793 dst->geom->num_sections = 0; 1794 dst->geom->sz_sections = 0; 1795 } 1796 1797 /* doodads */ 1798 if (dst->geom->num_doodads) { 1799 for (i = src->geom->num_doodads, 1800 ddoodad = dst->geom->doodads + 1801 src->geom->num_doodads; 1802 i < dst->geom->num_doodads; i++, ddoodad++) { 1803 if (ddoodad->any.type == XkbTextDoodad) { 1804 free(ddoodad->text.text); 1805 ddoodad->text.text = NULL; 1806 free(ddoodad->text.font); 1807 ddoodad->text.font = NULL; 1808 } 1809 else if (ddoodad->any.type == XkbLogoDoodad) { 1810 free(ddoodad->logo.logo_name); 1811 ddoodad->logo.logo_name = NULL; 1812 } 1813 } 1814 dst->geom->num_doodads = 0; 1815 } 1816 1817 if (src->geom->num_doodads) { 1818 /* Reallocate and clear all items. */ 1819 if (!XkbGeomRealloc 1820 ((void **) &dst->geom->doodads, dst->geom->sz_doodads, 1821 src->geom->num_doodads, sizeof(XkbDoodadRec), 1822 XKB_GEOM_CLEAR_ALL)) 1823 return FALSE; 1824 1825 dst->geom->sz_doodads = src->geom->num_doodads; 1826 1827 for (i = 0, 1828 sdoodad = src->geom->doodads, 1829 ddoodad = dst->geom->doodads; 1830 i < src->geom->num_doodads; i++, sdoodad++, ddoodad++) { 1831 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec)); 1832 if (sdoodad->any.type == XkbTextDoodad) { 1833 if (sdoodad->text.text) 1834 ddoodad->text.text = strdup(sdoodad->text.text); 1835 if (sdoodad->text.font) 1836 ddoodad->text.font = strdup(sdoodad->text.font); 1837 } 1838 else if (sdoodad->any.type == XkbLogoDoodad) { 1839 if (sdoodad->logo.logo_name) 1840 ddoodad->logo.logo_name = 1841 strdup(sdoodad->logo.logo_name); 1842 } 1843 } 1844 1845 dst->geom->num_doodads = dst->geom->sz_doodads; 1846 } 1847 else { 1848 if (dst->geom->sz_doodads) { 1849 free(dst->geom->doodads); 1850 } 1851 1852 dst->geom->doodads = NULL; 1853 dst->geom->num_doodads = 0; 1854 dst->geom->sz_doodads = 0; 1855 } 1856 1857 /* key aliases */ 1858 if (src->geom->num_key_aliases) { 1859 /* Reallocate but don't clear any items. There is no need 1860 * to clear anything because data is immediately copied 1861 * over the whole memory area with memcpy. */ 1862 if (!XkbGeomRealloc 1863 ((void **) &dst->geom->key_aliases, dst->geom->sz_key_aliases, 1864 src->geom->num_key_aliases, 2 * XkbKeyNameLength, 1865 XKB_GEOM_CLEAR_NONE)) 1866 return FALSE; 1867 1868 dst->geom->sz_key_aliases = src->geom->num_key_aliases; 1869 1870 memcpy(dst->geom->key_aliases, src->geom->key_aliases, 1871 src->geom->num_key_aliases * 2 * XkbKeyNameLength); 1872 1873 dst->geom->num_key_aliases = dst->geom->sz_key_aliases; 1874 } 1875 else { 1876 free(dst->geom->key_aliases); 1877 dst->geom->key_aliases = NULL; 1878 dst->geom->num_key_aliases = 0; 1879 dst->geom->sz_key_aliases = 0; 1880 } 1881 1882 /* font */ 1883 if (src->geom->label_font) { 1884 if (!dst->geom->label_font) { 1885 tmp = malloc(strlen(src->geom->label_font) + 1); 1886 if (!tmp) 1887 return FALSE; 1888 dst->geom->label_font = tmp; 1889 } 1890 else if (strlen(src->geom->label_font) != 1891 strlen(dst->geom->label_font)) { 1892 tmp = realloc(dst->geom->label_font, 1893 strlen(src->geom->label_font) + 1); 1894 if (!tmp) 1895 return FALSE; 1896 dst->geom->label_font = tmp; 1897 } 1898 1899 strcpy(dst->geom->label_font, src->geom->label_font); 1900 i = XkbGeomColorIndex(src->geom, src->geom->label_color); 1901 dst->geom->label_color = &(dst->geom->colors[i]); 1902 i = XkbGeomColorIndex(src->geom, src->geom->base_color); 1903 dst->geom->base_color = &(dst->geom->colors[i]); 1904 } 1905 else { 1906 free(dst->geom->label_font); 1907 dst->geom->label_font = NULL; 1908 dst->geom->label_color = NULL; 1909 dst->geom->base_color = NULL; 1910 } 1911 1912 dst->geom->name = src->geom->name; 1913 dst->geom->width_mm = src->geom->width_mm; 1914 dst->geom->height_mm = src->geom->height_mm; 1915 } 1916 else { 1917 if (dst->geom) { 1918 /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */ 1919 XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE); 1920 dst->geom = NULL; 1921 } 1922 } 1923 1924 return TRUE; 1925} 1926 1927static Bool 1928_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst) 1929{ 1930 /* indicators */ 1931 if (src->indicators) { 1932 if (!dst->indicators) { 1933 dst->indicators = malloc(sizeof(XkbIndicatorRec)); 1934 if (!dst->indicators) 1935 return FALSE; 1936 } 1937 memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec)); 1938 } 1939 else { 1940 free(dst->indicators); 1941 dst->indicators = NULL; 1942 } 1943 return TRUE; 1944} 1945 1946static Bool 1947_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst) 1948{ 1949 /* controls */ 1950 if (src->ctrls) { 1951 if (!dst->ctrls) { 1952 dst->ctrls = malloc(sizeof(XkbControlsRec)); 1953 if (!dst->ctrls) 1954 return FALSE; 1955 } 1956 memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec)); 1957 } 1958 else { 1959 free(dst->ctrls); 1960 dst->ctrls = NULL; 1961 } 1962 return TRUE; 1963} 1964 1965/** 1966 * Copy an XKB map from src to dst, reallocating when necessary: if some 1967 * map components are present in one, but not in the other, the destination 1968 * components will be allocated or freed as necessary. 1969 * 1970 * Basic map consistency is assumed on both sides, so maps with random 1971 * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19) 1972 * _will_ cause failures. You've been warned. 1973 * 1974 * Returns TRUE on success, or FALSE on failure. If this function fails, 1975 * dst may be in an inconsistent state: all its pointers are guaranteed 1976 * to remain valid, but part of the map may be from src and part from dst. 1977 * 1978 */ 1979 1980Bool 1981XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) 1982{ 1983 1984 if (!src || !dst) { 1985 DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst); 1986 return FALSE; 1987 } 1988 1989 if (src == dst) 1990 return TRUE; 1991 1992 if (!_XkbCopyClientMap(src, dst)) { 1993 DebugF("XkbCopyKeymap: failed to copy client map\n"); 1994 return FALSE; 1995 } 1996 if (!_XkbCopyServerMap(src, dst)) { 1997 DebugF("XkbCopyKeymap: failed to copy server map\n"); 1998 return FALSE; 1999 } 2000 if (!_XkbCopyIndicators(src, dst)) { 2001 DebugF("XkbCopyKeymap: failed to copy indicators\n"); 2002 return FALSE; 2003 } 2004 if (!_XkbCopyControls(src, dst)) { 2005 DebugF("XkbCopyKeymap: failed to copy controls\n"); 2006 return FALSE; 2007 } 2008 if (!_XkbCopyNames(src, dst)) { 2009 DebugF("XkbCopyKeymap: failed to copy names\n"); 2010 return FALSE; 2011 } 2012 if (!_XkbCopyCompat(src, dst)) { 2013 DebugF("XkbCopyKeymap: failed to copy compat map\n"); 2014 return FALSE; 2015 } 2016 if (!_XkbCopyGeom(src, dst)) { 2017 DebugF("XkbCopyKeymap: failed to copy geometry\n"); 2018 return FALSE; 2019 } 2020 2021 dst->min_key_code = src->min_key_code; 2022 dst->max_key_code = src->max_key_code; 2023 2024 return TRUE; 2025} 2026 2027Bool 2028XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc) 2029{ 2030 xkbNewKeyboardNotify nkn; 2031 Bool ret; 2032 2033 if (!dst->key || !desc) 2034 return FALSE; 2035 2036 memset(&nkn, 0, sizeof(xkbNewKeyboardNotify)); 2037 nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; 2038 nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; 2039 nkn.deviceID = dst->id; 2040 nkn.oldDeviceID = dst->id; 2041 nkn.minKeyCode = desc->min_key_code; 2042 nkn.maxKeyCode = desc->max_key_code; 2043 nkn.requestMajor = XkbReqCode; 2044 nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ 2045 nkn.changed = XkbNKN_KeycodesMask; 2046 if (desc->geom) 2047 nkn.changed |= XkbNKN_GeometryMask; 2048 2049 ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc); 2050 if (ret) 2051 XkbSendNewKeyboardNotify(dst, &nkn); 2052 2053 return ret; 2054} 2055 2056Bool 2057XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) 2058{ 2059 return XkbDeviceApplyKeymap(dst, src->key->xkbInfo->desc); 2060} 2061 2062int 2063XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode) 2064{ 2065 XkbDescPtr xkb = xkbi->desc; 2066 int effectiveGroup = xkbState->group; 2067 2068 if (!XkbKeycodeInRange(xkb, keycode)) 2069 return -1; 2070 2071 if (effectiveGroup == XkbGroup1Index) 2072 return effectiveGroup; 2073 2074 if (XkbKeyNumGroups(xkb, keycode) > 1U) { 2075 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode)) { 2076 unsigned int gi = XkbKeyGroupInfo(xkb, keycode); 2077 2078 switch (XkbOutOfRangeGroupAction(gi)) { 2079 default: 2080 case XkbWrapIntoRange: 2081 effectiveGroup %= XkbKeyNumGroups(xkb, keycode); 2082 break; 2083 case XkbClampIntoRange: 2084 effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1; 2085 break; 2086 case XkbRedirectIntoRange: 2087 effectiveGroup = XkbOutOfRangeGroupInfo(gi); 2088 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode)) 2089 effectiveGroup = 0; 2090 break; 2091 } 2092 } 2093 } 2094 else 2095 effectiveGroup = XkbGroup1Index; 2096 2097 return effectiveGroup; 2098} 2099 2100/* Merge the lockedPtrButtons from all attached SDs for the given master 2101 * device into the MD's state. 2102 */ 2103void 2104XkbMergeLockedPtrBtns(DeviceIntPtr master) 2105{ 2106 DeviceIntPtr d = inputInfo.devices; 2107 XkbSrvInfoPtr xkbi = NULL; 2108 2109 if (!IsMaster(master)) 2110 return; 2111 2112 if (!master->key) 2113 return; 2114 2115 xkbi = master->key->xkbInfo; 2116 xkbi->lockedPtrButtons = 0; 2117 2118 for (; d; d = d->next) { 2119 if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key) 2120 continue; 2121 2122 xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons; 2123 } 2124} 2125 2126void 2127XkbCopyControls(XkbDescPtr dst, XkbDescPtr src) 2128{ 2129 int i, nG, nTG; 2130 2131 if (!dst || !src) 2132 return; 2133 2134 *dst->ctrls = *src->ctrls; 2135 2136 for (nG = nTG = 0, i = dst->min_key_code; i <= dst->max_key_code; i++) { 2137 nG = XkbKeyNumGroups(dst, i); 2138 if (nG >= XkbNumKbdGroups) { 2139 nTG = XkbNumKbdGroups; 2140 break; 2141 } 2142 if (nG > nTG) { 2143 nTG = nG; 2144 } 2145 } 2146 dst->ctrls->num_groups = nTG; 2147} 2148