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 "xkbpath.h" 29#include "tokens.h" 30#include "keycodes.h" 31#include "misc.h" 32#include <X11/keysym.h> 33#include "parseutils.h" 34 35#include <X11/extensions/XKBgeom.h> 36 37/***====================================================================***/ 38 39/** 40 * Open the file given in the include statement and parse it's content. 41 * If the statement defines a specific map to use, this map is returned in 42 * file_rtrn. Otherwise, the default map is returned. 43 * 44 * @param stmt The include statement, specifying the file name to look for. 45 * @param file_type Type of file (XkmKeyNamesIdx, etc.) 46 * @param file_rtrn Returns the key map to be used. 47 * @param merge_rtrn Always returns stmt->merge. 48 * 49 * @return True on success or False otherwise. 50 */ 51Bool 52ProcessIncludeFile(IncludeStmt * stmt, 53 unsigned file_type, 54 XkbFile ** file_rtrn, unsigned *merge_rtrn) 55{ 56 XkbFile *rtrn, *mapToUse; 57 char oldFile[1024] = {0}; 58 int oldLine = lineNum; 59 60 rtrn = XkbFindFileInCache(stmt->file, file_type, &stmt->path); 61 if (rtrn == NULL) 62 { 63 /* file not in cache, open it, parse it and store it in cache for next 64 time. */ 65 FILE *file = XkbFindFileInPath(stmt->file, file_type, &stmt->path); 66 if (file == NULL) 67 { 68 ERROR("Can't find file \"%s\" for %s include\n", stmt->file, 69 XkbDirectoryForInclude(file_type)); 70 ACTION("Exiting\n"); 71 return False; 72 } 73 strcpy(oldFile, scanFile); 74 oldLine = lineNum; 75 setScanState(stmt->file, 1); 76#ifdef DEBUG 77 if (debugFlags & 2) 78 INFO("About to parse include file %s\n", stmt->file); 79#endif 80 /* parse the file */ 81 if ((XKBParseFile(file, &rtrn) == 0) || (rtrn == NULL)) 82 { 83 setScanState(oldFile, oldLine); 84 ERROR("Error interpreting include file \"%s\"\n", stmt->file); 85 ACTION("Exiting\n"); 86 fclose(file); 87 return False; 88 } 89 fclose(file); 90 XkbAddFileToCache(stmt->file, file_type, stmt->path, rtrn); 91 } 92 93 /* 94 * A single file may contain several maps. Here's how we choose the map: 95 * - If a specific map was requested, look for it exclusively. 96 * - Otherwise, if the file only contains a single map, return it. 97 * - Otherwise, if the file has maps tagged as default, return the 98 * first one. 99 * - If all fails, return the first map in the file. 100 */ 101 mapToUse = rtrn; 102 if (stmt->map != NULL) 103 { 104 while ((mapToUse) && ((!uStringEqual(mapToUse->name, stmt->map)) || 105 (mapToUse->type != file_type))) 106 { 107 mapToUse = (XkbFile *) mapToUse->common.next; 108 } 109 if (!mapToUse) 110 { 111 ERROR("No %s named \"%s\" in the include file \"%s\"\n", 112 XkbConfigText(file_type, XkbMessage), stmt->map, 113 stmt->file); 114 ACTION("Exiting\n"); 115 return False; 116 } 117 } 118 else if (rtrn->common.next != NULL) 119 { 120 while ((mapToUse) && !(mapToUse->flags & XkbLC_Default)) 121 { 122 mapToUse = (XkbFile *) mapToUse->common.next; 123 } 124 if (!mapToUse) 125 { 126 if (warningLevel > 5) 127 { 128 WARN("No map in include statement, but \"%s\" contains several without a default map\n", 129 stmt->file); 130 ACTION("Using first defined map, \"%s\"\n", rtrn->name); 131 } 132 mapToUse = rtrn; 133 } 134 } 135 136 setScanState(oldFile, oldLine); 137 if (mapToUse->type != file_type) 138 { 139 ERROR("Include file wrong type (expected %s, got %s)\n", 140 XkbConfigText(file_type, XkbMessage), 141 XkbConfigText(mapToUse->type, XkbMessage)); 142 ACTION("Include file \"%s\" ignored\n", stmt->file); 143 return False; 144 } 145 /* FIXME: we have to check recursive includes here (or somewhere) */ 146 147 mapToUse->compiled = True; 148 *file_rtrn = mapToUse; 149 *merge_rtrn = stmt->merge; 150 return True; 151} 152 153/***====================================================================***/ 154 155int 156ReportNotArray(const char *type, const char *field, const char *name) 157{ 158 ERROR("The %s %s field is not an array\n", type, field); 159 ACTION("Ignoring illegal assignment in %s\n", name); 160 return False; 161} 162 163int 164ReportShouldBeArray(const char *type, const char *field, char *name) 165{ 166 ERROR("Missing subscript for %s %s\n", type, field); 167 ACTION("Ignoring illegal assignment in %s\n", name); 168 return False; 169} 170 171int 172ReportBadType(const char *type, const char *field, 173 const char *name, const char *wanted) 174{ 175 ERROR("The %s %s field must be a %s\n", type, field, wanted); 176 ACTION("Ignoring illegal assignment in %s\n", name); 177 return False; 178} 179 180#if 0 181int 182ReportBadIndexType(char *type, char *field, char *name, char *wanted) 183{ 184 ERROR("Index for the %s %s field must be a %s\n", type, field, wanted); 185 ACTION("Ignoring assignment to illegal field in %s\n", name); 186 return False; 187} 188#endif 189 190int 191ReportBadField(const char *type, const char *field, const char *name) 192{ 193 ERROR("Unknown %s field %s in %s\n", type, field, name); 194 ACTION("Ignoring assignment to unknown field in %s\n", name); 195 return False; 196} 197 198#if 0 199int 200ReportMultipleDefs(char *type, char *field, char *name) 201{ 202 WARN("Multiple definitions of %s in %s \"%s\"\n", field, type, name); 203 ACTION("Using last definition\n"); 204 return False; 205} 206#endif 207 208/***====================================================================***/ 209 210Bool 211UseNewField(unsigned field, const CommonInfo *oldDefs, 212 const CommonInfo *newDefs, unsigned *pCollide) 213{ 214 Bool useNew; 215 216 useNew = False; 217 if (oldDefs->defined & field) 218 { 219 if (newDefs->defined & field) 220 { 221 if (((oldDefs->fileID == newDefs->fileID) 222 && (warningLevel > 0)) || (warningLevel > 9)) 223 { 224 *pCollide |= field; 225 } 226 if (newDefs->merge != MergeAugment) 227 useNew = True; 228 } 229 } 230 else if (newDefs->defined & field) 231 useNew = True; 232 return useNew; 233} 234 235#if 0 236static Bool 237MergeNewField(unsigned field, const CommonInfo *oldDefs, 238 const CommonInfo *newDefs, unsigned *pCollide) 239{ 240 if ((oldDefs->defined & field) && (newDefs->defined & field)) 241 { 242 if (((oldDefs->fileID == newDefs->fileID) && (warningLevel > 0)) || 243 (warningLevel > 9)) 244 { 245 *pCollide |= field; 246 } 247 if (newDefs->merge == MergeAugment) 248 return True; 249 } 250 return False; 251} 252#endif 253 254XPointer 255ClearCommonInfo(CommonInfo * cmn) 256{ 257 if (cmn != NULL) 258 { 259 CommonInfo *this, *next; 260 for (this = cmn; this != NULL; this = next) 261 { 262 next = this->next; 263 free(this); 264 } 265 } 266 return NULL; 267} 268 269XPointer 270AddCommonInfo(CommonInfo * old, CommonInfo * new) 271{ 272 CommonInfo *first; 273 274 first = old; 275 while (old && old->next) 276 { 277 old = old->next; 278 } 279 new->next = NULL; 280 if (old) 281 { 282 old->next = new; 283 return (XPointer) first; 284 } 285 return (XPointer) new; 286} 287 288/***====================================================================***/ 289 290typedef struct _KeyNameDesc 291{ 292 KeySym level1; 293 KeySym level2; 294 char name[5]; 295 Bool used; 296} KeyNameDesc; 297 298static KeyNameDesc dfltKeys[] = { 299 {XK_Escape, NoSymbol, "ESC\0", 0}, 300 {XK_quoteleft, XK_asciitilde, "TLDE", 0}, 301 {XK_1, XK_exclam, "AE01", 0}, 302 {XK_2, XK_at, "AE02", 0}, 303 {XK_3, XK_numbersign, "AE03", 0}, 304 {XK_4, XK_dollar, "AE04", 0}, 305 {XK_5, XK_percent, "AE05", 0}, 306 {XK_6, XK_asciicircum, "AE06", 0}, 307 {XK_7, XK_ampersand, "AE07", 0}, 308 {XK_8, XK_asterisk, "AE08", 0}, 309 {XK_9, XK_parenleft, "AE09", 0}, 310 {XK_0, XK_parenright, "AE10", 0}, 311 {XK_minus, XK_underscore, "AE11", 0}, 312 {XK_equal, XK_plus, "AE12", 0}, 313 {XK_BackSpace, NoSymbol, "BKSP", 0}, 314 {XK_Tab, NoSymbol, "TAB\0", 0}, 315 {XK_q, XK_Q, "AD01", 0}, 316 {XK_w, XK_W, "AD02", 0}, 317 {XK_e, XK_E, "AD03", 0}, 318 {XK_r, XK_R, "AD04", 0}, 319 {XK_t, XK_T, "AD05", 0}, 320 {XK_y, XK_Y, "AD06", 0}, 321 {XK_u, XK_U, "AD07", 0}, 322 {XK_i, XK_I, "AD08", 0}, 323 {XK_o, XK_O, "AD09", 0}, 324 {XK_p, XK_P, "AD10", 0}, 325 {XK_bracketleft, XK_braceleft, "AD11", 0}, 326 {XK_bracketright, XK_braceright, "AD12", 0}, 327 {XK_Return, NoSymbol, "RTRN", 0}, 328 {XK_Caps_Lock, NoSymbol, "CAPS", 0}, 329 {XK_a, XK_A, "AC01", 0}, 330 {XK_s, XK_S, "AC02", 0}, 331 {XK_d, XK_D, "AC03", 0}, 332 {XK_f, XK_F, "AC04", 0}, 333 {XK_g, XK_G, "AC05", 0}, 334 {XK_h, XK_H, "AC06", 0}, 335 {XK_j, XK_J, "AC07", 0}, 336 {XK_k, XK_K, "AC08", 0}, 337 {XK_l, XK_L, "AC09", 0}, 338 {XK_semicolon, XK_colon, "AC10", 0}, 339 {XK_quoteright, XK_quotedbl, "AC11", 0}, 340 {XK_Shift_L, NoSymbol, "LFSH", 0}, 341 {XK_z, XK_Z, "AB01", 0}, 342 {XK_x, XK_X, "AB02", 0}, 343 {XK_c, XK_C, "AB03", 0}, 344 {XK_v, XK_V, "AB04", 0}, 345 {XK_b, XK_B, "AB05", 0}, 346 {XK_n, XK_N, "AB06", 0}, 347 {XK_m, XK_M, "AB07", 0}, 348 {XK_comma, XK_less, "AB08", 0}, 349 {XK_period, XK_greater, "AB09", 0}, 350 {XK_slash, XK_question, "AB10", 0}, 351 {XK_backslash, XK_bar, "BKSL", 0}, 352 {XK_Control_L, NoSymbol, "LCTL", 0}, 353 {XK_space, NoSymbol, "SPCE", 0}, 354 {XK_Shift_R, NoSymbol, "RTSH", 0}, 355 {XK_Alt_L, NoSymbol, "LALT", 0}, 356 {XK_space, NoSymbol, "SPCE", 0}, 357 {XK_Control_R, NoSymbol, "RCTL", 0}, 358 {XK_Alt_R, NoSymbol, "RALT", 0}, 359 {XK_F1, NoSymbol, "FK01", 0}, 360 {XK_F2, NoSymbol, "FK02", 0}, 361 {XK_F3, NoSymbol, "FK03", 0}, 362 {XK_F4, NoSymbol, "FK04", 0}, 363 {XK_F5, NoSymbol, "FK05", 0}, 364 {XK_F6, NoSymbol, "FK06", 0}, 365 {XK_F7, NoSymbol, "FK07", 0}, 366 {XK_F8, NoSymbol, "FK08", 0}, 367 {XK_F9, NoSymbol, "FK09", 0}, 368 {XK_F10, NoSymbol, "FK10", 0}, 369 {XK_F11, NoSymbol, "FK11", 0}, 370 {XK_F12, NoSymbol, "FK12", 0}, 371 {XK_Print, NoSymbol, "PRSC", 0}, 372 {XK_Scroll_Lock, NoSymbol, "SCLK", 0}, 373 {XK_Pause, NoSymbol, "PAUS", 0}, 374 {XK_Insert, NoSymbol, "INS\0", 0}, 375 {XK_Home, NoSymbol, "HOME", 0}, 376 {XK_Prior, NoSymbol, "PGUP", 0}, 377 {XK_Delete, NoSymbol, "DELE", 0}, 378 {XK_End, NoSymbol, "END", 0}, 379 {XK_Next, NoSymbol, "PGDN", 0}, 380 {XK_Up, NoSymbol, "UP\0\0", 0}, 381 {XK_Left, NoSymbol, "LEFT", 0}, 382 {XK_Down, NoSymbol, "DOWN", 0}, 383 {XK_Right, NoSymbol, "RGHT", 0}, 384 {XK_Num_Lock, NoSymbol, "NMLK", 0}, 385 {XK_KP_Divide, NoSymbol, "KPDV", 0}, 386 {XK_KP_Multiply, NoSymbol, "KPMU", 0}, 387 {XK_KP_Subtract, NoSymbol, "KPSU", 0}, 388 {NoSymbol, XK_KP_7, "KP7\0", 0}, 389 {NoSymbol, XK_KP_8, "KP8\0", 0}, 390 {NoSymbol, XK_KP_9, "KP9\0", 0}, 391 {XK_KP_Add, NoSymbol, "KPAD", 0}, 392 {NoSymbol, XK_KP_4, "KP4\0", 0}, 393 {NoSymbol, XK_KP_5, "KP5\0", 0}, 394 {NoSymbol, XK_KP_6, "KP6\0", 0}, 395 {NoSymbol, XK_KP_1, "KP1\0", 0}, 396 {NoSymbol, XK_KP_2, "KP2\0", 0}, 397 {NoSymbol, XK_KP_3, "KP3\0", 0}, 398 {XK_KP_Enter, NoSymbol, "KPEN", 0}, 399 {NoSymbol, XK_KP_0, "KP0\0", 0}, 400 {XK_KP_Delete, NoSymbol, "KPDL", 0}, 401 {XK_less, XK_greater, "LSGT", 0}, 402 {XK_KP_Separator, NoSymbol, "KPCO", 0}, 403 {XK_Find, NoSymbol, "FIND", 0}, 404 {NoSymbol, NoSymbol, "\0\0\0\0", 0} 405}; 406 407Status 408ComputeKbdDefaults(XkbDescPtr xkb) 409{ 410 int nUnknown; 411 412 if ((xkb->names == NULL) || (xkb->names->keys == NULL)) 413 { 414 Status rtrn; 415 if ((rtrn = XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0)) != Success) 416 return rtrn; 417 } 418 for (KeyNameDesc *name = dfltKeys; (name->name[0] != '\0'); name++) 419 { 420 name->used = False; 421 } 422 nUnknown = 0; 423 for (int i = xkb->min_key_code; i <= xkb->max_key_code; i++) 424 { 425 int tmp = XkbKeyNumSyms(xkb, i); 426 if ((xkb->names->keys[i].name[0] == '\0') && (tmp > 0)) 427 { 428 KeySym *syms; 429 430 tmp = XkbKeyGroupsWidth(xkb, i); 431 syms = XkbKeySymsPtr(xkb, i); 432 for (KeyNameDesc *name = dfltKeys; (name->name[0] != '\0'); name++) 433 { 434 Bool match = True; 435 if (((name->level1 != syms[0]) 436 && (name->level1 != NoSymbol)) 437 || ((name->level2 != NoSymbol) && (tmp < 2)) 438 || ((name->level2 != syms[1]) 439 && (name->level2 != NoSymbol))) 440 { 441 match = False; 442 } 443 if (match) 444 { 445 if (!name->used) 446 { 447 memcpy(xkb->names->keys[i].name, name->name, 448 XkbKeyNameLength); 449 name->used = True; 450 } 451 else 452 { 453 char tmpname[XkbKeyNameLength + 1]; 454 455 if (warningLevel > 2) 456 { 457 WARN 458 ("Several keys match pattern for %s\n", 459 XkbKeyNameText(name->name, XkbMessage)); 460 ACTION("Using <U%03d> for key %d\n", 461 nUnknown, i); 462 } 463 snprintf(tmpname, sizeof(tmpname), "U%03d", 464 nUnknown++); 465 memcpy(xkb->names->keys[i].name, tmpname, 466 XkbKeyNameLength); 467 } 468 break; 469 } 470 } 471 if (xkb->names->keys[i].name[0] == '\0') 472 { 473 if (warningLevel > 2) 474 { 475 char tmpname[XkbKeyNameLength + 1]; 476 477 WARN("Key %d does not match any defaults\n", i); 478 ACTION("Using name <U%03d>\n", nUnknown); 479 snprintf(tmpname, sizeof(tmpname), "U%03d", nUnknown++); 480 memcpy(xkb->names->keys[i].name, tmpname, 481 XkbKeyNameLength); 482 } 483 } 484 } 485 } 486 return Success; 487} 488 489/** 490 * Find the key with the given name and return its keycode in kc_rtrn. 491 * 492 * @param name The 4-letter name of the key as a long. 493 * @param kc_rtrn Set to the keycode if the key was found, otherwise 0. 494 * @param use_aliases True if the key aliases should be searched too. 495 * @param create If True and the key is not found, it is added to the 496 * xkb->names at the first free keycode. 497 * @param start_from Keycode to start searching from. 498 * 499 * @return True if found, False otherwise. 500 */ 501Bool 502FindNamedKey(XkbDescPtr xkb, 503 unsigned long name, 504 unsigned int *kc_rtrn, 505 Bool use_aliases, Bool create, int start_from) 506{ 507 if (start_from < xkb->min_key_code) 508 { 509 start_from = xkb->min_key_code; 510 } 511 else if (start_from > xkb->max_key_code) 512 { 513 return False; 514 } 515 516 *kc_rtrn = 0; /* some callers rely on this */ 517 if (xkb && xkb->names && xkb->names->keys) 518 { 519 for (unsigned n = start_from; n <= xkb->max_key_code; n++) 520 { 521 unsigned long tmp; 522 tmp = KeyNameToLong(xkb->names->keys[n].name); 523 if (tmp == name) 524 { 525 *kc_rtrn = n; 526 return True; 527 } 528 } 529 if (use_aliases) 530 { 531 unsigned long new_name; 532 if (FindKeyNameForAlias(xkb, name, &new_name)) 533 return FindNamedKey(xkb, new_name, kc_rtrn, False, create, 0); 534 } 535 } 536 if (create) 537 { 538 if ((!xkb->names) || (!xkb->names->keys)) 539 { 540 if (xkb->min_key_code < XkbMinLegalKeyCode) 541 { 542 xkb->min_key_code = XkbMinLegalKeyCode; 543 xkb->max_key_code = XkbMaxLegalKeyCode; 544 } 545 if (XkbAllocNames(xkb, XkbKeyNamesMask, 0, 0) != Success) 546 { 547 if (warningLevel > 0) 548 { 549 WARN("Couldn't allocate key names in FindNamedKey\n"); 550 ACTION("Key \"%s\" not automatically created\n", 551 longText(name, XkbMessage)); 552 } 553 return False; 554 } 555 } 556 /* Find first unused keycode and store our key here */ 557 for (unsigned n = xkb->min_key_code; n <= xkb->max_key_code; n++) 558 { 559 if (xkb->names->keys[n].name[0] == '\0') 560 { 561 char buf[XkbKeyNameLength + 1]; 562 LongToKeyName(name, buf); 563 memcpy(xkb->names->keys[n].name, buf, XkbKeyNameLength); 564 *kc_rtrn = n; 565 return True; 566 } 567 } 568 } 569 return False; 570} 571 572Bool 573FindKeyNameForAlias(XkbDescPtr xkb, unsigned long lname, 574 unsigned long *real_name) 575{ 576 char name[XkbKeyNameLength + 1]; 577 578 if (xkb && xkb->geom && xkb->geom->key_aliases) 579 { 580 XkbKeyAliasPtr a; 581 a = xkb->geom->key_aliases; 582 LongToKeyName(lname, name); 583 name[XkbKeyNameLength] = '\0'; 584 for (int i = 0; i < xkb->geom->num_key_aliases; i++, a++) 585 { 586 if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 587 { 588 *real_name = KeyNameToLong(a->real); 589 return True; 590 } 591 } 592 } 593 if (xkb && xkb->names && xkb->names->key_aliases) 594 { 595 XkbKeyAliasPtr a; 596 a = xkb->names->key_aliases; 597 LongToKeyName(lname, name); 598 name[XkbKeyNameLength] = '\0'; 599 for (int i = 0; i < xkb->names->num_key_aliases; i++, a++) 600 { 601 if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 602 { 603 *real_name = KeyNameToLong(a->real); 604 return True; 605 } 606 } 607 } 608 return False; 609} 610