XKBMAlloc.c revision f2d49d05
1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30 31 32#include <stdio.h> 33#include "Xlibint.h" 34#include <X11/extensions/XKBproto.h> 35#include <X11/keysym.h> 36#include "XKBlibint.h" 37 38 39/***====================================================================***/ 40 41Status 42XkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes) 43{ 44 register int i; 45 XkbClientMapPtr map; 46 47 if ((xkb == NULL) || 48 ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes))) 49 return BadValue; 50 if ((which & XkbKeySymsMask) && 51 ((!XkbIsLegalKeycode(xkb->min_key_code)) || 52 (!XkbIsLegalKeycode(xkb->max_key_code)) || 53 (xkb->max_key_code < xkb->min_key_code))) { 54#ifdef DEBUG 55 fprintf(stderr, "bad keycode (%d,%d) in XkbAllocClientMap\n", 56 xkb->min_key_code, xkb->max_key_code); 57#endif 58 return BadValue; 59 } 60 61 if (xkb->map == NULL) { 62 map = _XkbTypedCalloc(1, XkbClientMapRec); 63 if (map == NULL) 64 return BadAlloc; 65 xkb->map = map; 66 } 67 else 68 map = xkb->map; 69 70 if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) { 71 if (map->types == NULL) { 72 map->num_types = map->size_types = 0; 73 } 74 if ((map->types == NULL) || (map->size_types < nTotalTypes)) { 75 _XkbResizeArray(map->types, map->size_types, nTotalTypes, 76 XkbKeyTypeRec); 77 78 if (map->types == NULL) { 79 map->num_types = map->size_types = 0; 80 return BadAlloc; 81 } 82 map->size_types = nTotalTypes; 83 } 84 } 85 if (which & XkbKeySymsMask) { 86 int nKeys = XkbNumKeys(xkb); 87 88 if (map->syms == NULL) { 89 map->size_syms = (nKeys * 15) / 10; 90 map->syms = _XkbTypedCalloc(map->size_syms, KeySym); 91 if (!map->syms) { 92 map->size_syms = 0; 93 return BadAlloc; 94 } 95 map->num_syms = 1; 96 map->syms[0] = NoSymbol; 97 } 98 if (map->key_sym_map == NULL) { 99 i = xkb->max_key_code + 1; 100 map->key_sym_map = _XkbTypedCalloc(i, XkbSymMapRec); 101 if (map->key_sym_map == NULL) 102 return BadAlloc; 103 } 104 } 105 if (which & XkbModifierMapMask) { 106 if ((!XkbIsLegalKeycode(xkb->min_key_code)) || 107 (!XkbIsLegalKeycode(xkb->max_key_code)) || 108 (xkb->max_key_code < xkb->min_key_code)) 109 return BadMatch; 110 if (map->modmap == NULL) { 111 i = xkb->max_key_code + 1; 112 map->modmap = _XkbTypedCalloc(i, unsigned char); 113 if (map->modmap == NULL) 114 return BadAlloc; 115 } 116 } 117 return Success; 118} 119 120Status 121XkbAllocServerMap(XkbDescPtr xkb, unsigned which, unsigned nNewActions) 122{ 123 register int i; 124 XkbServerMapPtr map; 125 126 if (xkb == NULL) 127 return BadMatch; 128 if (xkb->server == NULL) { 129 map = _XkbTypedCalloc(1, XkbServerMapRec); 130 if (map == NULL) 131 return BadAlloc; 132 for (i = 0; i < XkbNumVirtualMods; i++) { 133 map->vmods[i] = XkbNoModifierMask; 134 } 135 xkb->server = map; 136 } 137 else 138 map = xkb->server; 139 if (which & XkbExplicitComponentsMask) { 140 if ((!XkbIsLegalKeycode(xkb->min_key_code)) || 141 (!XkbIsLegalKeycode(xkb->max_key_code)) || 142 (xkb->max_key_code < xkb->min_key_code)) 143 return BadMatch; 144 if (map->explicit == NULL) { 145 i = xkb->max_key_code + 1; 146 map->explicit = _XkbTypedCalloc(i, unsigned char); 147 if (map->explicit == NULL) 148 return BadAlloc; 149 } 150 } 151 if (which & XkbKeyActionsMask) { 152 if ((!XkbIsLegalKeycode(xkb->min_key_code)) || 153 (!XkbIsLegalKeycode(xkb->max_key_code)) || 154 (xkb->max_key_code < xkb->min_key_code)) 155 return BadMatch; 156 if (nNewActions < 1) 157 nNewActions = 1; 158 if (map->acts == NULL) { 159 map->num_acts = 1; 160 map->size_acts = 0; 161 } 162 if ((map->acts == NULL) || 163 ((map->size_acts - map->num_acts) < nNewActions)) { 164 unsigned need; 165 166 need = map->num_acts + nNewActions; 167 _XkbResizeArray(map->acts, map->size_acts, need, XkbAction); 168 if (map->acts == NULL) { 169 map->num_acts = map->size_acts = 0; 170 return BadAlloc; 171 } 172 map->size_acts = need; 173 } 174 if (map->key_acts == NULL) { 175 i = xkb->max_key_code + 1; 176 map->key_acts = _XkbTypedCalloc(i, unsigned short); 177 if (map->key_acts == NULL) 178 return BadAlloc; 179 } 180 } 181 if (which & XkbKeyBehaviorsMask) { 182 if ((!XkbIsLegalKeycode(xkb->min_key_code)) || 183 (!XkbIsLegalKeycode(xkb->max_key_code)) || 184 (xkb->max_key_code < xkb->min_key_code)) 185 return BadMatch; 186 if (map->behaviors == NULL) { 187 i = xkb->max_key_code + 1; 188 map->behaviors = _XkbTypedCalloc(i, XkbBehavior); 189 if (map->behaviors == NULL) 190 return BadAlloc; 191 } 192 } 193 if (which & XkbVirtualModMapMask) { 194 if ((!XkbIsLegalKeycode(xkb->min_key_code)) || 195 (!XkbIsLegalKeycode(xkb->max_key_code)) || 196 (xkb->max_key_code < xkb->min_key_code)) 197 return BadMatch; 198 if (map->vmodmap == NULL) { 199 i = xkb->max_key_code + 1; 200 map->vmodmap = _XkbTypedCalloc(i, unsigned short); 201 if (map->vmodmap == NULL) 202 return BadAlloc; 203 } 204 } 205 return Success; 206} 207 208/***====================================================================***/ 209 210Status 211XkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into) 212{ 213 if ((!from) || (!into)) 214 return BadMatch; 215 216 _XkbFree(into->map); 217 into->map = NULL; 218 219 _XkbFree(into->preserve); 220 into->preserve = NULL; 221 222 _XkbFree(into->level_names); 223 into->level_names = NULL; 224 225 *into = *from; 226 if ((from->map) && (into->map_count > 0)) { 227 into->map = _XkbTypedCalloc(into->map_count, XkbKTMapEntryRec); 228 if (!into->map) 229 return BadAlloc; 230 memcpy(into->map, from->map, 231 into->map_count * sizeof(XkbKTMapEntryRec)); 232 } 233 if ((from->preserve) && (into->map_count > 0)) { 234 into->preserve = _XkbTypedCalloc(into->map_count, XkbModsRec); 235 if (!into->preserve) 236 return BadAlloc; 237 memcpy(into->preserve, from->preserve, 238 into->map_count * sizeof(XkbModsRec)); 239 } 240 if ((from->level_names) && (into->num_levels > 0)) { 241 into->level_names = _XkbTypedCalloc(into->num_levels, Atom); 242 if (!into->level_names) 243 return BadAlloc; 244 memcpy(into->level_names, from->level_names, 245 into->num_levels * sizeof(Atom)); 246 } 247 return Success; 248} 249 250Status 251XkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types) 252{ 253 register int i, rtrn; 254 255 if ((!from) || (!into) || (num_types < 0)) 256 return BadMatch; 257 for (i = 0; i < num_types; i++) { 258 if ((rtrn = XkbCopyKeyType(from++, into++)) != Success) 259 return rtrn; 260 } 261 return Success; 262} 263 264XkbKeyTypePtr 265XkbAddKeyType(XkbDescPtr xkb, 266 Atom name, 267 int map_count, 268 Bool want_preserve, 269 int num_lvls) 270{ 271 register int i; 272 unsigned tmp; 273 XkbKeyTypePtr type; 274 XkbClientMapPtr map; 275 276 if ((!xkb) || (num_lvls < 1)) 277 return NULL; 278 map = xkb->map; 279 if ((map) && (map->types)) { 280 for (i = 0; i < map->num_types; i++) { 281 if (map->types[i].name == name) { 282 Status status = 283 XkbResizeKeyType(xkb, i, map_count, want_preserve, 284 num_lvls); 285 return (status == Success ? &map->types[i] : NULL); 286 } 287 } 288 } 289 if ((!map) || (!map->types) || (map->num_types < XkbNumRequiredTypes)) { 290 tmp = XkbNumRequiredTypes + 1; 291 if (XkbAllocClientMap(xkb, XkbKeyTypesMask, tmp) != Success) 292 return NULL; 293 if (!map) 294 map = xkb->map; 295 tmp = 0; 296 if (map->num_types <= XkbKeypadIndex) 297 tmp |= XkbKeypadMask; 298 if (map->num_types <= XkbAlphabeticIndex) 299 tmp |= XkbAlphabeticMask; 300 if (map->num_types <= XkbTwoLevelIndex) 301 tmp |= XkbTwoLevelMask; 302 if (map->num_types <= XkbOneLevelIndex) 303 tmp |= XkbOneLevelMask; 304 if (XkbInitCanonicalKeyTypes(xkb, tmp, XkbNoModifier) == Success) { 305 for (i = 0; i < map->num_types; i++) { 306 Status status; 307 308 if (map->types[i].name != name) 309 continue; 310 status = XkbResizeKeyType(xkb, i, map_count, want_preserve, 311 num_lvls); 312 return (status == Success ? &map->types[i] : NULL); 313 } 314 } 315 } 316 if ((map->num_types <= map->size_types) && 317 (XkbAllocClientMap(xkb, XkbKeyTypesMask, map->num_types + 1) != 318 Success)) { 319 return NULL; 320 } 321 type = &map->types[map->num_types]; 322 map->num_types++; 323 bzero((char *) type, sizeof(XkbKeyTypeRec)); 324 type->num_levels = num_lvls; 325 type->map_count = map_count; 326 type->name = name; 327 if (map_count > 0) { 328 type->map = _XkbTypedCalloc(map_count, XkbKTMapEntryRec); 329 if (!type->map) { 330 map->num_types--; 331 return NULL; 332 } 333 if (want_preserve) { 334 type->preserve = _XkbTypedCalloc(map_count, XkbModsRec); 335 if (!type->preserve) { 336 _XkbFree(type->map); 337 map->num_types--; 338 return NULL; 339 } 340 } 341 } 342 return type; 343} 344 345Status 346XkbResizeKeyType(XkbDescPtr xkb, 347 int type_ndx, 348 int map_count, 349 Bool want_preserve, 350 int new_num_lvls) 351{ 352 XkbKeyTypePtr type; 353 KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys; 354 355 if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0) 356 || (new_num_lvls < 1)) 357 return BadValue; 358 switch (type_ndx) { 359 case XkbOneLevelIndex: 360 if (new_num_lvls != 1) 361 return BadMatch; 362 break; 363 case XkbTwoLevelIndex: 364 case XkbAlphabeticIndex: 365 case XkbKeypadIndex: 366 if (new_num_lvls != 2) 367 return BadMatch; 368 break; 369 } 370 type = &xkb->map->types[type_ndx]; 371 if (map_count == 0) { 372 _XkbFree(type->map); 373 type->map = NULL; 374 _XkbFree(type->preserve); 375 type->preserve = NULL; 376 type->map_count = 0; 377 } 378 else { 379 if ((map_count > type->map_count) || (type->map == NULL)) 380 _XkbResizeArray(type->map, type->map_count, map_count, 381 XkbKTMapEntryRec); 382 if (!type->map) { 383 return BadAlloc; 384 } 385 if (want_preserve) { 386 if ((map_count > type->map_count) || (type->preserve == NULL)) { 387 _XkbResizeArray(type->preserve, type->map_count, map_count, 388 XkbModsRec); 389 } 390 if (!type->preserve) { 391 return BadAlloc; 392 } 393 } 394 else { 395 _XkbFree(type->preserve); 396 type->preserve = NULL; 397 } 398 type->map_count = map_count; 399 } 400 401 if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) { 402 _XkbResizeArray(type->level_names, type->num_levels, new_num_lvls, Atom); 403 if (!type->level_names) { 404 return BadAlloc; 405 } 406 } 407 /* 408 * Here's the theory: 409 * If the width of the type changed, we might have to resize the symbol 410 * maps for any keys that use the type for one or more groups. This is 411 * expensive, so we'll try to cull out any keys that are obviously okay: 412 * In any case: 413 * - keys that have a group width <= the old width are okay (because 414 * they could not possibly have been associated with the old type) 415 * If the key type increased in size: 416 * - keys that already have a group width >= to the new width are okay 417 * + keys that have a group width >= the old width but < the new width 418 * might have to be enlarged. 419 * If the key type decreased in size: 420 * - keys that have a group width > the old width don't have to be 421 * resized (because they must have some other wider type associated 422 * with some group). 423 * + keys that have a group width == the old width might have to be 424 * shrunk. 425 * The possibilities marked with '+' require us to examine the key types 426 * associated with each group for the key. 427 */ 428 bzero(matchingKeys, XkbMaxKeyCount * sizeof(KeyCode)); 429 nMatchingKeys = 0; 430 if (new_num_lvls > type->num_levels) { 431 int nTotal; 432 KeySym *newSyms; 433 int width, match, nResize; 434 register int i, g, nSyms; 435 436 nResize = 0; 437 for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 438 width = XkbKeyGroupsWidth(xkb, i); 439 if (width < type->num_levels) 440 continue; 441 for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1; 442 (g >= 0) && (!match); g--) { 443 if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) { 444 matchingKeys[nMatchingKeys++] = i; 445 match = 1; 446 } 447 } 448 if ((!match) || (width >= new_num_lvls)) 449 nTotal += XkbKeyNumSyms(xkb, i); 450 else { 451 nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls; 452 nResize++; 453 } 454 } 455 if (nResize > 0) { 456 int nextMatch; 457 458 xkb->map->size_syms = (nTotal * 12) / 10; 459 newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym); 460 if (newSyms == NULL) 461 return BadAlloc; 462 nextMatch = 0; 463 nSyms = 1; 464 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 465 if (matchingKeys[nextMatch] == i) { 466 KeySym *pOld; 467 468 nextMatch++; 469 width = XkbKeyGroupsWidth(xkb, i); 470 pOld = XkbKeySymsPtr(xkb, i); 471 for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) { 472 memcpy(&newSyms[nSyms + (new_num_lvls * g)], 473 &pOld[width * g], width * sizeof(KeySym)); 474 } 475 xkb->map->key_sym_map[i].offset = nSyms; 476 nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls; 477 } 478 else { 479 memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i), 480 XkbKeyNumSyms(xkb, i) * sizeof(KeySym)); 481 xkb->map->key_sym_map[i].offset = nSyms; 482 nSyms += XkbKeyNumSyms(xkb, i); 483 } 484 } 485 type->num_levels = new_num_lvls; 486 _XkbFree(xkb->map->syms); 487 xkb->map->syms = newSyms; 488 xkb->map->num_syms = nSyms; 489 return Success; 490 } 491 } 492 else if (new_num_lvls < type->num_levels) { 493 int width, match; 494 register int g, i; 495 496 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 497 width = XkbKeyGroupsWidth(xkb, i); 498 if (width < type->num_levels) 499 continue; 500 for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1; 501 (g >= 0) && (!match); g--) { 502 if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) { 503 matchingKeys[nMatchingKeys++] = i; 504 match = 1; 505 } 506 } 507 } 508 } 509 if (nMatchingKeys > 0) { 510 int key, firstClear; 511 register int i, g; 512 513 if (new_num_lvls > type->num_levels) 514 firstClear = type->num_levels; 515 else 516 firstClear = new_num_lvls; 517 for (i = 0; i < nMatchingKeys; i++) { 518 KeySym *pSyms; 519 int width, nClear; 520 521 key = matchingKeys[i]; 522 width = XkbKeyGroupsWidth(xkb, key); 523 nClear = width - firstClear; 524 pSyms = XkbKeySymsPtr(xkb, key); 525 for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) { 526 if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) { 527 if (nClear > 0) 528 bzero(&pSyms[g * width + firstClear], 529 nClear * sizeof(KeySym)); 530 } 531 } 532 } 533 } 534 type->num_levels = new_num_lvls; 535 return Success; 536} 537 538KeySym * 539XkbResizeKeySyms(XkbDescPtr xkb, int key, int needed) 540{ 541 register int i, nSyms, nKeySyms; 542 unsigned nOldSyms; 543 KeySym *newSyms; 544 545 if (needed == 0) { 546 xkb->map->key_sym_map[key].offset = 0; 547 return xkb->map->syms; 548 } 549 nOldSyms = XkbKeyNumSyms(xkb, key); 550 if (nOldSyms >= (unsigned) needed) { 551 return XkbKeySymsPtr(xkb, key); 552 } 553 if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) { 554 if (nOldSyms > 0) { 555 memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key), 556 nOldSyms * sizeof(KeySym)); 557 } 558 if ((needed - nOldSyms) > 0) { 559 bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)], 560 (needed - nOldSyms) * sizeof(KeySym)); 561 } 562 xkb->map->key_sym_map[key].offset = xkb->map->num_syms; 563 xkb->map->num_syms += needed; 564 return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; 565 } 566 xkb->map->size_syms += (needed > 32 ? needed : 32); 567 newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym); 568 if (newSyms == NULL) 569 return NULL; 570 newSyms[0] = NoSymbol; 571 nSyms = 1; 572 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 573 int nCopy; 574 575 nCopy = nKeySyms = XkbKeyNumSyms(xkb, i); 576 if ((nKeySyms == 0) && (i != key)) 577 continue; 578 if (i == key) 579 nKeySyms = needed; 580 if (nCopy != 0) 581 memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i), 582 nCopy * sizeof(KeySym)); 583 if (nKeySyms > nCopy) 584 bzero(&newSyms[nSyms + nCopy], (nKeySyms - nCopy) * sizeof(KeySym)); 585 xkb->map->key_sym_map[i].offset = nSyms; 586 nSyms += nKeySyms; 587 } 588 _XkbFree(xkb->map->syms); 589 xkb->map->syms = newSyms; 590 xkb->map->num_syms = nSyms; 591 return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; 592} 593 594static unsigned 595_ExtendRange(unsigned int old_flags, 596 unsigned int flag, 597 KeyCode newKC, 598 KeyCode *old_min, 599 unsigned char *old_num) 600{ 601 if ((old_flags & flag) == 0) { 602 old_flags |= flag; 603 *old_min = newKC; 604 *old_num = 1; 605 } 606 else { 607 int last = (*old_min) + (*old_num) - 1; 608 609 if (newKC < *old_min) { 610 *old_min = newKC; 611 *old_num = (last - newKC) + 1; 612 } 613 else if (newKC > last) { 614 *old_num = (newKC - (*old_min)) + 1; 615 } 616 } 617 return old_flags; 618} 619 620Status 621XkbChangeKeycodeRange(XkbDescPtr xkb, 622 int minKC, 623 int maxKC, 624 XkbChangesPtr changes) 625{ 626 int tmp; 627 628 if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode)) 629 return BadValue; 630 if (minKC > maxKC) 631 return BadMatch; 632 if (minKC < xkb->min_key_code) { 633 if (changes) 634 changes->map.min_key_code = minKC; 635 tmp = xkb->min_key_code - minKC; 636 if (xkb->map) { 637 if (xkb->map->key_sym_map) { 638 bzero((char *) &xkb->map->key_sym_map[minKC], 639 tmp * sizeof(XkbSymMapRec)); 640 if (changes) { 641 changes->map.changed = _ExtendRange(changes->map.changed, 642 XkbKeySymsMask, minKC, 643 &changes->map.first_key_sym, 644 &changes->map.num_key_syms); 645 } 646 } 647 if (xkb->map->modmap) { 648 bzero((char *) &xkb->map->modmap[minKC], tmp); 649 if (changes) { 650 changes->map.changed = _ExtendRange(changes->map.changed, 651 XkbModifierMapMask, minKC, 652 &changes->map.first_modmap_key, 653 &changes->map.num_modmap_keys); 654 } 655 } 656 } 657 if (xkb->server) { 658 if (xkb->server->behaviors) { 659 bzero((char *) &xkb->server->behaviors[minKC], 660 tmp * sizeof(XkbBehavior)); 661 if (changes) { 662 changes->map.changed = _ExtendRange(changes->map.changed, 663 XkbKeyBehaviorsMask, minKC, 664 &changes->map.first_key_behavior, 665 &changes->map.num_key_behaviors); 666 } 667 } 668 if (xkb->server->key_acts) { 669 bzero((char *) &xkb->server->key_acts[minKC], 670 tmp * sizeof(unsigned short)); 671 if (changes) { 672 changes->map.changed = _ExtendRange(changes->map.changed, 673 XkbKeyActionsMask, minKC, 674 &changes->map.first_key_act, 675 &changes->map.num_key_acts); 676 } 677 } 678 if (xkb->server->vmodmap) { 679 bzero((char *) &xkb->server->vmodmap[minKC], 680 tmp * sizeof(unsigned short)); 681 if (changes) { 682 changes->map.changed = _ExtendRange(changes->map.changed, 683 XkbVirtualModMapMask, minKC, 684 &changes->map.first_modmap_key, 685 &changes->map.num_vmodmap_keys); 686 } 687 } 688 } 689 if ((xkb->names) && (xkb->names->keys)) { 690 bzero((char *) &xkb->names->keys[minKC], 691 tmp * sizeof(XkbKeyNameRec)); 692 if (changes) { 693 changes->names.changed = _ExtendRange(changes->names.changed, 694 XkbKeyNamesMask, minKC, 695 &changes->names.first_key, 696 &changes->names.num_keys); 697 } 698 } 699 xkb->min_key_code = minKC; 700 } 701 if (maxKC > xkb->max_key_code) { 702 if (changes) 703 changes->map.max_key_code = maxKC; 704 tmp = maxKC - xkb->max_key_code; 705 if (xkb->map) { 706 if (xkb->map->key_sym_map) { 707 _XkbResizeArray(xkb->map->key_sym_map, xkb->max_key_code + 1, 708 (maxKC + 1), XkbSymMapRec); 709 if (!xkb->map->key_sym_map) { 710 return BadAlloc; 711 } 712 if (changes) { 713 changes->map.changed = _ExtendRange(changes->map.changed, 714 XkbKeySymsMask, maxKC, 715 &changes->map.first_key_sym, 716 &changes->map.num_key_syms); 717 } 718 } 719 if (xkb->map->modmap) { 720 _XkbResizeArray(xkb->map->modmap, xkb->max_key_code + 1, 721 (maxKC + 1), unsigned char); 722 if (!xkb->map->modmap) { 723 return BadAlloc; 724 } 725 if (changes) { 726 changes->map.changed = _ExtendRange(changes->map.changed, 727 XkbModifierMapMask, maxKC, 728 &changes->map.first_modmap_key, 729 &changes->map.num_modmap_keys); 730 } 731 } 732 } 733 if (xkb->server) { 734 if (xkb->server->behaviors) { 735 _XkbResizeArray(xkb->server->behaviors, xkb->max_key_code + 1, 736 (maxKC + 1), XkbBehavior); 737 if (!xkb->server->behaviors) { 738 return BadAlloc; 739 } 740 if (changes) { 741 changes->map.changed = _ExtendRange(changes->map.changed, 742 XkbKeyBehaviorsMask, maxKC, 743 &changes->map.first_key_behavior, 744 &changes->map.num_key_behaviors); 745 } 746 } 747 if (xkb->server->key_acts) { 748 _XkbResizeArray(xkb->server->key_acts, xkb->max_key_code + 1, 749 (maxKC + 1), unsigned short); 750 if (!xkb->server->key_acts) { 751 return BadAlloc; 752 } 753 if (changes) { 754 changes->map.changed = _ExtendRange(changes->map.changed, 755 XkbKeyActionsMask, maxKC, 756 &changes->map.first_key_act, 757 &changes->map.num_key_acts); 758 } 759 } 760 if (xkb->server->vmodmap) { 761 _XkbResizeArray(xkb->server->vmodmap, xkb->max_key_code + 1, 762 (maxKC + 1), unsigned short); 763 if (!xkb->server->vmodmap) { 764 return BadAlloc; 765 } 766 if (changes) { 767 changes->map.changed = _ExtendRange(changes->map.changed, 768 XkbVirtualModMapMask, maxKC, 769 &changes->map.first_modmap_key, 770 &changes->map.num_vmodmap_keys); 771 } 772 } 773 } 774 if ((xkb->names) && (xkb->names->keys)) { 775 _XkbResizeArray(xkb->names->keys, xkb->max_key_code + 1, 776 (maxKC + 1), XkbKeyNameRec); 777 if (!xkb->names->keys) { 778 return BadAlloc; 779 } 780 if (changes) { 781 changes->names.changed = _ExtendRange(changes->names.changed, 782 XkbKeyNamesMask, maxKC, 783 &changes->names.first_key, 784 &changes->names.num_keys); 785 } 786 } 787 xkb->max_key_code = maxKC; 788 } 789 return Success; 790} 791 792XkbAction * 793XkbResizeKeyActions(XkbDescPtr xkb, int key, int needed) 794{ 795 register int i, nActs; 796 XkbAction *newActs; 797 798 if (needed == 0) { 799 xkb->server->key_acts[key] = 0; 800 return NULL; 801 } 802 if (XkbKeyHasActions(xkb, key) && 803 (XkbKeyNumSyms(xkb, key) >= (unsigned) needed)) 804 return XkbKeyActionsPtr(xkb, key); 805 if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) { 806 xkb->server->key_acts[key] = xkb->server->num_acts; 807 xkb->server->num_acts += needed; 808 return &xkb->server->acts[xkb->server->key_acts[key]]; 809 } 810 xkb->server->size_acts = xkb->server->num_acts + needed + 8; 811 newActs = _XkbTypedCalloc(xkb->server->size_acts, XkbAction); 812 if (newActs == NULL) 813 return NULL; 814 newActs[0].type = XkbSA_NoAction; 815 nActs = 1; 816 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 817 int nKeyActs, nCopy; 818 819 if ((xkb->server->key_acts[i] == 0) && (i != key)) 820 continue; 821 822 nCopy = nKeyActs = XkbKeyNumActions(xkb, i); 823 if (i == key) { 824 nKeyActs = needed; 825 if (needed < nCopy) 826 nCopy = needed; 827 } 828 829 if (nCopy > 0) 830 memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i), 831 nCopy * sizeof(XkbAction)); 832 if (nCopy < nKeyActs) 833 bzero(&newActs[nActs + nCopy], 834 (nKeyActs - nCopy) * sizeof(XkbAction)); 835 xkb->server->key_acts[i] = nActs; 836 nActs += nKeyActs; 837 } 838 _XkbFree(xkb->server->acts); 839 xkb->server->acts = newActs; 840 xkb->server->num_acts = nActs; 841 return &xkb->server->acts[xkb->server->key_acts[key]]; 842} 843 844void 845XkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap) 846{ 847 XkbClientMapPtr map; 848 849 if ((xkb == NULL) || (xkb->map == NULL)) 850 return; 851 if (freeMap) 852 what = XkbAllClientInfoMask; 853 map = xkb->map; 854 if (what & XkbKeyTypesMask) { 855 if (map->types != NULL) { 856 if (map->num_types > 0) { 857 register int i; 858 XkbKeyTypePtr type; 859 860 for (i = 0, type = map->types; i < map->num_types; i++, type++) { 861 _XkbFree(type->map); 862 type->map = NULL; 863 864 _XkbFree(type->preserve); 865 type->preserve = NULL; 866 867 type->map_count = 0; 868 869 _XkbFree(type->level_names); 870 type->level_names = NULL; 871 } 872 } 873 _XkbFree(map->types); 874 map->num_types = map->size_types = 0; 875 map->types = NULL; 876 } 877 } 878 if (what & XkbKeySymsMask) { 879 _XkbFree(map->key_sym_map); 880 map->key_sym_map = NULL; 881 882 _XkbFree(map->syms); 883 map->size_syms = map->num_syms = 0; 884 map->syms = NULL; 885 } 886 if (what & XkbModifierMapMask) { 887 _XkbFree(map->modmap); 888 map->modmap = NULL; 889 } 890 if (freeMap) { 891 _XkbFree(xkb->map); 892 xkb->map = NULL; 893 } 894 return; 895} 896 897void 898XkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap) 899{ 900 XkbServerMapPtr map; 901 902 if ((xkb == NULL) || (xkb->server == NULL)) 903 return; 904 if (freeMap) 905 what = XkbAllServerInfoMask; 906 map = xkb->server; 907 if (what & XkbExplicitComponentsMask) { 908 _XkbFree(map->explicit); 909 map->explicit = NULL; 910 } 911 if (what & XkbKeyActionsMask) { 912 _XkbFree(map->key_acts); 913 map->key_acts = NULL; 914 915 _XkbFree(map->acts); 916 map->num_acts = map->size_acts = 0; 917 map->acts = NULL; 918 } 919 if (what & XkbKeyBehaviorsMask) { 920 _XkbFree(map->behaviors); 921 map->behaviors = NULL; 922 } 923 if (what & XkbVirtualModMapMask) { 924 _XkbFree(map->vmodmap); 925 map->vmodmap = NULL; 926 } 927 928 if (freeMap) { 929 _XkbFree(xkb->server); 930 xkb->server = NULL; 931 } 932 return; 933} 934