winconfig.c revision 6747b715
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 static unsigned int layoutNum = 0; 244 int keyboardType; 245#ifdef XWIN_XF86CONFIG 246 XF86ConfInputPtr kbd = NULL; 247 XF86ConfInputPtr input_list = NULL; 248 MessageType kbdfrom = X_CONFIG; 249#endif 250 MessageType from = X_DEFAULT; 251 char *s = NULL; 252 253 /* Setup defaults */ 254 XkbGetRulesDflts(&g_winInfo.xkb); 255 256 /* 257 * Query the windows autorepeat settings and change the xserver defaults. 258 */ 259 { 260 int kbd_delay; 261 DWORD kbd_speed; 262 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) && 263 SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0)) 264 { 265 switch (kbd_delay) 266 { 267 case 0: g_winInfo.keyboard.delay = 250; break; 268 case 1: g_winInfo.keyboard.delay = 500; break; 269 case 2: g_winInfo.keyboard.delay = 750; break; 270 default: 271 case 3: g_winInfo.keyboard.delay = 1000; break; 272 } 273 g_winInfo.keyboard.rate = (kbd_speed>0)?kbd_speed:1; 274 winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%d, rate=%d\n", 275 g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); 276 } 277 } 278 279 280 keyboardType = GetKeyboardType (0); 281 if (keyboardType > 0 && GetKeyboardLayoutName (layoutName)) 282 { 283 WinKBLayoutPtr pLayout; 284 Bool bfound = FALSE; 285 286 if (! layoutNum) 287 layoutNum = strtoul (layoutName, (char **)NULL, 16); 288 if ((layoutNum & 0xffff) == 0x411) { 289 /* The japanese layouts know a lot of different IMEs which all have 290 different layout numbers set. Map them to a single entry. 291 Same might apply for chinese, korean and other symbol languages 292 too */ 293 layoutNum = (layoutNum & 0xffff); 294 if (keyboardType == 7) 295 { 296 /* Japanese layouts have problems with key event messages 297 such as the lack of WM_KEYUP for Caps Lock key. 298 Loading US layout fixes this problem. */ 299 if (LoadKeyboardLayout("00000409", KLF_ACTIVATE) != NULL) 300 winMsg (X_INFO, "Loading US keyboard layout.\n"); 301 else 302 winMsg (X_ERROR, "LoadKeyboardLaout failed.\n"); 303 } 304 } 305 winMsg (X_PROBED, "winConfigKeyboard - Layout: \"%s\" (%08x) \n", 306 layoutName, layoutNum); 307 308 for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) 309 { 310 if (pLayout->winlayout != layoutNum) 311 continue; 312 if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType) 313 continue; 314 315 bfound = TRUE; 316 winMsg (X_PROBED, 317 "Using preset keyboard for \"%s\" (%x), type \"%d\"\n", 318 pLayout->layoutname, pLayout->winlayout, keyboardType); 319 320 g_winInfo.xkb.model = pLayout->xkbmodel; 321 g_winInfo.xkb.layout = pLayout->xkblayout; 322 g_winInfo.xkb.variant = pLayout->xkbvariant; 323 g_winInfo.xkb.options = pLayout->xkboptions; 324 break; 325 } 326 327 if (!bfound) 328 { 329 HKEY regkey = NULL; 330 const char regtempl[] = 331 "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"; 332 char *regpath; 333 unsigned char lname[256]; 334 DWORD namesize = sizeof(lname); 335 336 regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1); 337 strcpy(regpath, regtempl); 338 strcat(regpath, layoutName); 339 340 if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, ®key) && 341 !RegQueryValueEx(regkey, "Layout Text", 0, NULL, lname, &namesize)) 342 { 343 winMsg (X_ERROR, 344 "Keyboardlayout \"%s\" (%s) is unknown\n", lname, layoutName); 345 } 346 347 /* Close registry key */ 348 if (regkey) 349 RegCloseKey (regkey); 350 free(regpath); 351 } 352 } 353 354 /* parse the configuration */ 355#ifdef XWIN_XF86CONFIG 356 if (g_cmdline.keyboard) 357 kbdfrom = X_CMDLINE; 358 359 /* 360 * Until the layout code is finished, I search for the keyboard 361 * device and configure the server with it. 362 */ 363 364 if (g_xf86configptr != NULL) 365 input_list = g_xf86configptr->conf_input_lst; 366 367 while (input_list != NULL) 368 { 369 if (winNameCompare (input_list->inp_driver, "keyboard") == 0) 370 { 371 /* Check if device name matches requested name */ 372 if (g_cmdline.keyboard && winNameCompare (input_list->inp_identifier, 373 g_cmdline.keyboard)) 374 continue; 375 kbd = input_list; 376 } 377 input_list = input_list->list.next; 378 } 379 380 if (kbd != NULL) 381 { 382 383 if (kbd->inp_identifier) 384 winMsg (kbdfrom, "Using keyboard \"%s\" as primary keyboard\n", 385 kbd->inp_identifier); 386 387 if ((s = winSetStrOption(kbd->inp_option_lst, "AutoRepeat", NULL))) 388 { 389 if ((sscanf(s, "%ld %ld", &g_winInfo.keyboard.delay, 390 &g_winInfo.keyboard.rate) != 2) || 391 (g_winInfo.keyboard.delay < 1) || 392 (g_winInfo.keyboard.rate == 0) || 393 (1000 / g_winInfo.keyboard.rate) < 1) 394 { 395 winErrorFVerb (2, "\"%s\" is not a valid AutoRepeat value", s); 396 free(s); 397 return FALSE; 398 } 399 free(s); 400 winMsg (X_CONFIG, "AutoRepeat: %ld %ld\n", 401 g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); 402 } 403#endif 404 405 s = NULL; 406 if (g_cmdline.xkbRules) 407 { 408 s = g_cmdline.xkbRules; 409 from = X_CMDLINE; 410 } 411#ifdef XWIN_XF86CONFIG 412 else 413 { 414 s = winSetStrOption (kbd->inp_option_lst, "XkbRules", NULL); 415 from = X_CONFIG; 416 } 417#endif 418 if (s) 419 { 420 g_winInfo.xkb.rules = NULL_IF_EMPTY (s); 421 winMsg (from, "XKB: rules: \"%s\"\n", s); 422 } 423 424 s = NULL; 425 if (g_cmdline.xkbModel) 426 { 427 s = g_cmdline.xkbModel; 428 from = X_CMDLINE; 429 } 430#ifdef XWIN_XF86CONFIG 431 else 432 { 433 s = winSetStrOption (kbd->inp_option_lst, "XkbModel", NULL); 434 from = X_CONFIG; 435 } 436#endif 437 if (s) 438 { 439 g_winInfo.xkb.model = NULL_IF_EMPTY (s); 440 winMsg (from, "XKB: model: \"%s\"\n", s); 441 } 442 443 s = NULL; 444 if (g_cmdline.xkbLayout) 445 { 446 s = g_cmdline.xkbLayout; 447 from = X_CMDLINE; 448 } 449#ifdef XWIN_XF86CONFIG 450 else 451 { 452 s = winSetStrOption (kbd->inp_option_lst, "XkbLayout", NULL); 453 from = X_CONFIG; 454 } 455#endif 456 if (s) 457 { 458 g_winInfo.xkb.layout = NULL_IF_EMPTY (s); 459 winMsg (from, "XKB: layout: \"%s\"\n", s); 460 } 461 462 s = NULL; 463 if (g_cmdline.xkbVariant) 464 { 465 s = g_cmdline.xkbVariant; 466 from = X_CMDLINE; 467 } 468#ifdef XWIN_XF86CONFIG 469 else 470 { 471 s = winSetStrOption (kbd->inp_option_lst, "XkbVariant", NULL); 472 from = X_CONFIG; 473 } 474#endif 475 if (s) 476 { 477 g_winInfo.xkb.variant = NULL_IF_EMPTY (s); 478 winMsg (from, "XKB: variant: \"%s\"\n", s); 479 } 480 481 s = NULL; 482 if (g_cmdline.xkbOptions) 483 { 484 s = g_cmdline.xkbOptions; 485 from = X_CMDLINE; 486 } 487#ifdef XWIN_XF86CONFIG 488 else 489 { 490 s = winSetStrOption (kbd->inp_option_lst, "XkbOptions", NULL); 491 from = X_CONFIG; 492 } 493#endif 494 if (s) 495 { 496 g_winInfo.xkb.options = NULL_IF_EMPTY (s); 497 winMsg (from, "XKB: options: \"%s\"\n", s); 498 } 499 500#ifdef XWIN_XF86CONFIG 501 } 502#endif 503 504 return TRUE; 505} 506 507 508#ifdef XWIN_XF86CONFIG 509Bool 510winConfigMouse (DeviceIntPtr pDevice) 511{ 512 MessageType mousefrom = X_CONFIG; 513 514 XF86ConfInputPtr mouse = NULL; 515 XF86ConfInputPtr input_list = NULL; 516 517 if (g_cmdline.mouse) 518 mousefrom = X_CMDLINE; 519 520 if (g_xf86configptr != NULL) 521 input_list = g_xf86configptr->conf_input_lst; 522 523 while (input_list != NULL) 524 { 525 if (winNameCompare (input_list->inp_driver, "mouse") == 0) 526 { 527 /* Check if device name matches requested name */ 528 if (g_cmdline.mouse && winNameCompare (input_list->inp_identifier, 529 g_cmdline.mouse)) 530 continue; 531 mouse = input_list; 532 } 533 input_list = input_list->list.next; 534 } 535 536 if (mouse != NULL) 537 { 538 if (mouse->inp_identifier) 539 winMsg (mousefrom, "Using pointer \"%s\" as primary pointer\n", 540 mouse->inp_identifier); 541 542 g_winInfo.pointer.emulate3Buttons = 543 winSetBoolOption (mouse->inp_option_lst, "Emulate3Buttons", FALSE); 544 if (g_cmdline.emulate3buttons) 545 g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons; 546 547 g_winInfo.pointer.emulate3Timeout = 548 winSetIntOption (mouse->inp_option_lst, "Emulate3Timeout", 50); 549 if (g_cmdline.emulate3timeout) 550 g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout; 551 } 552 else 553 { 554 winMsg (X_ERROR, "No primary pointer configured\n"); 555 winMsg (X_DEFAULT, "Using compiletime defaults for pointer\n"); 556 } 557 558 return TRUE; 559} 560 561 562Bool 563winConfigFiles () 564{ 565 MessageType from; 566 XF86ConfFilesPtr filesptr = NULL; 567 568 /* set some shortcuts */ 569 if (g_xf86configptr != NULL) 570 { 571 filesptr = g_xf86configptr->conf_files; 572 } 573 574 575 /* Fontpath */ 576 from = X_DEFAULT; 577 578 if (g_cmdline.fontPath) 579 { 580 from = X_CMDLINE; 581 defaultFontPath = g_cmdline.fontPath; 582 } 583 else if (filesptr != NULL && filesptr->file_fontpath) 584 { 585 from = X_CONFIG; 586 defaultFontPath = strdup (filesptr->file_fontpath); 587 } 588 winMsg (from, "FontPath set to \"%s\"\n", defaultFontPath); 589 590 return TRUE; 591} 592#else 593Bool 594winConfigFiles (void) 595{ 596 /* Fontpath */ 597 if (g_cmdline.fontPath) 598 { 599 defaultFontPath = g_cmdline.fontPath; 600 winMsg (X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath); 601 } 602 603 return TRUE; 604} 605#endif 606 607 608Bool 609winConfigOptions (void) 610{ 611 return TRUE; 612} 613 614 615Bool 616winConfigScreens (void) 617{ 618 return TRUE; 619} 620 621 622#ifdef XWIN_XF86CONFIG 623char * 624winSetStrOption (pointer optlist, const char *name, char *deflt) 625{ 626 OptionInfoRec o; 627 628 o.name = name; 629 o.type = OPTV_STRING; 630 if (ParseOptionValue (-1, optlist, &o)) 631 deflt = o.value.str; 632 if (deflt) 633 return strdup (deflt); 634 else 635 return NULL; 636} 637 638 639int 640winSetBoolOption (pointer optlist, const char *name, int deflt) 641{ 642 OptionInfoRec o; 643 644 o.name = name; 645 o.type = OPTV_BOOLEAN; 646 if (ParseOptionValue (-1, optlist, &o)) 647 deflt = o.value.bool; 648 return deflt; 649} 650 651 652int 653winSetIntOption (pointer optlist, const char *name, int deflt) 654{ 655 OptionInfoRec o; 656 657 o.name = name; 658 o.type = OPTV_INTEGER; 659 if (ParseOptionValue (-1, optlist, &o)) 660 deflt = o.value.num; 661 return deflt; 662} 663 664 665double 666winSetRealOption (pointer optlist, const char *name, double deflt) 667{ 668 OptionInfoRec o; 669 670 o.name = name; 671 o.type = OPTV_REAL; 672 if (ParseOptionValue (-1, optlist, &o)) 673 deflt = o.value.realnum; 674 return deflt; 675} 676 677double 678winSetPercentOption (pointer optlist, const char *name, double deflt) 679{ 680 OptionInfoRec o; 681 682 o.name = name; 683 o.type = OPTV_PERCENT; 684 if (ParseOptionValue (-1, optlist, &o)) 685 deflt = o.value.realnum; 686 return deflt; 687} 688#endif 689 690 691/* 692 * Compare two strings for equality. This is caseinsensitive and 693 * The characters '_', ' ' (space) and '\t' (tab) are treated as 694 * not existing. 695 */ 696 697int 698winNameCompare (const char *s1, const char *s2) 699{ 700 char c1, c2; 701 702 if (!s1 || *s1 == 0) 703 { 704 if (!s2 || *s2 == 0) 705 return 0; 706 else 707 return 1; 708 } 709 710 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 711 s1++; 712 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 713 s2++; 714 715 c1 = (isupper (*s1) ? tolower (*s1) : *s1); 716 c2 = (isupper (*s2) ? tolower (*s2) : *s2); 717 718 while (c1 == c2) 719 { 720 if (c1 == 0) 721 return 0; 722 s1++; 723 s2++; 724 725 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 726 s1++; 727 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 728 s2++; 729 730 c1 = (isupper (*s1) ? tolower (*s1) : *s1); 731 c2 = (isupper (*s2) ? tolower (*s2) : *s2); 732 } 733 return c1 - c2; 734} 735 736 737#ifdef XWIN_XF86CONFIG 738/* 739 * Find the named option in the list. 740 * @return the pointer to the option record, or NULL if not found. 741 */ 742 743XF86OptionPtr 744winFindOption (XF86OptionPtr list, const char *name) 745{ 746 while (list) 747 { 748 if (winNameCompare (list->opt_name, name) == 0) 749 return list; 750 list = list->list.next; 751 } 752 return NULL; 753} 754 755 756/* 757 * Find the Value of an named option. 758 * @return The option value or NULL if not found. 759 */ 760 761char * 762winFindOptionValue (XF86OptionPtr list, const char *name) 763{ 764 list = winFindOption (list, name); 765 if (list) 766 { 767 if (list->opt_val) 768 return list->opt_val; 769 else 770 return ""; 771 } 772 return NULL; 773} 774 775 776/* 777 * Parse the option. 778 */ 779 780static Bool 781ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p) 782{ 783 char *s, *end; 784 785 if ((s = winFindOptionValue (options, p->name)) != NULL) 786 { 787 switch (p->type) 788 { 789 case OPTV_INTEGER: 790 if (*s == '\0') 791 { 792 winDrvMsg (scrnIndex, X_WARNING, 793 "Option \"%s\" requires an integer value\n", 794 p->name); 795 p->found = FALSE; 796 } 797 else 798 { 799 p->value.num = strtoul (s, &end, 0); 800 if (*end == '\0') 801 { 802 p->found = TRUE; 803 } 804 else 805 { 806 winDrvMsg (scrnIndex, X_WARNING, 807 "Option \"%s\" requires an integer value\n", 808 p->name); 809 p->found = FALSE; 810 } 811 } 812 break; 813 case OPTV_STRING: 814 if (*s == '\0') 815 { 816 winDrvMsg (scrnIndex, X_WARNING, 817 "Option \"%s\" requires an string value\n", p->name); 818 p->found = FALSE; 819 } 820 else 821 { 822 p->value.str = s; 823 p->found = TRUE; 824 } 825 break; 826 case OPTV_ANYSTR: 827 p->value.str = s; 828 p->found = TRUE; 829 break; 830 case OPTV_REAL: 831 if (*s == '\0') 832 { 833 winDrvMsg (scrnIndex, X_WARNING, 834 "Option \"%s\" requires a floating point value\n", 835 p->name); 836 p->found = FALSE; 837 } 838 else 839 { 840 p->value.realnum = strtod (s, &end); 841 if (*end == '\0') 842 { 843 p->found = TRUE; 844 } 845 else 846 { 847 winDrvMsg (scrnIndex, X_WARNING, 848 "Option \"%s\" requires a floating point value\n", 849 p->name); 850 p->found = FALSE; 851 } 852 } 853 break; 854 case OPTV_BOOLEAN: 855 if (GetBoolValue (p, s)) 856 { 857 p->found = TRUE; 858 } 859 else 860 { 861 winDrvMsg (scrnIndex, X_WARNING, 862 "Option \"%s\" requires a boolean value\n", p->name); 863 p->found = FALSE; 864 } 865 break; 866 case OPTV_PERCENT: 867 if (*s == '\0') 868 { 869 winDrvMsg (scrnIndex, X_WARNING, 870 "Option \"%s\" requires a percent value\n", 871 p->name); 872 p->found = FALSE; 873 } 874 else 875 { 876 double percent = strtod (s, &end); 877 878 if (end != s && winNameCompare (end, "%")) 879 { 880 p->found = TRUE; 881 p->value.realnum = percent; 882 } 883 else 884 { 885 winDrvMsg (scrnIndex, X_WARNING, 886 "Option \"%s\" requires a frequency value\n", 887 p->name); 888 p->found = FALSE; 889 } 890 } 891 case OPTV_FREQ: 892 if (*s == '\0') 893 { 894 winDrvMsg (scrnIndex, X_WARNING, 895 "Option \"%s\" requires a frequency value\n", 896 p->name); 897 p->found = FALSE; 898 } 899 else 900 { 901 double freq = strtod (s, &end); 902 int units = 0; 903 904 if (end != s) 905 { 906 p->found = TRUE; 907 if (!winNameCompare (end, "Hz")) 908 units = 1; 909 else if (!winNameCompare (end, "kHz") || 910 !winNameCompare (end, "k")) 911 units = 1000; 912 else if (!winNameCompare (end, "MHz") || 913 !winNameCompare (end, "M")) 914 units = 1000000; 915 else 916 { 917 winDrvMsg (scrnIndex, X_WARNING, 918 "Option \"%s\" requires a frequency value\n", 919 p->name); 920 p->found = FALSE; 921 } 922 if (p->found) 923 freq *= (double) units; 924 } 925 else 926 { 927 winDrvMsg (scrnIndex, X_WARNING, 928 "Option \"%s\" requires a frequency value\n", 929 p->name); 930 p->found = FALSE; 931 } 932 if (p->found) 933 { 934 p->value.freq.freq = freq; 935 p->value.freq.units = units; 936 } 937 } 938 break; 939 case OPTV_NONE: 940 /* Should never get here */ 941 p->found = FALSE; 942 break; 943 } 944 if (p->found) 945 { 946 winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name); 947 if (!(p->type == OPTV_BOOLEAN && *s == 0)) 948 { 949 winErrorFVerb (2, " \"%s\"", s); 950 } 951 winErrorFVerb (2, "\n"); 952 } 953 } 954 else if (p->type == OPTV_BOOLEAN) 955 { 956 /* Look for matches with options with or without a "No" prefix. */ 957 char *n, *newn; 958 OptionInfoRec opt; 959 960 n = winNormalizeName (p->name); 961 if (!n) 962 { 963 p->found = FALSE; 964 return FALSE; 965 } 966 if (strncmp (n, "no", 2) == 0) 967 { 968 newn = n + 2; 969 } 970 else 971 { 972 free (n); 973 n = malloc (strlen (p->name) + 2 + 1); 974 if (!n) 975 { 976 p->found = FALSE; 977 return FALSE; 978 } 979 strcpy (n, "No"); 980 strcat (n, p->name); 981 newn = n; 982 } 983 if ((s = winFindOptionValue (options, newn)) != NULL) 984 { 985 if (GetBoolValue (&opt, s)) 986 { 987 p->value.bool = !opt.value.bool; 988 p->found = TRUE; 989 } 990 else 991 { 992 winDrvMsg (scrnIndex, X_WARNING, 993 "Option \"%s\" requires a boolean value\n", newn); 994 p->found = FALSE; 995 } 996 } 997 else 998 { 999 p->found = FALSE; 1000 } 1001 if (p->found) 1002 { 1003 winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); 1004 if (*s != 0) 1005 { 1006 winErrorFVerb (2, " \"%s\"", s); 1007 } 1008 winErrorFVerb (2, "\n"); 1009 } 1010 free (n); 1011 } 1012 else 1013 { 1014 p->found = FALSE; 1015 } 1016 return p->found; 1017} 1018 1019 1020static Bool 1021configLayout (serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, 1022 char *default_layout) 1023{ 1024#if 0 1025#pragma warn UNIMPLEMENTED 1026#endif 1027 return TRUE; 1028} 1029 1030 1031static Bool 1032configImpliedLayout (serverLayoutPtr servlayoutp, 1033 XF86ConfScreenPtr conf_screen) 1034{ 1035#if 0 1036#pragma warn UNIMPLEMENTED 1037#endif 1038 return TRUE; 1039} 1040 1041 1042static Bool 1043GetBoolValue (OptionInfoPtr p, const char *s) 1044{ 1045 if (*s == 0) 1046 { 1047 p->value.bool = TRUE; 1048 } 1049 else 1050 { 1051 if (winNameCompare (s, "1") == 0) 1052 p->value.bool = TRUE; 1053 else if (winNameCompare (s, "on") == 0) 1054 p->value.bool = TRUE; 1055 else if (winNameCompare (s, "true") == 0) 1056 p->value.bool = TRUE; 1057 else if (winNameCompare (s, "yes") == 0) 1058 p->value.bool = TRUE; 1059 else if (winNameCompare (s, "0") == 0) 1060 p->value.bool = FALSE; 1061 else if (winNameCompare (s, "off") == 0) 1062 p->value.bool = FALSE; 1063 else if (winNameCompare (s, "false") == 0) 1064 p->value.bool = FALSE; 1065 else if (winNameCompare (s, "no") == 0) 1066 p->value.bool = FALSE; 1067 } 1068 return TRUE; 1069} 1070#endif 1071 1072 1073char * 1074winNormalizeName (const char *s) 1075{ 1076 char *ret, *q; 1077 const char *p; 1078 1079 if (s == NULL) 1080 return NULL; 1081 1082 ret = malloc (strlen (s) + 1); 1083 for (p = s, q = ret; *p != 0; p++) 1084 { 1085 switch (*p) 1086 { 1087 case '_': 1088 case ' ': 1089 case '\t': 1090 continue; 1091 default: 1092 if (isupper (*p)) 1093 *q++ = tolower (*p); 1094 else 1095 *q++ = *p; 1096 } 1097 } 1098 *q = '\0'; 1099 return ret; 1100} 1101 1102