xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

winconfig.c (30062B)


      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 
     61 XF86ConfigPtr g_xf86configptr = NULL;
     62 #endif
     63 
     64 WinCmdlineRec 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 
     84 winInfoRec 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
    107 serverLayoutRec g_winConfigLayout;
    108 
    109 static Bool ParseOptionValue(int scrnIndex, void *options, OptionInfoPtr p);
    110 static Bool configLayout(serverLayoutPtr, XF86ConfLayoutPtr, char *);
    111 static Bool configImpliedLayout(serverLayoutPtr, XF86ConfScreenPtr);
    112 static Bool GetBoolValue(OptionInfoPtr p, const char *s);
    113 
    114 Bool
    115 winReadConfigfile()
    116 {
    117     Bool retval = TRUE;
    118     char *filename, *dirname;
    119     MessageType filefrom = X_DEFAULT;
    120     MessageType dirfrom = X_DEFAULT;
    121     char *xf86ConfigFile = NULL;
    122     char *xf86ConfigDir = NULL;
    123 
    124     if (g_cmdline.configFile) {
    125         filefrom = X_CMDLINE;
    126         xf86ConfigFile = g_cmdline.configFile;
    127     }
    128     if (g_cmdline.configDir) {
    129         dirfrom = X_CMDLINE;
    130         xf86ConfigDir = g_cmdline.configDir;
    131     }
    132 
    133     /* Parse config file into data structure */
    134     xf86initConfigFiles();
    135     dirname = xf86openConfigDirFiles(CONFIGDIRPATH, xf86ConfigDir, PROJECTROOT);
    136     filename = xf86openConfigFile(CONFIGPATH, xf86ConfigFile, PROJECTROOT);
    137 
    138     /* Hack for backward compatibility */
    139     if (!filename && from == X_DEFAULT)
    140         filename = xf86openConfigFile(CONFIGPATH, "XF86Config", PROJECTROOT);
    141 
    142     if (filename) {
    143         winMsg(from, "Using config file: \"%s\"\n", filename);
    144     }
    145     else {
    146         winMsg(X_ERROR, "Unable to locate/open config file");
    147         if (xf86ConfigFile)
    148             ErrorF(": \"%s\"", xf86ConfigFile);
    149         ErrorF("\n");
    150     }
    151     if (dirname) {
    152         winMsg(from, "Using config directory: \"%s\"\n", dirname);
    153     }
    154     else {
    155         winMsg(X_ERROR, "Unable to locate/open config directory");
    156         if (xf86ConfigDir)
    157             ErrorF(": \"%s\"", xf86ConfigDir);
    158         ErrorF("\n");
    159     }
    160     if (!filename && !dirname) {
    161         return FALSE;
    162     }
    163     free(filename);
    164     free(dirname);
    165     if ((g_xf86configptr = xf86readConfigFile()) == NULL) {
    166         winMsg(X_ERROR, "Problem parsing the config file\n");
    167         return FALSE;
    168     }
    169     xf86closeConfigFile();
    170 
    171     LogPrintMarkers();
    172 
    173     /* set options from data structure */
    174 
    175     if (g_xf86configptr->conf_layout_lst == NULL ||
    176         g_cmdline.screenname != NULL) {
    177         if (g_cmdline.screenname == NULL) {
    178             winMsg(X_WARNING,
    179                    "No Layout section. Using the first Screen section.\n");
    180         }
    181         if (!configImpliedLayout(&g_winConfigLayout,
    182                                  g_xf86configptr->conf_screen_lst)) {
    183             winMsg(X_ERROR, "Unable to determine the screen layout\n");
    184             return FALSE;
    185         }
    186     }
    187     else {
    188         /* Check if layout is given in the config file */
    189         if (g_xf86configptr->conf_flags != NULL) {
    190             char *dfltlayout = NULL;
    191             void *optlist = g_xf86configptr->conf_flags->flg_option_lst;
    192 
    193             if (optlist && winFindOption(optlist, "defaultserverlayout"))
    194                 dfltlayout =
    195                     winSetStrOption(optlist, "defaultserverlayout", NULL);
    196 
    197             if (!configLayout(&g_winConfigLayout,
    198                               g_xf86configptr->conf_layout_lst, dfltlayout)) {
    199                 winMsg(X_ERROR, "Unable to determine the screen layout\n");
    200                 return FALSE;
    201             }
    202         }
    203         else {
    204             if (!configLayout(&g_winConfigLayout,
    205                               g_xf86configptr->conf_layout_lst, NULL)) {
    206                 winMsg(X_ERROR, "Unable to determine the screen layout\n");
    207                 return FALSE;
    208             }
    209         }
    210     }
    211 
    212     /* setup special config files */
    213     winConfigFiles();
    214     return retval;
    215 }
    216 #endif
    217 
    218 /* load layout definitions */
    219 #include "winlayouts.h"
    220 
    221 /* Set the keyboard configuration */
    222 Bool
    223 winConfigKeyboard(DeviceIntPtr pDevice)
    224 {
    225     char layoutName[KL_NAMELENGTH];
    226     unsigned char layoutFriendlyName[256];
    227     unsigned int layoutNum = 0;
    228     unsigned int deviceIdentifier = 0;
    229     int keyboardType;
    230 
    231 #ifdef XWIN_XF86CONFIG
    232     XF86ConfInputPtr kbd = NULL;
    233     XF86ConfInputPtr input_list = NULL;
    234     MessageType kbdfrom = X_CONFIG;
    235 #endif
    236     MessageType from = X_DEFAULT;
    237     char *s = NULL;
    238 
    239     /* Setup defaults */
    240     XkbGetRulesDflts(&g_winInfo.xkb);
    241 
    242     /*
    243      * Query the windows autorepeat settings and change the xserver defaults.
    244      */
    245     {
    246         int kbd_delay;
    247         DWORD kbd_speed;
    248 
    249         if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) &&
    250             SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0)) {
    251             switch (kbd_delay) {
    252             case 0:
    253                 g_winInfo.keyboard.delay = 250;
    254                 break;
    255             case 1:
    256                 g_winInfo.keyboard.delay = 500;
    257                 break;
    258             case 2:
    259                 g_winInfo.keyboard.delay = 750;
    260                 break;
    261             default:
    262             case 3:
    263                 g_winInfo.keyboard.delay = 1000;
    264                 break;
    265             }
    266             g_winInfo.keyboard.rate = (kbd_speed > 0) ? kbd_speed : 1;
    267             winMsg(X_PROBED, "Setting autorepeat to delay=%ld, rate=%ld\n",
    268                    g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
    269 
    270         }
    271     }
    272 
    273     keyboardType = GetKeyboardType(0);
    274     if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) {
    275         WinKBLayoutPtr pLayout;
    276         Bool bfound = FALSE;
    277         int pass;
    278 
    279         layoutNum = strtoul(layoutName, (char **) NULL, 16);
    280         if ((layoutNum & 0xffff) == 0x411) {
    281             if (keyboardType == 7) {
    282                 /* Japanese layouts have problems with key event messages
    283                    such as the lack of WM_KEYUP for Caps Lock key.
    284                    Loading US layout fixes this problem. */
    285                 if (LoadKeyboardLayout("00000409", KLF_ACTIVATE) != NULL)
    286                     winMsg(X_INFO, "Loading US keyboard layout.\n");
    287                 else
    288                     winMsg(X_ERROR, "LoadKeyboardLayout failed.\n");
    289             }
    290         }
    291 
    292         /* Discover the friendly name of the current layout */
    293         {
    294             HKEY regkey = NULL;
    295             const char regtempl[] =
    296                 "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
    297             char *regpath;
    298             DWORD namesize = sizeof(layoutFriendlyName);
    299 
    300             regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1);
    301             strcpy(regpath, regtempl);
    302             strcat(regpath, layoutName);
    303 
    304             if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, &regkey))
    305                 RegQueryValueEx(regkey, "Layout Text", 0, NULL,
    306                                 layoutFriendlyName, &namesize);
    307 
    308             /* Close registry key */
    309             if (regkey)
    310                 RegCloseKey(regkey);
    311             free(regpath);
    312         }
    313 
    314         winMsg(X_PROBED,
    315                "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
    316                layoutName, layoutNum, layoutFriendlyName, keyboardType);
    317 
    318         deviceIdentifier = layoutNum >> 16;
    319         for (pass = 0; pass < 2; pass++) {
    320             /* If we didn't find an exact match for the input locale identifier,
    321                try to find an match on the language identifier part only  */
    322             if (pass == 1)
    323                 layoutNum = (layoutNum & 0xffff);
    324 
    325             for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
    326                 if (pLayout->winlayout != layoutNum)
    327                     continue;
    328                 if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
    329                     continue;
    330 
    331                 bfound = TRUE;
    332                 winMsg(X_PROBED,
    333                        "Found matching XKB configuration \"%s\"\n",
    334                        pLayout->layoutname);
    335 
    336                 winMsg(X_PROBED,
    337                        "Model = \"%s\" Layout = \"%s\""
    338                        " Variant = \"%s\" Options = \"%s\"\n",
    339                        pLayout->xkbmodel ? pLayout->xkbmodel : "none",
    340                        pLayout->xkblayout ? pLayout->xkblayout : "none",
    341                        pLayout->xkbvariant ? pLayout->xkbvariant : "none",
    342                        pLayout->xkboptions ? pLayout->xkboptions : "none");
    343 
    344                 g_winInfo.xkb.model = pLayout->xkbmodel;
    345                 g_winInfo.xkb.layout = pLayout->xkblayout;
    346                 g_winInfo.xkb.variant = pLayout->xkbvariant;
    347                 g_winInfo.xkb.options = pLayout->xkboptions;
    348 
    349                 if (deviceIdentifier == 0xa000) {
    350                     winMsg(X_PROBED, "Windows keyboard layout device identifier indicates Macintosh, setting Model = \"macintosh\"");
    351                     g_winInfo.xkb.model = "macintosh";
    352                 }
    353 
    354                 break;
    355             }
    356 
    357             if (bfound)
    358                 break;
    359         }
    360 
    361         if (!bfound) {
    362             winMsg(X_ERROR,
    363                    "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n",
    364                    layoutFriendlyName, layoutName);
    365         }
    366     }
    367 
    368     /* parse the configuration */
    369 #ifdef XWIN_XF86CONFIG
    370     if (g_cmdline.keyboard)
    371         kbdfrom = X_CMDLINE;
    372 
    373     /*
    374      * Until the layout code is finished, I search for the keyboard
    375      * device and configure the server with it.
    376      */
    377 
    378     if (g_xf86configptr != NULL)
    379         input_list = g_xf86configptr->conf_input_lst;
    380 
    381     while (input_list != NULL) {
    382         if (winNameCompare(input_list->inp_driver, "keyboard") == 0) {
    383             /* Check if device name matches requested name */
    384             if (g_cmdline.keyboard && winNameCompare(input_list->inp_identifier,
    385                                                      g_cmdline.keyboard))
    386                 continue;
    387             kbd = input_list;
    388         }
    389         input_list = input_list->list.next;
    390     }
    391 
    392     if (kbd != NULL) {
    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             if ((sscanf(s, "%ld %ld", &g_winInfo.keyboard.delay,
    400                         &g_winInfo.keyboard.rate) != 2) ||
    401                 (g_winInfo.keyboard.delay < 1) ||
    402                 (g_winInfo.keyboard.rate == 0) ||
    403                 (1000 / g_winInfo.keyboard.rate) < 1) {
    404                 winErrorFVerb(2, "\"%s\" is not a valid AutoRepeat value", s);
    405                 free(s);
    406                 return FALSE;
    407             }
    408             free(s);
    409             winMsg(X_CONFIG, "AutoRepeat: %ld %ld\n",
    410                    g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
    411         }
    412 #endif
    413 
    414         s = NULL;
    415         if (g_cmdline.xkbRules) {
    416             s = g_cmdline.xkbRules;
    417             from = X_CMDLINE;
    418         }
    419 #ifdef XWIN_XF86CONFIG
    420         else {
    421             s = winSetStrOption(kbd->inp_option_lst, "XkbRules", NULL);
    422             from = X_CONFIG;
    423         }
    424 #endif
    425         if (s) {
    426             g_winInfo.xkb.rules = NULL_IF_EMPTY(s);
    427             winMsg(from, "XKB: rules: \"%s\"\n", s);
    428         }
    429 
    430         s = NULL;
    431         if (g_cmdline.xkbModel) {
    432             s = g_cmdline.xkbModel;
    433             from = X_CMDLINE;
    434         }
    435 #ifdef XWIN_XF86CONFIG
    436         else {
    437             s = winSetStrOption(kbd->inp_option_lst, "XkbModel", NULL);
    438             from = X_CONFIG;
    439         }
    440 #endif
    441         if (s) {
    442             g_winInfo.xkb.model = NULL_IF_EMPTY(s);
    443             winMsg(from, "XKB: model: \"%s\"\n", s);
    444         }
    445 
    446         s = NULL;
    447         if (g_cmdline.xkbLayout) {
    448             s = g_cmdline.xkbLayout;
    449             from = X_CMDLINE;
    450         }
    451 #ifdef XWIN_XF86CONFIG
    452         else {
    453             s = winSetStrOption(kbd->inp_option_lst, "XkbLayout", NULL);
    454             from = X_CONFIG;
    455         }
    456 #endif
    457         if (s) {
    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             s = g_cmdline.xkbVariant;
    465             from = X_CMDLINE;
    466         }
    467 #ifdef XWIN_XF86CONFIG
    468         else {
    469             s = winSetStrOption(kbd->inp_option_lst, "XkbVariant", NULL);
    470             from = X_CONFIG;
    471         }
    472 #endif
    473         if (s) {
    474             g_winInfo.xkb.variant = NULL_IF_EMPTY(s);
    475             winMsg(from, "XKB: variant: \"%s\"\n", s);
    476         }
    477 
    478         s = NULL;
    479         if (g_cmdline.xkbOptions) {
    480             s = g_cmdline.xkbOptions;
    481             from = X_CMDLINE;
    482         }
    483 #ifdef XWIN_XF86CONFIG
    484         else {
    485             s = winSetStrOption(kbd->inp_option_lst, "XkbOptions", NULL);
    486             from = X_CONFIG;
    487         }
    488 #endif
    489         if (s) {
    490             g_winInfo.xkb.options = NULL_IF_EMPTY(s);
    491             winMsg(from, "XKB: options: \"%s\"\n", s);
    492         }
    493 
    494 #ifdef XWIN_XF86CONFIG
    495     }
    496 #endif
    497 
    498     return TRUE;
    499 }
    500 
    501 #ifdef XWIN_XF86CONFIG
    502 Bool
    503 winConfigMouse(DeviceIntPtr pDevice)
    504 {
    505     MessageType mousefrom = X_CONFIG;
    506 
    507     XF86ConfInputPtr mouse = NULL;
    508     XF86ConfInputPtr input_list = NULL;
    509 
    510     if (g_cmdline.mouse)
    511         mousefrom = X_CMDLINE;
    512 
    513     if (g_xf86configptr != NULL)
    514         input_list = g_xf86configptr->conf_input_lst;
    515 
    516     while (input_list != NULL) {
    517         if (winNameCompare(input_list->inp_driver, "mouse") == 0) {
    518             /* Check if device name matches requested name */
    519             if (g_cmdline.mouse && winNameCompare(input_list->inp_identifier,
    520                                                   g_cmdline.mouse))
    521                 continue;
    522             mouse = input_list;
    523         }
    524         input_list = input_list->list.next;
    525     }
    526 
    527     if (mouse != NULL) {
    528         if (mouse->inp_identifier)
    529             winMsg(mousefrom, "Using pointer \"%s\" as primary pointer\n",
    530                    mouse->inp_identifier);
    531 
    532         g_winInfo.pointer.emulate3Buttons =
    533             winSetBoolOption(mouse->inp_option_lst, "Emulate3Buttons", FALSE);
    534         if (g_cmdline.emulate3buttons)
    535             g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons;
    536 
    537         g_winInfo.pointer.emulate3Timeout =
    538             winSetIntOption(mouse->inp_option_lst, "Emulate3Timeout", 50);
    539         if (g_cmdline.emulate3timeout)
    540             g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout;
    541     }
    542     else {
    543         winMsg(X_ERROR, "No primary pointer configured\n");
    544         winMsg(X_DEFAULT, "Using compiletime defaults for pointer\n");
    545     }
    546 
    547     return TRUE;
    548 }
    549 
    550 Bool
    551 winConfigFiles()
    552 {
    553     MessageType from;
    554     XF86ConfFilesPtr filesptr = NULL;
    555 
    556     /* set some shortcuts */
    557     if (g_xf86configptr != NULL) {
    558         filesptr = g_xf86configptr->conf_files;
    559     }
    560 
    561     /* Fontpath */
    562     from = X_DEFAULT;
    563 
    564     if (g_cmdline.fontPath) {
    565         from = X_CMDLINE;
    566         defaultFontPath = g_cmdline.fontPath;
    567     }
    568     else if (filesptr != NULL && filesptr->file_fontpath) {
    569         from = X_CONFIG;
    570         defaultFontPath = strdup(filesptr->file_fontpath);
    571     }
    572     winMsg(from, "FontPath set to \"%s\"\n", defaultFontPath);
    573 
    574     return TRUE;
    575 }
    576 #else
    577 Bool
    578 winConfigFiles(void)
    579 {
    580     /* Fontpath */
    581     if (g_cmdline.fontPath) {
    582         defaultFontPath = g_cmdline.fontPath;
    583         winMsg(X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath);
    584     }
    585 
    586     return TRUE;
    587 }
    588 #endif
    589 
    590 Bool
    591 winConfigOptions(void)
    592 {
    593     return TRUE;
    594 }
    595 
    596 Bool
    597 winConfigScreens(void)
    598 {
    599     return TRUE;
    600 }
    601 
    602 #ifdef XWIN_XF86CONFIG
    603 char *
    604 winSetStrOption(void *optlist, const char *name, char *deflt)
    605 {
    606     OptionInfoRec o;
    607 
    608     o.name = name;
    609     o.type = OPTV_STRING;
    610     if (ParseOptionValue(-1, optlist, &o))
    611         deflt = o.value.str;
    612     if (deflt)
    613         return strdup(deflt);
    614     else
    615         return NULL;
    616 }
    617 
    618 int
    619 winSetBoolOption(void *optlist, const char *name, int deflt)
    620 {
    621     OptionInfoRec o;
    622 
    623     o.name = name;
    624     o.type = OPTV_BOOLEAN;
    625     if (ParseOptionValue(-1, optlist, &o))
    626         deflt = o.value.boolean;
    627     return deflt;
    628 }
    629 
    630 int
    631 winSetIntOption(void *optlist, const char *name, int deflt)
    632 {
    633     OptionInfoRec o;
    634 
    635     o.name = name;
    636     o.type = OPTV_INTEGER;
    637     if (ParseOptionValue(-1, optlist, &o))
    638         deflt = o.value.num;
    639     return deflt;
    640 }
    641 
    642 double
    643 winSetRealOption(void *optlist, const char *name, double deflt)
    644 {
    645     OptionInfoRec o;
    646 
    647     o.name = name;
    648     o.type = OPTV_REAL;
    649     if (ParseOptionValue(-1, optlist, &o))
    650         deflt = o.value.realnum;
    651     return deflt;
    652 }
    653 
    654 double
    655 winSetPercentOption(void *optlist, const char *name, double deflt)
    656 {
    657     OptionInfoRec o;
    658 
    659     o.name = name;
    660     o.type = OPTV_PERCENT;
    661     if (ParseOptionValue(-1, optlist, &o))
    662         deflt = o.value.realnum;
    663     return deflt;
    664 }
    665 #endif
    666 
    667 /*
    668  * Compare two strings for equality. This is caseinsensitive  and
    669  * The characters '_', ' ' (space) and '\t' (tab) are treated as
    670  * not existing.
    671  */
    672 
    673 int
    674 winNameCompare(const char *s1, const char *s2)
    675 {
    676     char c1, c2;
    677 
    678     if (!s1 || *s1 == 0) {
    679         if (!s2 || *s2 == 0)
    680             return 0;
    681         else
    682             return 1;
    683     }
    684 
    685     while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
    686         s1++;
    687     while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
    688         s2++;
    689 
    690     c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
    691     c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
    692 
    693     while (c1 == c2) {
    694         if (c1 == 0)
    695             return 0;
    696         s1++;
    697         s2++;
    698 
    699         while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
    700             s1++;
    701         while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
    702             s2++;
    703 
    704         c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
    705         c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
    706     }
    707     return c1 - c2;
    708 }
    709 
    710 #ifdef XWIN_XF86CONFIG
    711 /*
    712  * Find the named option in the list.
    713  * @return the pointer to the option record, or NULL if not found.
    714  */
    715 
    716 XF86OptionPtr
    717 winFindOption(XF86OptionPtr list, const char *name)
    718 {
    719     while (list) {
    720         if (winNameCompare(list->opt_name, name) == 0)
    721             return list;
    722         list = list->list.next;
    723     }
    724     return NULL;
    725 }
    726 
    727 /*
    728  * Find the Value of an named option.
    729  * @return The option value or NULL if not found.
    730  */
    731 
    732 char *
    733 winFindOptionValue(XF86OptionPtr list, const char *name)
    734 {
    735     list = winFindOption(list, name);
    736     if (list) {
    737         if (list->opt_val)
    738             return list->opt_val;
    739         else
    740             return "";
    741     }
    742     return NULL;
    743 }
    744 
    745 /*
    746  * Parse the option.
    747  */
    748 
    749 static Bool
    750 ParseOptionValue(int scrnIndex, void *options, OptionInfoPtr p)
    751 {
    752     char *s, *end;
    753 
    754     if ((s = winFindOptionValue(options, p->name)) != NULL) {
    755         switch (p->type) {
    756         case OPTV_INTEGER:
    757             if (*s == '\0') {
    758                 winDrvMsg(scrnIndex, X_WARNING,
    759                           "Option \"%s\" requires an integer value\n", p->name);
    760                 p->found = FALSE;
    761             }
    762             else {
    763                 p->value.num = strtoul(s, &end, 0);
    764                 if (*end == '\0') {
    765                     p->found = TRUE;
    766                 }
    767                 else {
    768                     winDrvMsg(scrnIndex, X_WARNING,
    769                               "Option \"%s\" requires an integer value\n",
    770                               p->name);
    771                     p->found = FALSE;
    772                 }
    773             }
    774             break;
    775         case OPTV_STRING:
    776             if (*s == '\0') {
    777                 winDrvMsg(scrnIndex, X_WARNING,
    778                           "Option \"%s\" requires a string value\n", p->name);
    779                 p->found = FALSE;
    780             }
    781             else {
    782                 p->value.str = s;
    783                 p->found = TRUE;
    784             }
    785             break;
    786         case OPTV_ANYSTR:
    787             p->value.str = s;
    788             p->found = TRUE;
    789             break;
    790         case OPTV_REAL:
    791             if (*s == '\0') {
    792                 winDrvMsg(scrnIndex, X_WARNING,
    793                           "Option \"%s\" requires a floating point value\n",
    794                           p->name);
    795                 p->found = FALSE;
    796             }
    797             else {
    798                 p->value.realnum = strtod(s, &end);
    799                 if (*end == '\0') {
    800                     p->found = TRUE;
    801                 }
    802                 else {
    803                     winDrvMsg(scrnIndex, X_WARNING,
    804                               "Option \"%s\" requires a floating point value\n",
    805                               p->name);
    806                     p->found = FALSE;
    807                 }
    808             }
    809             break;
    810         case OPTV_BOOLEAN:
    811             if (GetBoolValue(p, s)) {
    812                 p->found = TRUE;
    813             }
    814             else {
    815                 winDrvMsg(scrnIndex, X_WARNING,
    816                           "Option \"%s\" requires a boolean value\n", p->name);
    817                 p->found = FALSE;
    818             }
    819             break;
    820         case OPTV_PERCENT:
    821             if (*s == '\0') {
    822                 winDrvMsg(scrnIndex, X_WARNING,
    823                           "Option \"%s\" requires a percent value\n", p->name);
    824                 p->found = FALSE;
    825             }
    826             else {
    827                 double percent = strtod(s, &end);
    828 
    829                 if (end != s && winNameCompare(end, "%")) {
    830                     p->found = TRUE;
    831                     p->value.realnum = percent;
    832                 }
    833                 else {
    834                     winDrvMsg(scrnIndex, X_WARNING,
    835                               "Option \"%s\" requires a frequency value\n",
    836                               p->name);
    837                     p->found = FALSE;
    838                 }
    839             }
    840         case OPTV_FREQ:
    841             if (*s == '\0') {
    842                 winDrvMsg(scrnIndex, X_WARNING,
    843                           "Option \"%s\" requires a frequency value\n",
    844                           p->name);
    845                 p->found = FALSE;
    846             }
    847             else {
    848                 double freq = strtod(s, &end);
    849                 int units = 0;
    850 
    851                 if (end != s) {
    852                     p->found = TRUE;
    853                     if (!winNameCompare(end, "Hz"))
    854                         units = 1;
    855                     else if (!winNameCompare(end, "kHz") ||
    856                              !winNameCompare(end, "k"))
    857                         units = 1000;
    858                     else if (!winNameCompare(end, "MHz") ||
    859                              !winNameCompare(end, "M"))
    860                         units = 1000000;
    861                     else {
    862                         winDrvMsg(scrnIndex, X_WARNING,
    863                                   "Option \"%s\" requires a frequency value\n",
    864                                   p->name);
    865                         p->found = FALSE;
    866                     }
    867                     if (p->found)
    868                         freq *= (double) units;
    869                 }
    870                 else {
    871                     winDrvMsg(scrnIndex, X_WARNING,
    872                               "Option \"%s\" requires a frequency value\n",
    873                               p->name);
    874                     p->found = FALSE;
    875                 }
    876                 if (p->found) {
    877                     p->value.freq.freq = freq;
    878                     p->value.freq.units = units;
    879                 }
    880             }
    881             break;
    882         case OPTV_NONE:
    883             /* Should never get here */
    884             p->found = FALSE;
    885             break;
    886         }
    887         if (p->found) {
    888             winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name);
    889             if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
    890                 winErrorFVerb(2, " \"%s\"", s);
    891             }
    892             winErrorFVerb(2, "\n");
    893         }
    894     }
    895     else if (p->type == OPTV_BOOLEAN) {
    896         /* Look for matches with options with or without a "No" prefix. */
    897         char *n, *newn;
    898         OptionInfoRec opt;
    899 
    900         n = winNormalizeName(p->name);
    901         if (!n) {
    902             p->found = FALSE;
    903             return FALSE;
    904         }
    905         if (strncmp(n, "no", 2) == 0) {
    906             newn = n + 2;
    907         }
    908         else {
    909             free(n);
    910             n = malloc(strlen(p->name) + 2 + 1);
    911             if (!n) {
    912                 p->found = FALSE;
    913                 return FALSE;
    914             }
    915             strcpy(n, "No");
    916             strcat(n, p->name);
    917             newn = n;
    918         }
    919         if ((s = winFindOptionValue(options, newn)) != NULL) {
    920             if (GetBoolValue(&opt, s)) {
    921                 p->value.boolean = !opt.value.boolean;
    922                 p->found = TRUE;
    923             }
    924             else {
    925                 winDrvMsg(scrnIndex, X_WARNING,
    926                           "Option \"%s\" requires a boolean value\n", newn);
    927                 p->found = FALSE;
    928             }
    929         }
    930         else {
    931             p->found = FALSE;
    932         }
    933         if (p->found) {
    934             winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
    935             if (*s != 0) {
    936                 winErrorFVerb(2, " \"%s\"", s);
    937             }
    938             winErrorFVerb(2, "\n");
    939         }
    940         free(n);
    941     }
    942     else {
    943         p->found = FALSE;
    944     }
    945     return p->found;
    946 }
    947 
    948 static Bool
    949 configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
    950              char *default_layout)
    951 {
    952 #if 0
    953 #pragma warn UNIMPLEMENTED
    954 #endif
    955     return TRUE;
    956 }
    957 
    958 static Bool
    959 configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen)
    960 {
    961 #if 0
    962 #pragma warn UNIMPLEMENTED
    963 #endif
    964     return TRUE;
    965 }
    966 
    967 static Bool
    968 GetBoolValue(OptionInfoPtr p, const char *s)
    969 {
    970     if (*s == 0) {
    971         p->value.boolean = TRUE;
    972     }
    973     else {
    974         if (winNameCompare(s, "1") == 0)
    975             p->value.boolean = TRUE;
    976         else if (winNameCompare(s, "on") == 0)
    977             p->value.boolean = TRUE;
    978         else if (winNameCompare(s, "true") == 0)
    979             p->value.boolean = TRUE;
    980         else if (winNameCompare(s, "yes") == 0)
    981             p->value.boolean = TRUE;
    982         else if (winNameCompare(s, "0") == 0)
    983             p->value.boolean = FALSE;
    984         else if (winNameCompare(s, "off") == 0)
    985             p->value.boolean = FALSE;
    986         else if (winNameCompare(s, "false") == 0)
    987             p->value.boolean = FALSE;
    988         else if (winNameCompare(s, "no") == 0)
    989             p->value.boolean = FALSE;
    990     }
    991     return TRUE;
    992 }
    993 #endif
    994 
    995 char *
    996 winNormalizeName(const char *s)
    997 {
    998     char *ret, *q;
    999     const char *p;
   1000 
   1001     if (s == NULL)
   1002         return NULL;
   1003 
   1004     ret = malloc(strlen(s) + 1);
   1005     for (p = s, q = ret; *p != 0; p++) {
   1006         switch (*p) {
   1007         case '_':
   1008         case ' ':
   1009         case '\t':
   1010             continue;
   1011         default:
   1012             if (isupper((int) *p))
   1013                 *q++ = tolower((int) *p);
   1014             else
   1015                 *q++ = *p;
   1016         }
   1017     }
   1018     *q = '\0';
   1019     return ret;
   1020 }