1/************************************************************ 2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25 ********************************************************/ 26 27#include "xkbcomp.h" 28#include "tokens.h" 29#include "expr.h" 30#include "keycodes.h" 31#include "misc.h" 32#include "alias.h" 33 34static Bool high_keycode_warned; 35 36char * 37longText(unsigned long val, unsigned format) 38{ 39 char buf[4]; 40 41 LongToKeyName(val, buf); 42 return XkbKeyNameText(buf, format); 43} 44 45/***====================================================================***/ 46 47void 48LongToKeyName(unsigned long val, char *name) 49{ 50 name[0] = ((val >> 24) & 0xff); 51 name[1] = ((val >> 16) & 0xff); 52 name[2] = ((val >> 8) & 0xff); 53 name[3] = (val & 0xff); 54 return; 55} 56 57/***====================================================================***/ 58 59typedef struct _IndicatorNameInfo 60{ 61 CommonInfo defs; 62 int ndx; 63 Atom name; 64 Bool virtual; 65} IndicatorNameInfo; 66 67typedef struct _KeyNamesInfo 68{ 69 char *name; /* e.g. evdev+aliases(qwerty) */ 70 int errorCount; 71 unsigned fileID; 72 unsigned merge; 73 int computedMin; /* lowest keycode stored */ 74 int computedMax; /* highest keycode stored */ 75 int explicitMin; 76 int explicitMax; 77 int effectiveMin; 78 int effectiveMax; 79 unsigned long names[XkbMaxLegalKeyCode + 1]; /* 4-letter name of key, keycode is the index */ 80 unsigned files[XkbMaxLegalKeyCode + 1]; 81 unsigned char has_alt_forms[XkbMaxLegalKeyCode + 1]; 82 IndicatorNameInfo *leds; 83 AliasInfo *aliases; 84} KeyNamesInfo; 85 86static void HandleKeycodesFile(XkbFile * file, 87 XkbDescPtr xkb, 88 unsigned merge, 89 KeyNamesInfo * info); 90 91static void 92InitIndicatorNameInfo(IndicatorNameInfo *ii, const KeyNamesInfo *info) 93{ 94 ii->defs.defined = 0; 95 ii->defs.merge = info->merge; 96 ii->defs.fileID = info->fileID; 97 ii->defs.next = NULL; 98 ii->ndx = 0; 99 ii->name = None; 100 ii->virtual = False; 101 return; 102} 103 104static void 105ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info) 106{ 107 if (ii == info->leds) 108 { 109 ClearCommonInfo(&ii->defs); 110 info->leds = NULL; 111 } 112 return; 113} 114 115static IndicatorNameInfo * 116NextIndicatorName(KeyNamesInfo * info) 117{ 118 IndicatorNameInfo *ii; 119 120 ii = malloc(sizeof(IndicatorNameInfo)); 121 if (ii) 122 { 123 InitIndicatorNameInfo(ii, info); 124 info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs, 125 (CommonInfo *) ii); 126 } 127 return ii; 128} 129 130static IndicatorNameInfo * 131FindIndicatorByIndex(KeyNamesInfo * info, int ndx) 132{ 133 for (IndicatorNameInfo *old = info->leds; old != NULL; 134 old = (IndicatorNameInfo *) old->defs.next) 135 { 136 if (old->ndx == ndx) 137 return old; 138 } 139 return NULL; 140} 141 142static IndicatorNameInfo * 143FindIndicatorByName(KeyNamesInfo * info, Atom name) 144{ 145 for (IndicatorNameInfo *old = info->leds; old != NULL; 146 old = (IndicatorNameInfo *) old->defs.next) 147 { 148 if (old->name == name) 149 return old; 150 } 151 return NULL; 152} 153 154static Bool 155AddIndicatorName(KeyNamesInfo * info, IndicatorNameInfo * new) 156{ 157 IndicatorNameInfo *old; 158 Bool replace; 159 160 replace = (new->defs.merge == MergeReplace) || 161 (new->defs.merge == MergeOverride); 162 old = FindIndicatorByName(info, new->name); 163 if (old) 164 { 165 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 166 || (warningLevel > 9)) 167 { 168 WARN("Multiple indicators named %s\n", 169 XkbAtomText(NULL, new->name, XkbMessage)); 170 if (old->ndx == new->ndx) 171 { 172 if (old->virtual != new->virtual) 173 { 174 if (replace) 175 old->virtual = new->virtual; 176 ACTION("Using %s instead of %s\n", 177 (old->virtual ? "virtual" : "real"), 178 (old->virtual ? "real" : "virtual")); 179 } 180 else 181 { 182 ACTION("Identical definitions ignored\n"); 183 } 184 return True; 185 } 186 else 187 { 188 if (replace) 189 ACTION("Ignoring %d, using %d\n", old->ndx, new->ndx); 190 else 191 ACTION("Using %d, ignoring %d\n", old->ndx, new->ndx); 192 } 193 if (replace) 194 { 195 if (info->leds == old) 196 info->leds = (IndicatorNameInfo *) old->defs.next; 197 else 198 { 199 for (IndicatorNameInfo *tmp = info->leds; tmp != NULL; 200 tmp = (IndicatorNameInfo *) tmp->defs.next) 201 { 202 if (tmp->defs.next == (CommonInfo *) old) 203 { 204 tmp->defs.next = old->defs.next; 205 break; 206 } 207 } 208 } 209 free(old); 210 } 211 } 212 } 213 old = FindIndicatorByIndex(info, new->ndx); 214 if (old) 215 { 216 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 217 || (warningLevel > 9)) 218 { 219 WARN("Multiple names for indicator %d\n", new->ndx); 220 if ((old->name == new->name) && (old->virtual == new->virtual)) 221 ACTION("Identical definitions ignored\n"); 222 else 223 { 224 const char *oldType, *newType; 225 Atom using, ignoring; 226 if (old->virtual) 227 oldType = "virtual indicator"; 228 else 229 oldType = "real indicator"; 230 if (new->virtual) 231 newType = "virtual indicator"; 232 else 233 newType = "real indicator"; 234 if (replace) 235 { 236 using = new->name; 237 ignoring = old->name; 238 } 239 else 240 { 241 using = old->name; 242 ignoring = new->name; 243 } 244 ACTION("Using %s %s, ignoring %s %s\n", 245 oldType, XkbAtomText(NULL, using, XkbMessage), 246 newType, XkbAtomText(NULL, ignoring, XkbMessage)); 247 } 248 } 249 if (replace) 250 { 251 old->name = new->name; 252 old->virtual = new->virtual; 253 } 254 return True; 255 } 256 old = new; 257 new = NextIndicatorName(info); 258 if (!new) 259 { 260 WSGO("Couldn't allocate name for indicator %d\n", old->ndx); 261 ACTION("Ignored\n"); 262 return False; 263 } 264 new->name = old->name; 265 new->ndx = old->ndx; 266 new->virtual = old->virtual; 267 return True; 268} 269 270static void 271ClearKeyNamesInfo(KeyNamesInfo * info) 272{ 273 free(info->name); 274 info->name = NULL; 275 info->computedMax = info->explicitMax = info->explicitMin = -1; 276 info->computedMin = 256; 277 info->effectiveMin = 8; 278 info->effectiveMax = 255; 279 bzero(info->names, sizeof(info->names)); 280 bzero(info->files, sizeof(info->files)); 281 bzero(info->has_alt_forms, sizeof(info->has_alt_forms)); 282 if (info->leds) 283 ClearIndicatorNameInfo(info->leds, info); 284 if (info->aliases) 285 ClearAliases(&info->aliases); 286 return; 287} 288 289static void 290InitKeyNamesInfo(KeyNamesInfo * info) 291{ 292 info->name = NULL; 293 info->leds = NULL; 294 info->aliases = NULL; 295 ClearKeyNamesInfo(info); 296 info->errorCount = 0; 297 return; 298} 299 300static int 301FindKeyByLong(const KeyNamesInfo *info, unsigned long name) 302{ 303 for (int i = info->effectiveMin; i <= info->effectiveMax; i++) 304 { 305 if (info->names[i] == name) 306 return i; 307 } 308 return 0; 309} 310 311/** 312 * Store the name of the key as a long in the info struct under the given 313 * keycode. If the same keys is referred to twice, print a warning. 314 * Note that the key's name is stored as a long, the keycode is the index. 315 */ 316static Bool 317AddKeyName(KeyNamesInfo *info, int kc, const char *name, 318 unsigned merge, unsigned fileID, Bool reportCollisions) 319{ 320 int old; 321 unsigned long lval; 322 323 if ((kc < info->effectiveMin) || (kc > info->effectiveMax)) 324 { 325 if (!high_keycode_warned && warningLevel > 1) 326 { 327 INFO("Keycodes above %d (e.g. <%s>) are not supported by X and are ignored\n", 328 kc, name); 329 high_keycode_warned = True; 330 } 331 return True; 332 } 333 if (kc < info->computedMin) 334 info->computedMin = kc; 335 if (kc > info->computedMax) 336 info->computedMax = kc; 337 lval = KeyNameToLong(name); 338 339 if (reportCollisions) 340 { 341 reportCollisions = ((warningLevel > 7) || 342 ((warningLevel > 0) 343 && (fileID == info->files[kc]))); 344 } 345 346 if (info->names[kc] != 0) 347 { 348 char buf[6]; 349 350 LongToKeyName(info->names[kc], buf); 351 buf[4] = '\0'; 352 if (info->names[kc] == lval) 353 { 354 if (info->has_alt_forms[kc] || (merge == MergeAltForm)) 355 { 356 info->has_alt_forms[kc] = True; 357 } 358 else if (reportCollisions) 359 { 360 WARN("Multiple identical key name definitions\n"); 361 ACTION("Later occurrences of \"<%s> = %d\" ignored\n", 362 buf, kc); 363 } 364 return True; 365 } 366 if (merge == MergeAugment) 367 { 368 if (reportCollisions) 369 { 370 WARN("Multiple names for keycode %d\n", kc); 371 ACTION("Using <%s>, ignoring <%s>\n", buf, name); 372 } 373 return True; 374 } 375 else 376 { 377 if (reportCollisions) 378 { 379 WARN("Multiple names for keycode %d\n", kc); 380 ACTION("Using <%s>, ignoring <%s>\n", name, buf); 381 } 382 info->names[kc] = 0; 383 info->files[kc] = 0; 384 } 385 } 386 old = FindKeyByLong(info, lval); 387 if ((old != 0) && (old != kc)) 388 { 389 if (merge == MergeOverride) 390 { 391 info->names[old] = 0; 392 info->files[old] = 0; 393 info->has_alt_forms[old] = True; 394 if (reportCollisions) 395 { 396 WARN("Key name <%s> assigned to multiple keys\n", name); 397 ACTION("Using %d, ignoring %d\n", kc, old); 398 } 399 } 400 else if (merge != MergeAltForm) 401 { 402 if ((reportCollisions) && (warningLevel > 3)) 403 { 404 WARN("Key name <%s> assigned to multiple keys\n", name); 405 ACTION("Using %d, ignoring %d\n", old, kc); 406 ACTION 407 ("Use 'alternate' keyword to assign the same name to multiple keys\n"); 408 } 409 return True; 410 } 411 else 412 { 413 info->has_alt_forms[old] = True; 414 } 415 } 416 info->names[kc] = lval; 417 info->files[kc] = fileID; 418 info->has_alt_forms[kc] = (merge == MergeAltForm); 419 return True; 420} 421 422/***====================================================================***/ 423 424static void 425MergeIncludedKeycodes(KeyNamesInfo * into, KeyNamesInfo * from, 426 unsigned merge) 427{ 428 if (from->errorCount > 0) 429 { 430 into->errorCount += from->errorCount; 431 return; 432 } 433 if (into->name == NULL) 434 { 435 into->name = from->name; 436 from->name = NULL; 437 } 438 for (int i = from->computedMin; i <= from->computedMax; i++) 439 { 440 unsigned thisMerge; 441 char buf[5]; 442 443 if (from->names[i] == 0) 444 continue; 445 LongToKeyName(from->names[i], buf); 446 buf[4] = '\0'; 447 if (from->has_alt_forms[i]) 448 thisMerge = MergeAltForm; 449 else 450 thisMerge = merge; 451 if (!AddKeyName(into, i, buf, thisMerge, from->fileID, False)) 452 into->errorCount++; 453 } 454 if (from->leds) 455 { 456 IndicatorNameInfo *led, *next; 457 for (led = from->leds; led != NULL; led = next) 458 { 459 if (merge != MergeDefault) 460 led->defs.merge = merge; 461 if (!AddIndicatorName(into, led)) 462 into->errorCount++; 463 next = (IndicatorNameInfo *) led->defs.next; 464 } 465 } 466 if (!MergeAliases(&into->aliases, &from->aliases, merge)) 467 into->errorCount++; 468 if (from->explicitMin > 0) 469 { 470 if ((into->explicitMin < 0) 471 || (into->explicitMin > from->explicitMin)) 472 into->effectiveMin = into->explicitMin = from->explicitMin; 473 } 474 if (from->explicitMax > 0) 475 { 476 if ((into->explicitMax < 0) 477 || (into->explicitMax < from->explicitMax)) 478 into->effectiveMax = into->explicitMax = from->explicitMax; 479 } 480 return; 481} 482 483/** 484 * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)"). 485 * 486 * @param stmt The include statement from the keymap file. 487 * @param xkb Unused for all but the xkb->flags. 488 * @param info Struct to store the key info in. 489 */ 490static Bool 491HandleIncludeKeycodes(IncludeStmt * stmt, XkbDescPtr xkb, KeyNamesInfo * info) 492{ 493 unsigned newMerge; 494 XkbFile *rtrn; 495 KeyNamesInfo included = {NULL}; 496 Bool haveSelf; 497 498 haveSelf = False; 499 if ((stmt->file == NULL) && (stmt->map == NULL)) 500 { 501 haveSelf = True; 502 included = *info; 503 bzero(info, sizeof(KeyNamesInfo)); 504 } 505 else if (strcmp(stmt->file, "computed") == 0) 506 { 507 xkb->flags |= AutoKeyNames; 508 info->explicitMin = XkbMinLegalKeyCode; 509 info->explicitMax = XkbMaxLegalKeyCode; 510 return (info->errorCount == 0); 511 } /* parse file, store returned info in the xkb struct */ 512 else if (ProcessIncludeFile(stmt, XkmKeyNamesIndex, &rtrn, &newMerge)) 513 { 514 InitKeyNamesInfo(&included); 515 HandleKeycodesFile(rtrn, xkb, MergeOverride, &included); 516 if (stmt->stmt != NULL) 517 { 518 free(included.name); 519 included.name = stmt->stmt; 520 stmt->stmt = NULL; 521 } 522 } 523 else 524 { 525 info->errorCount += 10; /* XXX: why 10?? */ 526 return False; 527 } 528 /* Do we have more than one include statement? */ 529 if ((stmt->next != NULL) && (included.errorCount < 1)) 530 { 531 unsigned op; 532 KeyNamesInfo next_incl; 533 534 for (IncludeStmt *next = stmt->next; next != NULL; next = next->next) 535 { 536 if ((next->file == NULL) && (next->map == NULL)) 537 { 538 haveSelf = True; 539 MergeIncludedKeycodes(&included, info, next->merge); 540 ClearKeyNamesInfo(info); 541 } 542 else if (ProcessIncludeFile(next, XkmKeyNamesIndex, &rtrn, &op)) 543 { 544 InitKeyNamesInfo(&next_incl); 545 HandleKeycodesFile(rtrn, xkb, MergeOverride, &next_incl); 546 MergeIncludedKeycodes(&included, &next_incl, op); 547 ClearKeyNamesInfo(&next_incl); 548 } 549 else 550 { 551 info->errorCount += 10; /* XXX: Why 10?? */ 552 return False; 553 } 554 } 555 } 556 if (haveSelf) 557 *info = included; 558 else 559 { 560 MergeIncludedKeycodes(info, &included, newMerge); 561 ClearKeyNamesInfo(&included); 562 } 563 return (info->errorCount == 0); 564} 565 566/** 567 * Parse the given statement and store the output in the info struct. 568 * e.g. <ESC> = 9 569 */ 570static int 571HandleKeycodeDef(const KeycodeDef *stmt, unsigned merge, KeyNamesInfo *info) 572{ 573 int code; 574 ExprResult result; 575 576 if (!ExprResolveInteger(stmt->value, &result, NULL, NULL)) 577 { 578 ACTION("No value keycode assigned to name <%s>\n", stmt->name); 579 return 0; 580 } 581 code = result.ival; 582 if ((code < info->effectiveMin) || (code > info->effectiveMax)) 583 { 584 if (!high_keycode_warned && warningLevel > 1) 585 { 586 INFO("Keycodes above %d (e.g. <%s>) are not supported by X and are ignored\n", 587 code, stmt->name); 588 high_keycode_warned = True; 589 } 590 return 1; 591 } 592 if (stmt->merge != MergeDefault) 593 { 594 if (stmt->merge == MergeReplace) 595 merge = MergeOverride; 596 else 597 merge = stmt->merge; 598 } 599 return AddKeyName(info, code, stmt->name, merge, info->fileID, True); 600} 601 602#define MIN_KEYCODE_DEF 0 603#define MAX_KEYCODE_DEF 1 604 605/** 606 * Handle the minimum/maximum statement of the xkb file. 607 * Sets explicitMin/Max and effectiveMin/Max of the info struct. 608 * 609 * @return 1 on success, 0 otherwise. 610 */ 611static int 612HandleKeyNameVar(const VarDef *stmt, KeyNamesInfo *info) 613{ 614 ExprResult tmp, field; 615 ExprDef *arrayNdx; 616 int which; 617 618 if (ExprResolveLhs(stmt->name, &tmp, &field, &arrayNdx) == 0) 619 return 0; /* internal error, already reported */ 620 621 if (tmp.str != NULL) 622 { 623 ERROR("Unknown element %s encountered\n", tmp.str); 624 ACTION("Default for field %s ignored\n", field.str); 625 return 0; 626 } 627 if (uStrCaseCmp(field.str, "minimum") == 0) 628 which = MIN_KEYCODE_DEF; 629 else if (uStrCaseCmp(field.str, "maximum") == 0) 630 which = MAX_KEYCODE_DEF; 631 else 632 { 633 ERROR("Unknown field encountered\n"); 634 ACTION("Assignment to field %s ignored\n", field.str); 635 return 0; 636 } 637 if (arrayNdx != NULL) 638 { 639 ERROR("The %s setting is not an array\n", field.str); 640 ACTION("Illegal array reference ignored\n"); 641 return 0; 642 } 643 644 if (ExprResolveInteger(stmt->value, &tmp, NULL, NULL) == 0) 645 { 646 ACTION("Assignment to field %s ignored\n", field.str); 647 return 0; 648 } 649 if ((tmp.ival < XkbMinLegalKeyCode)) 650 { 651 ERROR 652 ("Illegal keycode %d (must be in the range %d-%d inclusive)\n", 653 tmp.ival, XkbMinLegalKeyCode, XkbMaxLegalKeyCode); 654 ACTION("Value of \"%s\" not changed\n", field.str); 655 return 0; 656 } 657 if ((tmp.ival > XkbMaxLegalKeyCode)) 658 { 659 WARN("Unsupported maximum keycode %d, clipping.\n", tmp.ival); 660 ACTION("X11 cannot support keycodes above 255.\n"); 661 info->explicitMax = XkbMaxLegalKeyCode; 662 info->effectiveMax = XkbMaxLegalKeyCode; 663 return 1; 664 } 665 if (which == MIN_KEYCODE_DEF) 666 { 667 if ((info->explicitMax > 0) && (info->explicitMax < tmp.ival)) 668 { 669 ERROR 670 ("Minimum key code (%d) must be <= maximum key code (%d)\n", 671 tmp.ival, info->explicitMax); 672 ACTION("Minimum key code value not changed\n"); 673 return 0; 674 } 675 if ((info->computedMax > 0) && (info->computedMin < tmp.ival)) 676 { 677 ERROR 678 ("Minimum key code (%d) must be <= lowest defined key (%d)\n", 679 tmp.ival, info->computedMin); 680 ACTION("Minimum key code value not changed\n"); 681 return 0; 682 } 683 info->explicitMin = tmp.ival; 684 info->effectiveMin = tmp.ival; 685 } 686 if (which == MAX_KEYCODE_DEF) 687 { 688 if ((info->explicitMin > 0) && (info->explicitMin > tmp.ival)) 689 { 690 ERROR("Maximum code (%d) must be >= minimum key code (%d)\n", 691 tmp.ival, info->explicitMin); 692 ACTION("Maximum code value not changed\n"); 693 return 0; 694 } 695 if ((info->computedMax > 0) && (info->computedMax > tmp.ival)) 696 { 697 ERROR 698 ("Maximum code (%d) must be >= highest defined key (%d)\n", 699 tmp.ival, info->computedMax); 700 ACTION("Maximum code value not changed\n"); 701 return 0; 702 } 703 info->explicitMax = tmp.ival; 704 info->effectiveMax = tmp.ival; 705 } 706 return 1; 707} 708 709static int 710HandleIndicatorNameDef(const IndicatorNameDef *def, 711 unsigned merge, KeyNamesInfo * info) 712{ 713 IndicatorNameInfo ii; 714 ExprResult tmp; 715 716 if ((def->ndx < 1) || (def->ndx > XkbNumIndicators)) 717 { 718 info->errorCount++; 719 ERROR("Name specified for illegal indicator index %d\n", def->ndx); 720 ACTION("Ignored\n"); 721 return False; 722 } 723 InitIndicatorNameInfo(&ii, info); 724 ii.ndx = def->ndx; 725 if (!ExprResolveString(def->name, &tmp, NULL, NULL)) 726 { 727 char buf[20]; 728 snprintf(buf, sizeof(buf), "%d", def->ndx); 729 info->errorCount++; 730 return ReportBadType("indicator", "name", buf, "string"); 731 } 732 ii.name = XkbInternAtom(NULL, tmp.str, False); 733 ii.virtual = def->virtual; 734 if (!AddIndicatorName(info, &ii)) 735 return False; 736 return True; 737} 738 739/** 740 * Handle the xkb_keycodes section of a xkb file. 741 * All information about parsed keys is stored in the info struct. 742 * 743 * Such a section may have include statements, in which case this function is 744 * semi-recursive (it calls HandleIncludeKeycodes, which may call 745 * HandleKeycodesFile again). 746 * 747 * @param file The input file (parsed xkb_keycodes section) 748 * @param xkb Necessary to pass down, may have flags changed. 749 * @param merge Merge strategy (MergeOverride, etc.) 750 * @param info Struct to contain the fully parsed key information. 751 */ 752static void 753HandleKeycodesFile(XkbFile * file, 754 XkbDescPtr xkb, unsigned merge, KeyNamesInfo * info) 755{ 756 ParseCommon *stmt; 757 758 info->name = uStringDup(file->name); 759 stmt = file->defs; 760 while (stmt) 761 { 762 switch (stmt->stmtType) 763 { 764 case StmtInclude: /* e.g. include "evdev+aliases(qwerty)" */ 765 if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info)) 766 info->errorCount++; 767 break; 768 case StmtKeycodeDef: /* e.g. <ESC> = 9; */ 769 if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info)) 770 info->errorCount++; 771 break; 772 case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */ 773 if (!HandleAliasDef((KeyAliasDef *) stmt, 774 merge, info->fileID, &info->aliases)) 775 info->errorCount++; 776 break; 777 case StmtVarDef: /* e.g. minimum, maximum */ 778 if (!HandleKeyNameVar((VarDef *) stmt, info)) 779 info->errorCount++; 780 break; 781 case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */ 782 if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt, 783 merge, info)) 784 { 785 info->errorCount++; 786 } 787 break; 788 case StmtInterpDef: 789 case StmtVModDef: 790 ERROR("Keycode files may define key and indicator names only\n"); 791 ACTION("Ignoring definition of %s\n", 792 ((stmt->stmtType == 793 StmtInterpDef) ? "a symbol interpretation" : 794 "virtual modifiers")); 795 info->errorCount++; 796 break; 797 default: 798 WSGO("Unexpected statement type %d in HandleKeycodesFile\n", 799 stmt->stmtType); 800 break; 801 } 802 stmt = stmt->next; 803 if (info->errorCount > 10) 804 { 805#ifdef NOISY 806 ERROR("Too many errors\n"); 807#endif 808 ACTION("Abandoning keycodes file \"%s\"\n", file->topName); 809 break; 810 } 811 } 812 return; 813} 814 815/** 816 * Compile the xkb_keycodes section, parse it's output, return the results. 817 * 818 * @param file The parsed XKB file (may have include statements requiring 819 * further parsing) 820 * @param result The effective keycodes, as gathered from the file. 821 * @param merge Merge strategy. 822 * 823 * @return True on success, False otherwise. 824 */ 825Bool 826CompileKeycodes(XkbFile * file, XkbFileInfo * result, unsigned merge) 827{ 828 KeyNamesInfo info; /* contains all the info after parsing */ 829 XkbDescPtr xkb; 830 831 xkb = result->xkb; 832 InitKeyNamesInfo(&info); 833 HandleKeycodesFile(file, xkb, merge, &info); 834 835 /* all the keys are now stored in info */ 836 837 if (info.errorCount == 0) 838 { 839 if (info.explicitMin > 0) /* if "minimum" statement was present */ 840 xkb->min_key_code = info.effectiveMin; 841 else 842 xkb->min_key_code = info.computedMin; 843 if (info.explicitMax > 0) /* if "maximum" statement was present */ 844 xkb->max_key_code = info.effectiveMax; 845 else 846 xkb->max_key_code = info.computedMax; 847 if (XkbAllocNames(xkb, XkbKeyNamesMask | XkbIndicatorNamesMask, 0, 0) 848 == Success) 849 { 850 int i; 851 xkb->names->keycodes = XkbInternAtom(xkb->dpy, info.name, False); 852 uDEBUG2(1, "key range: %d..%d\n", xkb->min_key_code, 853 xkb->max_key_code); 854 for (i = info.computedMin; i <= info.computedMax; i++) 855 { 856 LongToKeyName(info.names[i], xkb->names->keys[i].name); 857 uDEBUG2(2, "key %d = %s\n", i, 858 XkbKeyNameText(xkb->names->keys[i].name, XkbMessage)); 859 } 860 } 861 else 862 { 863 WSGO("Cannot create XkbNamesRec in CompileKeycodes\n"); 864 return False; 865 } 866 if (info.leds) 867 { 868 IndicatorNameInfo *ii; 869 if (XkbAllocIndicatorMaps(xkb) != Success) 870 { 871 WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n"); 872 ACTION("Physical indicators not set\n"); 873 } 874 for (ii = info.leds; ii != NULL; 875 ii = (IndicatorNameInfo *) ii->defs.next) 876 { 877 xkb->names->indicators[ii->ndx - 1] = 878 XkbInternAtom(xkb->dpy, 879 XkbAtomGetString(NULL, ii->name), False); 880 if (xkb->indicators != NULL) 881 { 882 unsigned bit = 1U << (ii->ndx - 1); 883 884 if (ii->virtual) 885 xkb->indicators->phys_indicators &= ~bit; 886 else 887 xkb->indicators->phys_indicators |= bit; 888 } 889 } 890 } 891 if (info.aliases) 892 ApplyAliases(xkb, False, &info.aliases); 893 return True; 894 } 895 ClearKeyNamesInfo(&info); 896 return False; 897} 898