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