xkbmisc.c revision 70728a38
1/************************************************************ 2 Copyright (c) 1995 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#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#elif defined(HAVE_CONFIG_H) 30#include <config.h> 31#endif 32 33#include <stdio.h> 34#include <ctype.h> 35#include <stdlib.h> 36 37#include <X11/Xos.h> 38#include <X11/Xfuncs.h> 39 40 41#include <X11/Xlib.h> 42#include <X11/keysym.h> 43#include <X11/XKBlib.h> 44#include <X11/extensions/XKBgeom.h> 45#include "XKMformat.h" 46#include "XKBfileInt.h" 47 48 49unsigned 50_XkbKSCheckCase(KeySym ks) 51{ 52 unsigned set, rtrn; 53 54 set = (ks & (~0xff)) >> 8; 55 rtrn = 0; 56 switch (set) { 57 case 0: /* latin 1 */ 58 if (((ks >= XK_A) && (ks <= XK_Z)) || 59 ((ks >= XK_Agrave) && (ks <= XK_THORN) && (ks != XK_multiply))) { 60 rtrn |= _XkbKSUpper; 61 } 62 if (((ks >= XK_a) && (ks <= XK_z)) || 63 ((ks >= XK_agrave) && (ks <= XK_ydiaeresis))) { 64 rtrn |= _XkbKSLower; 65 } 66 break; 67 case 1: /* latin 2 */ 68 if (((ks >= XK_Aogonek) && (ks <= XK_Zabovedot) && (ks != XK_breve)) || 69 ((ks >= XK_Racute) && (ks <= XK_Tcedilla))) { 70 rtrn |= _XkbKSUpper; 71 } 72 if (((ks >= XK_aogonek) && (ks <= XK_zabovedot) && (ks != XK_caron)) || 73 ((ks >= XK_racute) && (ks <= XK_tcedilla))) { 74 rtrn |= _XkbKSLower; 75 } 76 break; 77 case 2: /* latin 3 */ 78 if (((ks >= XK_Hstroke) && (ks <= XK_Jcircumflex)) || 79 ((ks >= XK_Cabovedot) && (ks <= XK_Scircumflex))) { 80 rtrn |= _XkbKSUpper; 81 } 82 if (((ks >= XK_hstroke) && (ks <= XK_jcircumflex)) || 83 ((ks >= XK_cabovedot) && (ks <= XK_scircumflex))) { 84 rtrn |= _XkbKSLower; 85 } 86 break; 87 case 3: /* latin 4 */ 88 if (((ks >= XK_Rcedilla) && (ks <= XK_Tslash)) || 89 (ks == XK_ENG) || ((ks >= XK_Amacron) && (ks <= XK_Umacron))) { 90 rtrn |= _XkbKSUpper; 91 } 92 if (((ks >= XK_rcedilla) && (ks <= XK_tslash)) || 93 (ks == XK_eng) || ((ks >= XK_amacron) && (ks <= XK_umacron))) { 94 rtrn |= _XkbKSLower; 95 } 96 break; 97 case 18: /* latin 8 */ 98 if ((ks == XK_Babovedot) || 99 ((ks >= XK_Dabovedot) && (ks <= XK_Wacute)) || 100 ((ks >= XK_Ygrave) && (ks <= XK_Fabovedot)) || 101 (ks == XK_Mabovedot) || 102 (ks == XK_Pabovedot) || 103 (ks == XK_Sabovedot) || 104 (ks == XK_Wdiaeresis) || 105 ((ks >= XK_Wcircumflex) && (ks <= XK_Ycircumflex))) { 106 rtrn |= _XkbKSUpper; 107 } 108 if ((ks == XK_babovedot) || 109 (ks == XK_dabovedot) || 110 (ks == XK_fabovedot) || 111 (ks == XK_mabovedot) || 112 ((ks >= XK_wgrave) && (ks <= XK_wacute)) || 113 (ks == XK_ygrave) || 114 ((ks >= XK_wdiaeresis) && (ks <= XK_ycircumflex))) { 115 rtrn |= _XkbKSLower; 116 } 117 break; 118 case 19: /* latin 9 */ 119 if ((ks == XK_OE) || (ks == XK_Ydiaeresis)) { 120 rtrn |= _XkbKSUpper; 121 } 122 if (ks == XK_oe) { 123 rtrn |= _XkbKSLower; 124 } 125 break; 126 } 127 return rtrn; 128} 129 130/***===================================================================***/ 131 132Bool 133XkbLookupGroupAndLevel(XkbDescPtr xkb, 134 int key, 135 int * mods_inout, 136 int * grp_inout, 137 int * lvl_rtrn) 138{ 139 int nG, eG; 140 141 if ((!xkb) || (!XkbKeycodeInRange(xkb, key)) || (!grp_inout)) 142 return False; 143 144 nG = XkbKeyNumGroups(xkb, key); 145 eG = *grp_inout; 146 147 if (nG == 0) { 148 *grp_inout = 0; 149 if (lvl_rtrn != NULL) 150 *lvl_rtrn = 0; 151 return False; 152 } 153 else if (nG == 1) { 154 eG = 0; 155 } 156 else if (eG >= nG) { 157 unsigned gI = XkbKeyGroupInfo(xkb, key); 158 159 switch (XkbOutOfRangeGroupAction(gI)) { 160 default: 161 eG %= nG; 162 break; 163 case XkbClampIntoRange: 164 eG = nG - 1; 165 break; 166 case XkbRedirectIntoRange: 167 eG = XkbOutOfRangeGroupNumber(gI); 168 if (eG >= nG) 169 eG = 0; 170 break; 171 } 172 } 173 *grp_inout = eG; 174 if (mods_inout != NULL) { 175 XkbKeyTypePtr type; 176 int preserve; 177 178 type = XkbKeyKeyType(xkb, key, eG); 179 if (lvl_rtrn != NULL) 180 *lvl_rtrn = 0; 181 preserve = 0; 182 if (type->map) { /* find the shift level */ 183 register int i; 184 register XkbKTMapEntryPtr entry; 185 186 for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 187 if ((entry->active) && 188 (((*mods_inout) & type->mods.mask) == entry->mods.mask)) { 189 if (lvl_rtrn != NULL) 190 *lvl_rtrn = entry->level; 191 if (type->preserve) 192 preserve = type->preserve[i].mask; 193 break; 194 } 195 } 196 } 197 (*mods_inout) &= ~(type->mods.mask & (~preserve)); 198 } 199 return True; 200} 201 202/***===================================================================***/ 203 204static Bool 205XkbWriteSectionFromName(FILE *file, const char *sectionName, const char *name) 206{ 207 fprintf(file, " xkb_%-20s { include \"%s\" };\n", sectionName, name); 208 return True; 209} 210 211#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) 212#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) 213 214/* ARGSUSED */ 215static void 216_AddIncl(FILE * file, 217 XkbFileInfo * result, 218 Bool topLevel, 219 Bool showImplicit, 220 int index, 221 void * priv) 222{ 223 if ((priv) && (strcmp((char *) priv, "%") != 0)) 224 fprintf(file, " include \"%s\"\n", (char *) priv); 225 return; 226} 227 228Bool 229XkbWriteXKBKeymapForNames(FILE * file, 230 XkbComponentNamesPtr names, 231 Display * dpy, 232 XkbDescPtr xkb, 233 unsigned want, 234 unsigned need) 235{ 236 char *name, *tmp; 237 unsigned complete; 238 XkbNamesPtr old_names; 239 int multi_section; 240 unsigned wantNames, wantConfig, wantDflts; 241 XkbFileInfo finfo; 242 243 bzero(&finfo, sizeof(XkbFileInfo)); 244 245 complete = 0; 246 if ((name = names->keymap) == NULL) 247 name = "default"; 248 if (COMPLETE(names->keycodes)) 249 complete |= XkmKeyNamesMask; 250 if (COMPLETE(names->types)) 251 complete |= XkmTypesMask; 252 if (COMPLETE(names->compat)) 253 complete |= XkmCompatMapMask; 254 if (COMPLETE(names->symbols)) 255 complete |= XkmSymbolsMask; 256 if (COMPLETE(names->geometry)) 257 complete |= XkmGeometryMask; 258 want |= (complete | need); 259 if (want & XkmSymbolsMask) 260 want |= XkmKeyNamesMask | XkmTypesMask; 261 262 if (want == 0) 263 return False; 264 265 if (xkb != NULL) { 266 old_names = xkb->names; 267 finfo.type = 0; 268 finfo.defined = 0; 269 finfo.xkb = xkb; 270 if (!XkbDetermineFileType(&finfo, XkbXKBFile, NULL)) 271 return False; 272 } 273 else 274 old_names = NULL; 275 276 wantConfig = want & (~complete); 277 if (xkb != NULL) { 278 if (wantConfig & XkmTypesMask) { 279 if ((!xkb->map) || (xkb->map->num_types < XkbNumRequiredTypes)) 280 wantConfig &= ~XkmTypesMask; 281 } 282 if (wantConfig & XkmCompatMapMask) { 283 if ((!xkb->compat) || (xkb->compat->num_si < 1)) 284 wantConfig &= ~XkmCompatMapMask; 285 } 286 if (wantConfig & XkmSymbolsMask) { 287 if ((!xkb->map) || (!xkb->map->key_sym_map)) 288 wantConfig &= ~XkmSymbolsMask; 289 } 290 if (wantConfig & XkmIndicatorsMask) { 291 if (!xkb->indicators) 292 wantConfig &= ~XkmIndicatorsMask; 293 } 294 if (wantConfig & XkmKeyNamesMask) { 295 if ((!xkb->names) || (!xkb->names->keys)) 296 wantConfig &= ~XkmKeyNamesMask; 297 } 298 if ((wantConfig & XkmGeometryMask) && (!xkb->geom)) 299 wantConfig &= ~XkmGeometryMask; 300 } 301 else { 302 wantConfig = 0; 303 } 304 complete |= wantConfig; 305 306 wantDflts = 0; 307 wantNames = want & (~complete); 308 if ((xkb != NULL) && (old_names != NULL)) { 309 if (wantNames & XkmTypesMask) { 310 if (old_names->types != None) { 311 tmp = XkbAtomGetString(dpy, old_names->types); 312 names->types = tmp; 313 } 314 else { 315 wantDflts |= XkmTypesMask; 316 } 317 complete |= XkmTypesMask; 318 } 319 if (wantNames & XkmCompatMapMask) { 320 if (old_names->compat != None) { 321 tmp = XkbAtomGetString(dpy, old_names->compat); 322 names->compat = tmp; 323 } 324 else 325 wantDflts |= XkmCompatMapMask; 326 complete |= XkmCompatMapMask; 327 } 328 if (wantNames & XkmSymbolsMask) { 329 if (old_names->symbols == None) 330 return False; 331 tmp = XkbAtomGetString(dpy, old_names->symbols); 332 names->symbols = tmp; 333 complete |= XkmSymbolsMask; 334 } 335 if (wantNames & XkmKeyNamesMask) { 336 if (old_names->keycodes != None) { 337 tmp = XkbAtomGetString(dpy, old_names->keycodes); 338 names->keycodes = tmp; 339 } 340 else 341 wantDflts |= XkmKeyNamesMask; 342 complete |= XkmKeyNamesMask; 343 } 344 if (wantNames & XkmGeometryMask) { 345 if (old_names->geometry == None) 346 return False; 347 tmp = XkbAtomGetString(dpy, old_names->geometry); 348 names->geometry = tmp; 349 complete |= XkmGeometryMask; 350 wantNames &= ~XkmGeometryMask; 351 } 352 } 353 if (complete & XkmCompatMapMask) 354 complete |= XkmIndicatorsMask | XkmVirtualModsMask; 355 else if (complete & (XkmSymbolsMask | XkmTypesMask)) 356 complete |= XkmVirtualModsMask; 357 if (need & (~complete)) 358 return False; 359 if ((complete & XkmSymbolsMask) && 360 ((XkmKeyNamesMask | XkmTypesMask) & (~complete))) 361 return False; 362 363 multi_section = 1; 364 if (((complete & XkmKeymapRequired) == XkmKeymapRequired) && 365 ((complete & (~XkmKeymapLegal)) == 0)) { 366 fprintf(file, "xkb_keymap \"%s\" {\n", name); 367 } 368 else if (((complete & XkmSemanticsRequired) == XkmSemanticsRequired) && 369 ((complete & (~XkmSemanticsLegal)) == 0)) { 370 fprintf(file, "xkb_semantics \"%s\" {\n", name); 371 } 372 else if (((complete & XkmLayoutRequired) == XkmLayoutRequired) && 373 ((complete & (~XkmLayoutLegal)) == 0)) { 374 fprintf(file, "xkb_layout \"%s\" {\n", name); 375 } 376 else if (XkmSingleSection(complete & (~XkmVirtualModsMask))) { 377 multi_section = 0; 378 } 379 else { 380 return False; 381 } 382 383 wantNames = complete & (~(wantConfig | wantDflts)); 384 name = names->keycodes; 385 if (wantConfig & XkmKeyNamesMask) 386 XkbWriteXKBKeycodes(file, &finfo, False, False, _AddIncl, name); 387 else if (wantDflts & XkmKeyNamesMask) 388 fprintf(stderr, "Default symbols not implemented yet!\n"); 389 else if (wantNames & XkmKeyNamesMask) 390 XkbWriteSectionFromName(file, "keycodes", name); 391 392 name = names->types; 393 if (wantConfig & XkmTypesMask) 394 XkbWriteXKBKeyTypes(file, &finfo, False, False, _AddIncl, name); 395 else if (wantDflts & XkmTypesMask) 396 fprintf(stderr, "Default types not implemented yet!\n"); 397 else if (wantNames & XkmTypesMask) 398 XkbWriteSectionFromName(file, "types", name); 399 400 name = names->compat; 401 if (wantConfig & XkmCompatMapMask) 402 XkbWriteXKBCompatMap(file, &finfo, False, False, _AddIncl, name); 403 else if (wantDflts & XkmCompatMapMask) 404 fprintf(stderr, "Default interps not implemented yet!\n"); 405 else if (wantNames & XkmCompatMapMask) 406 XkbWriteSectionFromName(file, "compatibility", name); 407 408 name = names->symbols; 409 if (wantConfig & XkmSymbolsMask) 410 XkbWriteXKBSymbols(file, &finfo, False, False, _AddIncl, name); 411 else if (wantNames & XkmSymbolsMask) 412 XkbWriteSectionFromName(file, "symbols", name); 413 414 name = names->geometry; 415 if (wantConfig & XkmGeometryMask) 416 XkbWriteXKBGeometry(file, &finfo, False, False, _AddIncl, name); 417 else if (wantNames & XkmGeometryMask) 418 XkbWriteSectionFromName(file, "geometry", name); 419 420 if (multi_section) 421 fprintf(file, "};\n"); 422 return True; 423} 424 425/***====================================================================***/ 426 427/*ARGSUSED*/ 428Status 429XkbMergeFile(XkbDescPtr xkb, XkbFileInfo finfo) 430{ 431 return BadImplementation; 432} 433 434/***====================================================================***/ 435 436int 437XkbFindKeycodeByName(XkbDescPtr xkb, char *name, Bool use_aliases) 438{ 439 register int i; 440 441 if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) 442 return 0; 443 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 444 if (strncmp(xkb->names->keys[i].name, name, XkbKeyNameLength) == 0) 445 return i; 446 } 447 if (!use_aliases) 448 return 0; 449 if (xkb->geom && xkb->geom->key_aliases) { 450 XkbKeyAliasPtr a; 451 452 a = xkb->geom->key_aliases; 453 for (i = 0; i < xkb->geom->num_key_aliases; i++, a++) { 454 if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 455 return XkbFindKeycodeByName(xkb, a->real, False); 456 } 457 } 458 if (xkb->names && xkb->names->key_aliases) { 459 XkbKeyAliasPtr a; 460 461 a = xkb->names->key_aliases; 462 for (i = 0; i < xkb->names->num_key_aliases; i++, a++) { 463 if (strncmp(name, a->alias, XkbKeyNameLength) == 0) 464 return XkbFindKeycodeByName(xkb, a->real, False); 465 } 466 } 467 return 0; 468} 469 470unsigned 471XkbConvertGetByNameComponents(Bool toXkm, unsigned orig) 472{ 473 unsigned rtrn; 474 475 rtrn = 0; 476 if (toXkm) { 477 if (orig & XkbGBN_TypesMask) 478 rtrn |= XkmTypesMask; 479 if (orig & XkbGBN_CompatMapMask) 480 rtrn |= XkmCompatMapMask; 481 if (orig & XkbGBN_SymbolsMask) 482 rtrn |= XkmSymbolsMask; 483 if (orig & XkbGBN_IndicatorMapMask) 484 rtrn |= XkmIndicatorsMask; 485 if (orig & XkbGBN_KeyNamesMask) 486 rtrn |= XkmKeyNamesMask; 487 if (orig & XkbGBN_GeometryMask) 488 rtrn |= XkmGeometryMask; 489 } 490 else { 491 if (orig & XkmTypesMask) 492 rtrn |= XkbGBN_TypesMask; 493 if (orig & XkmCompatMapMask) 494 rtrn |= XkbGBN_CompatMapMask; 495 if (orig & XkmSymbolsMask) 496 rtrn |= XkbGBN_SymbolsMask; 497 if (orig & XkmIndicatorsMask) 498 rtrn |= XkbGBN_IndicatorMapMask; 499 if (orig & XkmKeyNamesMask) 500 rtrn |= XkbGBN_KeyNamesMask; 501 if (orig & XkmGeometryMask) 502 rtrn |= XkbGBN_GeometryMask; 503 if (orig != 0) 504 rtrn |= XkbGBN_OtherNamesMask; 505 } 506 return rtrn; 507} 508 509unsigned 510XkbConvertXkbComponents(Bool toXkm, unsigned orig) 511{ 512 unsigned rtrn; 513 514 rtrn = 0; 515 if (toXkm) { 516 if (orig & XkbClientMapMask) 517 rtrn |= XkmTypesMask | XkmSymbolsMask; 518 if (orig & XkbServerMapMask) 519 rtrn |= XkmTypesMask | XkmSymbolsMask; 520 if (orig & XkbCompatMapMask) 521 rtrn |= XkmCompatMapMask; 522 if (orig & XkbIndicatorMapMask) 523 rtrn |= XkmIndicatorsMask; 524 if (orig & XkbNamesMask) 525 rtrn |= XkmKeyNamesMask; 526 if (orig & XkbGeometryMask) 527 rtrn |= XkmGeometryMask; 528 } 529 else { 530 if (orig != 0) 531 rtrn |= XkbNamesMask; 532 if (orig & XkmTypesMask) 533 rtrn |= XkbClientMapMask; 534 if (orig & XkmCompatMapMask) 535 rtrn |= XkbCompatMapMask | XkbIndicatorMapMask; 536 if (orig & XkmSymbolsMask) 537 rtrn |= XkbClientMapMask | XkbServerMapMask; 538 if (orig & XkmIndicatorsMask) 539 rtrn |= XkbIndicatorMapMask; 540 if (orig & XkmKeyNamesMask) 541 rtrn |= XkbNamesMask | XkbIndicatorMapMask; 542 if (orig & XkmGeometryMask) 543 rtrn |= XkbGeometryMask; 544 } 545 return rtrn; 546} 547 548Bool 549XkbDetermineFileType(XkbFileInfoPtr finfo, int format, int *opts_missing) 550{ 551 unsigned present; 552 XkbDescPtr xkb; 553 554 if ((!finfo) || (!finfo->xkb)) 555 return False; 556 if (opts_missing) 557 *opts_missing = 0; 558 xkb = finfo->xkb; 559 present = 0; 560 if ((xkb->names) && (xkb->names->keys)) 561 present |= XkmKeyNamesMask; 562 if ((xkb->map) && (xkb->map->types)) 563 present |= XkmTypesMask; 564 if (xkb->compat) 565 present |= XkmCompatMapMask; 566 if ((xkb->map) && (xkb->map->num_syms > 1)) 567 present |= XkmSymbolsMask; 568 if (xkb->indicators) 569 present |= XkmIndicatorsMask; 570 if (xkb->geom) 571 present |= XkmGeometryMask; 572 if (!present) 573 return False; 574 else 575 switch (present) { 576 case XkmKeyNamesMask: 577 finfo->type = XkmKeyNamesIndex; 578 finfo->defined = present; 579 return True; 580 case XkmTypesMask: 581 finfo->type = XkmTypesIndex; 582 finfo->defined = present; 583 return True; 584 case XkmCompatMapMask: 585 finfo->type = XkmCompatMapIndex; 586 finfo->defined = present; 587 return True; 588 case XkmSymbolsMask: 589 if (format != XkbXKMFile) { 590 finfo->type = XkmSymbolsIndex; 591 finfo->defined = present; 592 return True; 593 } 594 break; 595 case XkmGeometryMask: 596 finfo->type = XkmGeometryIndex; 597 finfo->defined = present; 598 return True; 599 } 600 if ((present & (~XkmSemanticsLegal)) == 0) { 601 if ((XkmSemanticsRequired & present) == XkmSemanticsRequired) { 602 if (opts_missing) 603 *opts_missing = XkmSemanticsOptional & (~present); 604 finfo->type = XkmSemanticsFile; 605 finfo->defined = present; 606 return True; 607 } 608 } 609 else if ((present & (~XkmLayoutLegal)) == 0) { 610 if ((XkmLayoutRequired & present) == XkmLayoutRequired) { 611 if (opts_missing) 612 *opts_missing = XkmLayoutOptional & (~present); 613 finfo->type = XkmLayoutFile; 614 finfo->defined = present; 615 return True; 616 } 617 } 618 else if ((present & (~XkmKeymapLegal)) == 0) { 619 if ((XkmKeymapRequired & present) == XkmKeymapRequired) { 620 if (opts_missing) 621 *opts_missing = XkmKeymapOptional & (~present); 622 finfo->type = XkmKeymapFile; 623 finfo->defined = present; 624 return True; 625 } 626 } 627 return False; 628} 629 630/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */ 631/* wildcards */ 632 633static unsigned char componentSpecLegal[] = { 634 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, 635 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 637 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 638}; 639 640void 641XkbEnsureSafeMapName(char *name) 642{ 643 if (name == NULL) 644 return; 645 while (*name != '\0') { 646 if ((componentSpecLegal[(*name) / 8] & (1 << ((*name) % 8))) == 0) 647 *name = '_'; 648 name++; 649 } 650 return; 651} 652 653/***====================================================================***/ 654 655#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) 656 657Bool 658XkbNameMatchesPattern(char *name, char *ptrn) 659{ 660 while (ptrn[0] != '\0') { 661 if (name[0] == '\0') { 662 if (ptrn[0] == '*') { 663 ptrn++; 664 continue; 665 } 666 return False; 667 } 668 if (ptrn[0] == '?') { 669 if (UNMATCHABLE(name[0])) 670 return False; 671 } 672 else if (ptrn[0] == '*') { 673 if ((!UNMATCHABLE(name[0])) && 674 XkbNameMatchesPattern(name + 1, ptrn)) 675 return True; 676 return XkbNameMatchesPattern(name, ptrn + 1); 677 } 678 else if (ptrn[0] != name[0]) 679 return False; 680 name++; 681 ptrn++; 682 } 683 /* if we get here, the pattern is exhausted (-:just like me:-) */ 684 return (name[0] == '\0'); 685} 686 687#ifdef NEED_STRCASECMP 688_X_HIDDEN int 689_XkbStrCaseCmp(char *str1, char *str2) 690{ 691 const u_char *us1 = (const u_char *) str1, *us2 = (const u_char *) str2; 692 693 while (tolower(*us1) == tolower(*us2)) { 694 if (*us1++ == '\0') 695 return (0); 696 us2++; 697 } 698 699 return (tolower(*us1) - tolower(*us2)); 700} 701#endif 702