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