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