1/* 2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 *"Software"), to deal in the Software without restriction, including 7 *without limitation the rights to use, copy, modify, merge, publish, 8 *distribute, sublicense, and/or sell copies of the Software, and to 9 *permit persons to whom the Software is furnished to do so, subject to 10 *the following conditions: 11 * 12 *The above copyright notice and this permission notice shall be 13 *included in all copies or substantial portions of the Software. 14 * 15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 *Except as contained in this notice, the name of the XFree86 Project 24 *shall not be used in advertising or otherwise to promote the sale, use 25 *or other dealings in this Software without prior written authorization 26 *from the XFree86 Project. 27 * 28 * Authors: Alexander Gottwald 29 */ 30 31#ifdef HAVE_XWIN_CONFIG_H 32#include <xwin-config.h> 33#endif 34#include "win.h" 35#include "winconfig.h" 36#include "winmsg.h" 37#include "globals.h" 38 39#include "xkbsrv.h" 40 41#ifdef XWIN_XF86CONFIG 42#ifndef CONFIGPATH 43#define CONFIGPATH "%A," "%R," \ 44 "/etc/X11/%R," "%P/etc/X11/%R," \ 45 "%E," "%F," \ 46 "/etc/X11/%F," "%P/etc/X11/%F," \ 47 "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ 48 "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ 49 "%P/etc/X11/%X," \ 50 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ 51 "%P/lib/X11/%X" 52#endif 53#ifndef CONFIGDIRPATH 54#define CONFIGDIRPATH "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ 55 "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ 56 "%P/etc/X11/%X," \ 57 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ 58 "%P/lib/X11/%X" 59#endif 60 61XF86ConfigPtr g_xf86configptr = NULL; 62#endif 63 64WinCmdlineRec g_cmdline = { 65#ifdef XWIN_XF86CONFIG 66 NULL, /* configFile */ 67 NULL, /* configDir */ 68#endif 69 NULL, /* fontPath */ 70#ifdef XWIN_XF86CONFIG 71 NULL, /* keyboard */ 72#endif 73 NULL, /* xkbRules */ 74 NULL, /* xkbModel */ 75 NULL, /* xkbLayout */ 76 NULL, /* xkbVariant */ 77 NULL, /* xkbOptions */ 78 NULL, /* screenname */ 79 NULL, /* mousename */ 80 FALSE, /* emulate3Buttons */ 81 0 /* emulate3Timeout */ 82}; 83 84winInfoRec g_winInfo = { 85 { /* keyboard */ 86 0, /* leds */ 87 500, /* delay */ 88 30 /* rate */ 89 } 90 , 91 { /* xkb */ 92 NULL, /* rules */ 93 NULL, /* model */ 94 NULL, /* layout */ 95 NULL, /* variant */ 96 NULL, /* options */ 97 } 98 , 99 { 100 FALSE, 101 50} 102}; 103 104#define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL) 105 106#ifdef XWIN_XF86CONFIG 107serverLayoutRec g_winConfigLayout; 108 109static Bool ParseOptionValue (int scrnIndex, pointer options, 110 OptionInfoPtr p); 111static Bool configLayout (serverLayoutPtr, XF86ConfLayoutPtr, char *); 112static Bool configImpliedLayout (serverLayoutPtr, XF86ConfScreenPtr); 113static Bool GetBoolValue (OptionInfoPtr p, const char *s); 114 115 116Bool 117winReadConfigfile () 118{ 119 Bool retval = TRUE; 120 const char *filename, *dirname; 121 MessageType filefrom = X_DEFAULT; 122 MessageType dirfrom = X_DEFAULT; 123 char *xf86ConfigFile = NULL; 124 char *xf86ConfigDir = NULL; 125 126 if (g_cmdline.configFile) 127 { 128 filefrom = X_CMDLINE; 129 xf86ConfigFile = g_cmdline.configFile; 130 } 131 if (g_cmdline.configDir) 132 { 133 dirfrom = X_CMDLINE; 134 xf86ConfigDir = g_cmdline.configDir; 135 } 136 137 /* Parse config file into data structure */ 138 xf86initConfigFiles(); 139 dirname = xf86openConfigDirFiles (CONFIGDIRPATH, xf86ConfigDir, PROJECTROOT); 140 filename = xf86openConfigFile (CONFIGPATH, xf86ConfigFile, PROJECTROOT); 141 142 /* Hack for backward compatibility */ 143 if (!filename && from == X_DEFAULT) 144 filename = xf86openConfigFile (CONFIGPATH, "XF86Config", PROJECTROOT); 145 146 if (filename) 147 { 148 winMsg (from, "Using config file: \"%s\"\n", filename); 149 } 150 else 151 { 152 winMsg (X_ERROR, "Unable to locate/open config file"); 153 if (xf86ConfigFile) 154 ErrorF (": \"%s\"", xf86ConfigFile); 155 ErrorF ("\n"); 156 } 157 if (dirname) 158 { 159 winMsg (from, "Using config directory: \"%s\"\n", dirname); 160 } 161 else 162 { 163 winMsg (X_ERROR, "Unable to locate/open config directory"); 164 if (xf86ConfigDir) 165 ErrorF (": \"%s\"", xf86ConfigDir); 166 ErrorF ("\n"); 167 } 168 if (!filename && !dirname) 169 { 170 return FALSE; 171 } 172 if ((g_xf86configptr = xf86readConfigFile ()) == NULL) 173 { 174 winMsg (X_ERROR, "Problem parsing the config file\n"); 175 return FALSE; 176 } 177 xf86closeConfigFile (); 178 179 LogPrintMarkers(); 180 181 /* set options from data structure */ 182 183 if (g_xf86configptr->conf_layout_lst == NULL || g_cmdline.screenname != NULL) 184 { 185 if (g_cmdline.screenname == NULL) 186 { 187 winMsg (X_WARNING, 188 "No Layout section. Using the first Screen section.\n"); 189 } 190 if (!configImpliedLayout (&g_winConfigLayout, 191 g_xf86configptr->conf_screen_lst)) 192 { 193 winMsg (X_ERROR, "Unable to determine the screen layout\n"); 194 return FALSE; 195 } 196 } 197 else 198 { 199 /* Check if layout is given in the config file */ 200 if (g_xf86configptr->conf_flags != NULL) 201 { 202 char *dfltlayout = NULL; 203 pointer optlist = g_xf86configptr->conf_flags->flg_option_lst; 204 205 if (optlist && winFindOption (optlist, "defaultserverlayout")) 206 dfltlayout = 207 winSetStrOption (optlist, "defaultserverlayout", NULL); 208 209 if (!configLayout (&g_winConfigLayout, 210 g_xf86configptr->conf_layout_lst, 211 dfltlayout)) 212 { 213 winMsg (X_ERROR, "Unable to determine the screen layout\n"); 214 return FALSE; 215 } 216 } 217 else 218 { 219 if (!configLayout (&g_winConfigLayout, 220 g_xf86configptr->conf_layout_lst, 221 NULL)) 222 { 223 winMsg (X_ERROR, "Unable to determine the screen layout\n"); 224 return FALSE; 225 } 226 } 227 } 228 229 /* setup special config files */ 230 winConfigFiles (); 231 return retval; 232} 233#endif 234 235/* load layout definitions */ 236#include "winlayouts.h" 237 238/* Set the keyboard configuration */ 239Bool 240winConfigKeyboard (DeviceIntPtr pDevice) 241{ 242 char layoutName[KL_NAMELENGTH]; 243 unsigned char layoutFriendlyName[256]; 244 static unsigned int layoutNum = 0; 245 int keyboardType; 246#ifdef XWIN_XF86CONFIG 247 XF86ConfInputPtr kbd = NULL; 248 XF86ConfInputPtr input_list = NULL; 249 MessageType kbdfrom = X_CONFIG; 250#endif 251 MessageType from = X_DEFAULT; 252 char *s = NULL; 253 254 /* Setup defaults */ 255 XkbGetRulesDflts(&g_winInfo.xkb); 256 257 /* 258 * Query the windows autorepeat settings and change the xserver defaults. 259 */ 260 { 261 int kbd_delay; 262 DWORD kbd_speed; 263 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) && 264 SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0)) 265 { 266 switch (kbd_delay) 267 { 268 case 0: g_winInfo.keyboard.delay = 250; break; 269 case 1: g_winInfo.keyboard.delay = 500; break; 270 case 2: g_winInfo.keyboard.delay = 750; break; 271 default: 272 case 3: g_winInfo.keyboard.delay = 1000; break; 273 } 274 g_winInfo.keyboard.rate = (kbd_speed>0)?kbd_speed:1; 275 winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%d, rate=%d\n", 276 g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); 277 } 278 } 279 280 281 keyboardType = GetKeyboardType (0); 282 if (keyboardType > 0 && GetKeyboardLayoutName (layoutName)) 283 { 284 WinKBLayoutPtr pLayout; 285 Bool bfound = FALSE; 286 287 if (! layoutNum) 288 layoutNum = strtoul (layoutName, (char **)NULL, 16); 289 if ((layoutNum & 0xffff) == 0x411) { 290 /* The japanese layouts know a lot of different IMEs which all have 291 different layout numbers set. Map them to a single entry. 292 Same might apply for chinese, korean and other symbol languages 293 too */ 294 layoutNum = (layoutNum & 0xffff); 295 if (keyboardType == 7) 296 { 297 /* Japanese layouts have problems with key event messages 298 such as the lack of WM_KEYUP for Caps Lock key. 299 Loading US layout fixes this problem. */ 300 if (LoadKeyboardLayout("00000409", KLF_ACTIVATE) != NULL) 301 winMsg (X_INFO, "Loading US keyboard layout.\n"); 302 else 303 winMsg (X_ERROR, "LoadKeyboardLayout failed.\n"); 304 } 305 } 306 307 /* Discover the friendly name of the current layout */ 308 { 309 HKEY regkey = NULL; 310 const char regtempl[] = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"; 311 char *regpath; 312 DWORD namesize = sizeof(layoutFriendlyName); 313 314 regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1); 315 strcpy(regpath, regtempl); 316 strcat(regpath, layoutName); 317 318 if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, ®key)) 319 RegQueryValueEx(regkey, "Layout Text", 0, NULL, layoutFriendlyName, &namesize); 320 321 /* Close registry key */ 322 if (regkey) 323 RegCloseKey (regkey); 324 free(regpath); 325 } 326 327 winMsg (X_PROBED, "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n", 328 layoutName, layoutNum, layoutFriendlyName, keyboardType); 329 330 for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) 331 { 332 if (pLayout->winlayout != layoutNum) 333 continue; 334 if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType) 335 continue; 336 337 bfound = TRUE; 338 winMsg (X_PROBED, 339 "Found matching XKB configuration \"%s\"\n", 340 pLayout->layoutname); 341 342 winMsg(X_PROBED, 343 "Model = \"%s\" Layout = \"%s\"" 344 " Variant = \"%s\" Options = \"%s\"\n", 345 pLayout->xkbmodel ? pLayout->xkbmodel : "none", 346 pLayout->xkblayout ? pLayout->xkblayout : "none", 347 pLayout->xkbvariant ? pLayout->xkbvariant : "none", 348 pLayout->xkboptions ? pLayout->xkboptions : "none"); 349 350 g_winInfo.xkb.model = pLayout->xkbmodel; 351 g_winInfo.xkb.layout = pLayout->xkblayout; 352 g_winInfo.xkb.variant = pLayout->xkbvariant; 353 g_winInfo.xkb.options = pLayout->xkboptions; 354 355 356 break; 357 } 358 359 if (!bfound) 360 { 361 winMsg (X_ERROR, "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n", layoutFriendlyName, layoutName); 362 } 363 } 364 365 /* parse the configuration */ 366#ifdef XWIN_XF86CONFIG 367 if (g_cmdline.keyboard) 368 kbdfrom = X_CMDLINE; 369 370 /* 371 * Until the layout code is finished, I search for the keyboard 372 * device and configure the server with it. 373 */ 374 375 if (g_xf86configptr != NULL) 376 input_list = g_xf86configptr->conf_input_lst; 377 378 while (input_list != NULL) 379 { 380 if (winNameCompare (input_list->inp_driver, "keyboard") == 0) 381 { 382 /* Check if device name matches requested name */ 383 if (g_cmdline.keyboard && winNameCompare (input_list->inp_identifier, 384 g_cmdline.keyboard)) 385 continue; 386 kbd = input_list; 387 } 388 input_list = input_list->list.next; 389 } 390 391 if (kbd != NULL) 392 { 393 394 if (kbd->inp_identifier) 395 winMsg (kbdfrom, "Using keyboard \"%s\" as primary keyboard\n", 396 kbd->inp_identifier); 397 398 if ((s = winSetStrOption(kbd->inp_option_lst, "AutoRepeat", NULL))) 399 { 400 if ((sscanf(s, "%ld %ld", &g_winInfo.keyboard.delay, 401 &g_winInfo.keyboard.rate) != 2) || 402 (g_winInfo.keyboard.delay < 1) || 403 (g_winInfo.keyboard.rate == 0) || 404 (1000 / g_winInfo.keyboard.rate) < 1) 405 { 406 winErrorFVerb (2, "\"%s\" is not a valid AutoRepeat value", s); 407 free(s); 408 return FALSE; 409 } 410 free(s); 411 winMsg (X_CONFIG, "AutoRepeat: %ld %ld\n", 412 g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); 413 } 414#endif 415 416 s = NULL; 417 if (g_cmdline.xkbRules) 418 { 419 s = g_cmdline.xkbRules; 420 from = X_CMDLINE; 421 } 422#ifdef XWIN_XF86CONFIG 423 else 424 { 425 s = winSetStrOption (kbd->inp_option_lst, "XkbRules", NULL); 426 from = X_CONFIG; 427 } 428#endif 429 if (s) 430 { 431 g_winInfo.xkb.rules = NULL_IF_EMPTY (s); 432 winMsg (from, "XKB: rules: \"%s\"\n", s); 433 } 434 435 s = NULL; 436 if (g_cmdline.xkbModel) 437 { 438 s = g_cmdline.xkbModel; 439 from = X_CMDLINE; 440 } 441#ifdef XWIN_XF86CONFIG 442 else 443 { 444 s = winSetStrOption (kbd->inp_option_lst, "XkbModel", NULL); 445 from = X_CONFIG; 446 } 447#endif 448 if (s) 449 { 450 g_winInfo.xkb.model = NULL_IF_EMPTY (s); 451 winMsg (from, "XKB: model: \"%s\"\n", s); 452 } 453 454 s = NULL; 455 if (g_cmdline.xkbLayout) 456 { 457 s = g_cmdline.xkbLayout; 458 from = X_CMDLINE; 459 } 460#ifdef XWIN_XF86CONFIG 461 else 462 { 463 s = winSetStrOption (kbd->inp_option_lst, "XkbLayout", NULL); 464 from = X_CONFIG; 465 } 466#endif 467 if (s) 468 { 469 g_winInfo.xkb.layout = NULL_IF_EMPTY (s); 470 winMsg (from, "XKB: layout: \"%s\"\n", s); 471 } 472 473 s = NULL; 474 if (g_cmdline.xkbVariant) 475 { 476 s = g_cmdline.xkbVariant; 477 from = X_CMDLINE; 478 } 479#ifdef XWIN_XF86CONFIG 480 else 481 { 482 s = winSetStrOption (kbd->inp_option_lst, "XkbVariant", NULL); 483 from = X_CONFIG; 484 } 485#endif 486 if (s) 487 { 488 g_winInfo.xkb.variant = NULL_IF_EMPTY (s); 489 winMsg (from, "XKB: variant: \"%s\"\n", s); 490 } 491 492 s = NULL; 493 if (g_cmdline.xkbOptions) 494 { 495 s = g_cmdline.xkbOptions; 496 from = X_CMDLINE; 497 } 498#ifdef XWIN_XF86CONFIG 499 else 500 { 501 s = winSetStrOption (kbd->inp_option_lst, "XkbOptions", NULL); 502 from = X_CONFIG; 503 } 504#endif 505 if (s) 506 { 507 g_winInfo.xkb.options = NULL_IF_EMPTY (s); 508 winMsg (from, "XKB: options: \"%s\"\n", s); 509 } 510 511#ifdef XWIN_XF86CONFIG 512 } 513#endif 514 515 return TRUE; 516} 517 518 519#ifdef XWIN_XF86CONFIG 520Bool 521winConfigMouse (DeviceIntPtr pDevice) 522{ 523 MessageType mousefrom = X_CONFIG; 524 525 XF86ConfInputPtr mouse = NULL; 526 XF86ConfInputPtr input_list = NULL; 527 528 if (g_cmdline.mouse) 529 mousefrom = X_CMDLINE; 530 531 if (g_xf86configptr != NULL) 532 input_list = g_xf86configptr->conf_input_lst; 533 534 while (input_list != NULL) 535 { 536 if (winNameCompare (input_list->inp_driver, "mouse") == 0) 537 { 538 /* Check if device name matches requested name */ 539 if (g_cmdline.mouse && winNameCompare (input_list->inp_identifier, 540 g_cmdline.mouse)) 541 continue; 542 mouse = input_list; 543 } 544 input_list = input_list->list.next; 545 } 546 547 if (mouse != NULL) 548 { 549 if (mouse->inp_identifier) 550 winMsg (mousefrom, "Using pointer \"%s\" as primary pointer\n", 551 mouse->inp_identifier); 552 553 g_winInfo.pointer.emulate3Buttons = 554 winSetBoolOption (mouse->inp_option_lst, "Emulate3Buttons", FALSE); 555 if (g_cmdline.emulate3buttons) 556 g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons; 557 558 g_winInfo.pointer.emulate3Timeout = 559 winSetIntOption (mouse->inp_option_lst, "Emulate3Timeout", 50); 560 if (g_cmdline.emulate3timeout) 561 g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout; 562 } 563 else 564 { 565 winMsg (X_ERROR, "No primary pointer configured\n"); 566 winMsg (X_DEFAULT, "Using compiletime defaults for pointer\n"); 567 } 568 569 return TRUE; 570} 571 572 573Bool 574winConfigFiles () 575{ 576 MessageType from; 577 XF86ConfFilesPtr filesptr = NULL; 578 579 /* set some shortcuts */ 580 if (g_xf86configptr != NULL) 581 { 582 filesptr = g_xf86configptr->conf_files; 583 } 584 585 586 /* Fontpath */ 587 from = X_DEFAULT; 588 589 if (g_cmdline.fontPath) 590 { 591 from = X_CMDLINE; 592 defaultFontPath = g_cmdline.fontPath; 593 } 594 else if (filesptr != NULL && filesptr->file_fontpath) 595 { 596 from = X_CONFIG; 597 defaultFontPath = strdup (filesptr->file_fontpath); 598 } 599 winMsg (from, "FontPath set to \"%s\"\n", defaultFontPath); 600 601 return TRUE; 602} 603#else 604Bool 605winConfigFiles (void) 606{ 607 /* Fontpath */ 608 if (g_cmdline.fontPath) 609 { 610 defaultFontPath = g_cmdline.fontPath; 611 winMsg (X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath); 612 } 613 614 return TRUE; 615} 616#endif 617 618 619Bool 620winConfigOptions (void) 621{ 622 return TRUE; 623} 624 625 626Bool 627winConfigScreens (void) 628{ 629 return TRUE; 630} 631 632 633#ifdef XWIN_XF86CONFIG 634char * 635winSetStrOption (pointer optlist, const char *name, char *deflt) 636{ 637 OptionInfoRec o; 638 639 o.name = name; 640 o.type = OPTV_STRING; 641 if (ParseOptionValue (-1, optlist, &o)) 642 deflt = o.value.str; 643 if (deflt) 644 return strdup (deflt); 645 else 646 return NULL; 647} 648 649 650int 651winSetBoolOption (pointer optlist, const char *name, int deflt) 652{ 653 OptionInfoRec o; 654 655 o.name = name; 656 o.type = OPTV_BOOLEAN; 657 if (ParseOptionValue (-1, optlist, &o)) 658 deflt = o.value.bool; 659 return deflt; 660} 661 662 663int 664winSetIntOption (pointer optlist, const char *name, int deflt) 665{ 666 OptionInfoRec o; 667 668 o.name = name; 669 o.type = OPTV_INTEGER; 670 if (ParseOptionValue (-1, optlist, &o)) 671 deflt = o.value.num; 672 return deflt; 673} 674 675 676double 677winSetRealOption (pointer optlist, const char *name, double deflt) 678{ 679 OptionInfoRec o; 680 681 o.name = name; 682 o.type = OPTV_REAL; 683 if (ParseOptionValue (-1, optlist, &o)) 684 deflt = o.value.realnum; 685 return deflt; 686} 687 688double 689winSetPercentOption (pointer optlist, const char *name, double deflt) 690{ 691 OptionInfoRec o; 692 693 o.name = name; 694 o.type = OPTV_PERCENT; 695 if (ParseOptionValue (-1, optlist, &o)) 696 deflt = o.value.realnum; 697 return deflt; 698} 699#endif 700 701 702/* 703 * Compare two strings for equality. This is caseinsensitive and 704 * The characters '_', ' ' (space) and '\t' (tab) are treated as 705 * not existing. 706 */ 707 708int 709winNameCompare (const char *s1, const char *s2) 710{ 711 char c1, c2; 712 713 if (!s1 || *s1 == 0) 714 { 715 if (!s2 || *s2 == 0) 716 return 0; 717 else 718 return 1; 719 } 720 721 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 722 s1++; 723 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 724 s2++; 725 726 c1 = (isupper ((int)*s1) ? tolower ((int)*s1) : *s1); 727 c2 = (isupper ((int)*s2) ? tolower ((int)*s2) : *s2); 728 729 while (c1 == c2) 730 { 731 if (c1 == 0) 732 return 0; 733 s1++; 734 s2++; 735 736 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 737 s1++; 738 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 739 s2++; 740 741 c1 = (isupper ((int)*s1) ? tolower ((int)*s1) : *s1); 742 c2 = (isupper ((int)*s2) ? tolower ((int)*s2) : *s2); 743 } 744 return c1 - c2; 745} 746 747 748#ifdef XWIN_XF86CONFIG 749/* 750 * Find the named option in the list. 751 * @return the pointer to the option record, or NULL if not found. 752 */ 753 754XF86OptionPtr 755winFindOption (XF86OptionPtr list, const char *name) 756{ 757 while (list) 758 { 759 if (winNameCompare (list->opt_name, name) == 0) 760 return list; 761 list = list->list.next; 762 } 763 return NULL; 764} 765 766 767/* 768 * Find the Value of an named option. 769 * @return The option value or NULL if not found. 770 */ 771 772char * 773winFindOptionValue (XF86OptionPtr list, const char *name) 774{ 775 list = winFindOption (list, name); 776 if (list) 777 { 778 if (list->opt_val) 779 return list->opt_val; 780 else 781 return ""; 782 } 783 return NULL; 784} 785 786 787/* 788 * Parse the option. 789 */ 790 791static Bool 792ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p) 793{ 794 char *s, *end; 795 796 if ((s = winFindOptionValue (options, p->name)) != NULL) 797 { 798 switch (p->type) 799 { 800 case OPTV_INTEGER: 801 if (*s == '\0') 802 { 803 winDrvMsg (scrnIndex, X_WARNING, 804 "Option \"%s\" requires an integer value\n", 805 p->name); 806 p->found = FALSE; 807 } 808 else 809 { 810 p->value.num = strtoul (s, &end, 0); 811 if (*end == '\0') 812 { 813 p->found = TRUE; 814 } 815 else 816 { 817 winDrvMsg (scrnIndex, X_WARNING, 818 "Option \"%s\" requires an integer value\n", 819 p->name); 820 p->found = FALSE; 821 } 822 } 823 break; 824 case OPTV_STRING: 825 if (*s == '\0') 826 { 827 winDrvMsg (scrnIndex, X_WARNING, 828 "Option \"%s\" requires an string value\n", p->name); 829 p->found = FALSE; 830 } 831 else 832 { 833 p->value.str = s; 834 p->found = TRUE; 835 } 836 break; 837 case OPTV_ANYSTR: 838 p->value.str = s; 839 p->found = TRUE; 840 break; 841 case OPTV_REAL: 842 if (*s == '\0') 843 { 844 winDrvMsg (scrnIndex, X_WARNING, 845 "Option \"%s\" requires a floating point value\n", 846 p->name); 847 p->found = FALSE; 848 } 849 else 850 { 851 p->value.realnum = strtod (s, &end); 852 if (*end == '\0') 853 { 854 p->found = TRUE; 855 } 856 else 857 { 858 winDrvMsg (scrnIndex, X_WARNING, 859 "Option \"%s\" requires a floating point value\n", 860 p->name); 861 p->found = FALSE; 862 } 863 } 864 break; 865 case OPTV_BOOLEAN: 866 if (GetBoolValue (p, s)) 867 { 868 p->found = TRUE; 869 } 870 else 871 { 872 winDrvMsg (scrnIndex, X_WARNING, 873 "Option \"%s\" requires a boolean value\n", p->name); 874 p->found = FALSE; 875 } 876 break; 877 case OPTV_PERCENT: 878 if (*s == '\0') 879 { 880 winDrvMsg (scrnIndex, X_WARNING, 881 "Option \"%s\" requires a percent value\n", 882 p->name); 883 p->found = FALSE; 884 } 885 else 886 { 887 double percent = strtod (s, &end); 888 889 if (end != s && winNameCompare (end, "%")) 890 { 891 p->found = TRUE; 892 p->value.realnum = percent; 893 } 894 else 895 { 896 winDrvMsg (scrnIndex, X_WARNING, 897 "Option \"%s\" requires a frequency value\n", 898 p->name); 899 p->found = FALSE; 900 } 901 } 902 case OPTV_FREQ: 903 if (*s == '\0') 904 { 905 winDrvMsg (scrnIndex, X_WARNING, 906 "Option \"%s\" requires a frequency value\n", 907 p->name); 908 p->found = FALSE; 909 } 910 else 911 { 912 double freq = strtod (s, &end); 913 int units = 0; 914 915 if (end != s) 916 { 917 p->found = TRUE; 918 if (!winNameCompare (end, "Hz")) 919 units = 1; 920 else if (!winNameCompare (end, "kHz") || 921 !winNameCompare (end, "k")) 922 units = 1000; 923 else if (!winNameCompare (end, "MHz") || 924 !winNameCompare (end, "M")) 925 units = 1000000; 926 else 927 { 928 winDrvMsg (scrnIndex, X_WARNING, 929 "Option \"%s\" requires a frequency value\n", 930 p->name); 931 p->found = FALSE; 932 } 933 if (p->found) 934 freq *= (double) units; 935 } 936 else 937 { 938 winDrvMsg (scrnIndex, X_WARNING, 939 "Option \"%s\" requires a frequency value\n", 940 p->name); 941 p->found = FALSE; 942 } 943 if (p->found) 944 { 945 p->value.freq.freq = freq; 946 p->value.freq.units = units; 947 } 948 } 949 break; 950 case OPTV_NONE: 951 /* Should never get here */ 952 p->found = FALSE; 953 break; 954 } 955 if (p->found) 956 { 957 winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name); 958 if (!(p->type == OPTV_BOOLEAN && *s == 0)) 959 { 960 winErrorFVerb (2, " \"%s\"", s); 961 } 962 winErrorFVerb (2, "\n"); 963 } 964 } 965 else if (p->type == OPTV_BOOLEAN) 966 { 967 /* Look for matches with options with or without a "No" prefix. */ 968 char *n, *newn; 969 OptionInfoRec opt; 970 971 n = winNormalizeName (p->name); 972 if (!n) 973 { 974 p->found = FALSE; 975 return FALSE; 976 } 977 if (strncmp (n, "no", 2) == 0) 978 { 979 newn = n + 2; 980 } 981 else 982 { 983 free (n); 984 n = malloc (strlen (p->name) + 2 + 1); 985 if (!n) 986 { 987 p->found = FALSE; 988 return FALSE; 989 } 990 strcpy (n, "No"); 991 strcat (n, p->name); 992 newn = n; 993 } 994 if ((s = winFindOptionValue (options, newn)) != NULL) 995 { 996 if (GetBoolValue (&opt, s)) 997 { 998 p->value.bool = !opt.value.bool; 999 p->found = TRUE; 1000 } 1001 else 1002 { 1003 winDrvMsg (scrnIndex, X_WARNING, 1004 "Option \"%s\" requires a boolean value\n", newn); 1005 p->found = FALSE; 1006 } 1007 } 1008 else 1009 { 1010 p->found = FALSE; 1011 } 1012 if (p->found) 1013 { 1014 winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); 1015 if (*s != 0) 1016 { 1017 winErrorFVerb (2, " \"%s\"", s); 1018 } 1019 winErrorFVerb (2, "\n"); 1020 } 1021 free (n); 1022 } 1023 else 1024 { 1025 p->found = FALSE; 1026 } 1027 return p->found; 1028} 1029 1030 1031static Bool 1032configLayout (serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, 1033 char *default_layout) 1034{ 1035#if 0 1036#pragma warn UNIMPLEMENTED 1037#endif 1038 return TRUE; 1039} 1040 1041 1042static Bool 1043configImpliedLayout (serverLayoutPtr servlayoutp, 1044 XF86ConfScreenPtr conf_screen) 1045{ 1046#if 0 1047#pragma warn UNIMPLEMENTED 1048#endif 1049 return TRUE; 1050} 1051 1052 1053static Bool 1054GetBoolValue (OptionInfoPtr p, const char *s) 1055{ 1056 if (*s == 0) 1057 { 1058 p->value.bool = TRUE; 1059 } 1060 else 1061 { 1062 if (winNameCompare (s, "1") == 0) 1063 p->value.bool = TRUE; 1064 else if (winNameCompare (s, "on") == 0) 1065 p->value.bool = TRUE; 1066 else if (winNameCompare (s, "true") == 0) 1067 p->value.bool = TRUE; 1068 else if (winNameCompare (s, "yes") == 0) 1069 p->value.bool = TRUE; 1070 else if (winNameCompare (s, "0") == 0) 1071 p->value.bool = FALSE; 1072 else if (winNameCompare (s, "off") == 0) 1073 p->value.bool = FALSE; 1074 else if (winNameCompare (s, "false") == 0) 1075 p->value.bool = FALSE; 1076 else if (winNameCompare (s, "no") == 0) 1077 p->value.bool = FALSE; 1078 } 1079 return TRUE; 1080} 1081#endif 1082 1083 1084char * 1085winNormalizeName (const char *s) 1086{ 1087 char *ret, *q; 1088 const char *p; 1089 1090 if (s == NULL) 1091 return NULL; 1092 1093 ret = malloc (strlen (s) + 1); 1094 for (p = s, q = ret; *p != 0; p++) 1095 { 1096 switch (*p) 1097 { 1098 case '_': 1099 case ' ': 1100 case '\t': 1101 continue; 1102 default: 1103 if (isupper ((int)*p)) 1104 *q++ = tolower ((int)*p); 1105 else 1106 *q++ = *p; 1107 } 1108 } 1109 *q = '\0'; 1110 return ret; 1111} 1112 1113