winconfig.c revision ed6184df
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
305b261ecSmrg *
405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
505b261ecSmrg * a copy of this software and associated documentation files (the
605b261ecSmrg *"Software"), to deal in the Software without restriction, including
705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1005b261ecSmrg *the following conditions:
1105b261ecSmrg *
1205b261ecSmrg *The above copyright notice and this permission notice shall be
1305b261ecSmrg *included in all copies or substantial portions of the Software.
1405b261ecSmrg *
1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project
2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2505b261ecSmrg *or other dealings in this Software without prior written authorization
2605b261ecSmrg *from the XFree86 Project.
2705b261ecSmrg *
2805b261ecSmrg * Authors: Alexander Gottwald
2905b261ecSmrg */
3005b261ecSmrg
3105b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3205b261ecSmrg#include <xwin-config.h>
3305b261ecSmrg#endif
3405b261ecSmrg#include "win.h"
3505b261ecSmrg#include "winconfig.h"
3605b261ecSmrg#include "winmsg.h"
3705b261ecSmrg#include "globals.h"
3805b261ecSmrg
396747b715Smrg#include "xkbsrv.h"
4005b261ecSmrg
4105b261ecSmrg#ifdef XWIN_XF86CONFIG
4205b261ecSmrg#ifndef CONFIGPATH
4305b261ecSmrg#define CONFIGPATH  "%A," "%R," \
4405b261ecSmrg                    "/etc/X11/%R," "%P/etc/X11/%R," \
4505b261ecSmrg                    "%E," "%F," \
4605b261ecSmrg                    "/etc/X11/%F," "%P/etc/X11/%F," \
4705b261ecSmrg                    "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
4805b261ecSmrg                    "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
4905b261ecSmrg                    "%P/etc/X11/%X," \
5005b261ecSmrg                    "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
5105b261ecSmrg                    "%P/lib/X11/%X"
5205b261ecSmrg#endif
536747b715Smrg#ifndef CONFIGDIRPATH
546747b715Smrg#define CONFIGDIRPATH  "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
556747b715Smrg                       "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
566747b715Smrg                       "%P/etc/X11/%X," \
576747b715Smrg                       "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
586747b715Smrg                       "%P/lib/X11/%X"
596747b715Smrg#endif
6005b261ecSmrg
6105b261ecSmrgXF86ConfigPtr g_xf86configptr = NULL;
6205b261ecSmrg#endif
6305b261ecSmrg
6405b261ecSmrgWinCmdlineRec g_cmdline = {
6505b261ecSmrg#ifdef XWIN_XF86CONFIG
6635c4bbdfSmrg    NULL,                       /* configFile */
6735c4bbdfSmrg    NULL,                       /* configDir */
6805b261ecSmrg#endif
6935c4bbdfSmrg    NULL,                       /* fontPath */
7005b261ecSmrg#ifdef XWIN_XF86CONFIG
7135c4bbdfSmrg    NULL,                       /* keyboard */
7205b261ecSmrg#endif
7335c4bbdfSmrg    NULL,                       /* xkbRules */
7435c4bbdfSmrg    NULL,                       /* xkbModel */
7535c4bbdfSmrg    NULL,                       /* xkbLayout */
7635c4bbdfSmrg    NULL,                       /* xkbVariant */
7735c4bbdfSmrg    NULL,                       /* xkbOptions */
7835c4bbdfSmrg    NULL,                       /* screenname */
7935c4bbdfSmrg    NULL,                       /* mousename */
8035c4bbdfSmrg    FALSE,                      /* emulate3Buttons */
8135c4bbdfSmrg    0                           /* emulate3Timeout */
8205b261ecSmrg};
8305b261ecSmrg
8405b261ecSmrgwinInfoRec g_winInfo = {
8535c4bbdfSmrg    {                           /* keyboard */
8635c4bbdfSmrg     0,                         /* leds */
8735c4bbdfSmrg     500,                       /* delay */
8835c4bbdfSmrg     30                         /* rate */
8935c4bbdfSmrg     }
9035c4bbdfSmrg    ,
9135c4bbdfSmrg    {                           /* xkb */
9235c4bbdfSmrg     NULL,                      /* rules */
9335c4bbdfSmrg     NULL,                      /* model */
9435c4bbdfSmrg     NULL,                      /* layout */
9535c4bbdfSmrg     NULL,                      /* variant */
9635c4bbdfSmrg     NULL,                      /* options */
9735c4bbdfSmrg     }
9835c4bbdfSmrg    ,
9935c4bbdfSmrg    {
10035c4bbdfSmrg     FALSE,
10135c4bbdfSmrg     50}
10205b261ecSmrg};
10305b261ecSmrg
10405b261ecSmrg#define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
10505b261ecSmrg
10605b261ecSmrg#ifdef XWIN_XF86CONFIG
10705b261ecSmrgserverLayoutRec g_winConfigLayout;
10805b261ecSmrg
10935c4bbdfSmrgstatic Bool ParseOptionValue(int scrnIndex, void *options, OptionInfoPtr p);
11035c4bbdfSmrgstatic Bool configLayout(serverLayoutPtr, XF86ConfLayoutPtr, char *);
11135c4bbdfSmrgstatic Bool configImpliedLayout(serverLayoutPtr, XF86ConfScreenPtr);
11235c4bbdfSmrgstatic Bool GetBoolValue(OptionInfoPtr p, const char *s);
11305b261ecSmrg
11405b261ecSmrgBool
11535c4bbdfSmrgwinReadConfigfile()
11605b261ecSmrg{
11735c4bbdfSmrg    Bool retval = TRUE;
11835c4bbdfSmrg    char *filename, *dirname;
11935c4bbdfSmrg    MessageType filefrom = X_DEFAULT;
12035c4bbdfSmrg    MessageType dirfrom = X_DEFAULT;
12135c4bbdfSmrg    char *xf86ConfigFile = NULL;
12235c4bbdfSmrg    char *xf86ConfigDir = NULL;
12335c4bbdfSmrg
12435c4bbdfSmrg    if (g_cmdline.configFile) {
12535c4bbdfSmrg        filefrom = X_CMDLINE;
12635c4bbdfSmrg        xf86ConfigFile = g_cmdline.configFile;
12705b261ecSmrg    }
12835c4bbdfSmrg    if (g_cmdline.configDir) {
12935c4bbdfSmrg        dirfrom = X_CMDLINE;
13035c4bbdfSmrg        xf86ConfigDir = g_cmdline.configDir;
1316747b715Smrg    }
13205b261ecSmrg
13335c4bbdfSmrg    /* Parse config file into data structure */
13435c4bbdfSmrg    xf86initConfigFiles();
13535c4bbdfSmrg    dirname = xf86openConfigDirFiles(CONFIGDIRPATH, xf86ConfigDir, PROJECTROOT);
13635c4bbdfSmrg    filename = xf86openConfigFile(CONFIGPATH, xf86ConfigFile, PROJECTROOT);
1376747b715Smrg
13835c4bbdfSmrg    /* Hack for backward compatibility */
13935c4bbdfSmrg    if (!filename && from == X_DEFAULT)
14035c4bbdfSmrg        filename = xf86openConfigFile(CONFIGPATH, "XF86Config", PROJECTROOT);
14105b261ecSmrg
14235c4bbdfSmrg    if (filename) {
14335c4bbdfSmrg        winMsg(from, "Using config file: \"%s\"\n", filename);
14405b261ecSmrg    }
14535c4bbdfSmrg    else {
14635c4bbdfSmrg        winMsg(X_ERROR, "Unable to locate/open config file");
14735c4bbdfSmrg        if (xf86ConfigFile)
14835c4bbdfSmrg            ErrorF(": \"%s\"", xf86ConfigFile);
14935c4bbdfSmrg        ErrorF("\n");
1506747b715Smrg    }
15135c4bbdfSmrg    if (dirname) {
15235c4bbdfSmrg        winMsg(from, "Using config directory: \"%s\"\n", dirname);
1536747b715Smrg    }
15435c4bbdfSmrg    else {
15535c4bbdfSmrg        winMsg(X_ERROR, "Unable to locate/open config directory");
15635c4bbdfSmrg        if (xf86ConfigDir)
15735c4bbdfSmrg            ErrorF(": \"%s\"", xf86ConfigDir);
15835c4bbdfSmrg        ErrorF("\n");
1596747b715Smrg    }
16035c4bbdfSmrg    if (!filename && !dirname) {
16135c4bbdfSmrg        return FALSE;
16205b261ecSmrg    }
16335c4bbdfSmrg    free(filename);
16435c4bbdfSmrg    free(dirname);
16535c4bbdfSmrg    if ((g_xf86configptr = xf86readConfigFile()) == NULL) {
16635c4bbdfSmrg        winMsg(X_ERROR, "Problem parsing the config file\n");
16735c4bbdfSmrg        return FALSE;
16805b261ecSmrg    }
16935c4bbdfSmrg    xf86closeConfigFile();
17005b261ecSmrg
17135c4bbdfSmrg    LogPrintMarkers();
17205b261ecSmrg
17335c4bbdfSmrg    /* set options from data structure */
17405b261ecSmrg
17535c4bbdfSmrg    if (g_xf86configptr->conf_layout_lst == NULL ||
17635c4bbdfSmrg        g_cmdline.screenname != NULL) {
17735c4bbdfSmrg        if (g_cmdline.screenname == NULL) {
17835c4bbdfSmrg            winMsg(X_WARNING,
17935c4bbdfSmrg                   "No Layout section. Using the first Screen section.\n");
18035c4bbdfSmrg        }
18135c4bbdfSmrg        if (!configImpliedLayout(&g_winConfigLayout,
18235c4bbdfSmrg                                 g_xf86configptr->conf_screen_lst)) {
18335c4bbdfSmrg            winMsg(X_ERROR, "Unable to determine the screen layout\n");
18435c4bbdfSmrg            return FALSE;
18535c4bbdfSmrg        }
18605b261ecSmrg    }
18735c4bbdfSmrg    else {
18835c4bbdfSmrg        /* Check if layout is given in the config file */
18935c4bbdfSmrg        if (g_xf86configptr->conf_flags != NULL) {
19035c4bbdfSmrg            char *dfltlayout = NULL;
19135c4bbdfSmrg            void *optlist = g_xf86configptr->conf_flags->flg_option_lst;
19235c4bbdfSmrg
19335c4bbdfSmrg            if (optlist && winFindOption(optlist, "defaultserverlayout"))
19435c4bbdfSmrg                dfltlayout =
19535c4bbdfSmrg                    winSetStrOption(optlist, "defaultserverlayout", NULL);
19635c4bbdfSmrg
19735c4bbdfSmrg            if (!configLayout(&g_winConfigLayout,
19835c4bbdfSmrg                              g_xf86configptr->conf_layout_lst, dfltlayout)) {
19935c4bbdfSmrg                winMsg(X_ERROR, "Unable to determine the screen layout\n");
20035c4bbdfSmrg                return FALSE;
20135c4bbdfSmrg            }
20235c4bbdfSmrg        }
20335c4bbdfSmrg        else {
20435c4bbdfSmrg            if (!configLayout(&g_winConfigLayout,
20535c4bbdfSmrg                              g_xf86configptr->conf_layout_lst, NULL)) {
20635c4bbdfSmrg                winMsg(X_ERROR, "Unable to determine the screen layout\n");
20735c4bbdfSmrg                return FALSE;
20835c4bbdfSmrg            }
20935c4bbdfSmrg        }
21005b261ecSmrg    }
21105b261ecSmrg
21235c4bbdfSmrg    /* setup special config files */
21335c4bbdfSmrg    winConfigFiles();
21435c4bbdfSmrg    return retval;
21505b261ecSmrg}
21605b261ecSmrg#endif
21705b261ecSmrg
21805b261ecSmrg/* load layout definitions */
21905b261ecSmrg#include "winlayouts.h"
22005b261ecSmrg
22105b261ecSmrg/* Set the keyboard configuration */
22205b261ecSmrgBool
22335c4bbdfSmrgwinConfigKeyboard(DeviceIntPtr pDevice)
22405b261ecSmrg{
22535c4bbdfSmrg    char layoutName[KL_NAMELENGTH];
22635c4bbdfSmrg    unsigned char layoutFriendlyName[256];
22735c4bbdfSmrg    unsigned int layoutNum = 0;
22835c4bbdfSmrg    unsigned int deviceIdentifier = 0;
22935c4bbdfSmrg    int keyboardType;
23035c4bbdfSmrg
23105b261ecSmrg#ifdef XWIN_XF86CONFIG
23235c4bbdfSmrg    XF86ConfInputPtr kbd = NULL;
23335c4bbdfSmrg    XF86ConfInputPtr input_list = NULL;
23435c4bbdfSmrg    MessageType kbdfrom = X_CONFIG;
23505b261ecSmrg#endif
23635c4bbdfSmrg    MessageType from = X_DEFAULT;
23735c4bbdfSmrg    char *s = NULL;
2389ace9065Smrg
23935c4bbdfSmrg    /* Setup defaults */
24035c4bbdfSmrg    XkbGetRulesDflts(&g_winInfo.xkb);
24135c4bbdfSmrg
24235c4bbdfSmrg    /*
24335c4bbdfSmrg     * Query the windows autorepeat settings and change the xserver defaults.
24435c4bbdfSmrg     */
2459ace9065Smrg    {
24635c4bbdfSmrg        int kbd_delay;
24735c4bbdfSmrg        DWORD kbd_speed;
24835c4bbdfSmrg
24935c4bbdfSmrg        if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) &&
25035c4bbdfSmrg            SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0)) {
25135c4bbdfSmrg            switch (kbd_delay) {
25235c4bbdfSmrg            case 0:
25335c4bbdfSmrg                g_winInfo.keyboard.delay = 250;
25435c4bbdfSmrg                break;
25535c4bbdfSmrg            case 1:
25635c4bbdfSmrg                g_winInfo.keyboard.delay = 500;
25735c4bbdfSmrg                break;
25835c4bbdfSmrg            case 2:
25935c4bbdfSmrg                g_winInfo.keyboard.delay = 750;
26035c4bbdfSmrg                break;
26135c4bbdfSmrg            default:
26235c4bbdfSmrg            case 3:
26335c4bbdfSmrg                g_winInfo.keyboard.delay = 1000;
26435c4bbdfSmrg                break;
26535c4bbdfSmrg            }
26635c4bbdfSmrg            g_winInfo.keyboard.rate = (kbd_speed > 0) ? kbd_speed : 1;
2671b5d61b8Smrg            winMsg(X_PROBED, "Setting autorepeat to delay=%ld, rate=%ld\n",
2681b5d61b8Smrg                   g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
2691b5d61b8Smrg
27035c4bbdfSmrg        }
2719ace9065Smrg    }
2729ace9065Smrg
27335c4bbdfSmrg    keyboardType = GetKeyboardType(0);
27435c4bbdfSmrg    if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) {
27535c4bbdfSmrg        WinKBLayoutPtr pLayout;
27635c4bbdfSmrg        Bool bfound = FALSE;
27735c4bbdfSmrg        int pass;
27835c4bbdfSmrg
27935c4bbdfSmrg        layoutNum = strtoul(layoutName, (char **) NULL, 16);
28035c4bbdfSmrg        if ((layoutNum & 0xffff) == 0x411) {
28135c4bbdfSmrg            if (keyboardType == 7) {
28235c4bbdfSmrg                /* Japanese layouts have problems with key event messages
28335c4bbdfSmrg                   such as the lack of WM_KEYUP for Caps Lock key.
28435c4bbdfSmrg                   Loading US layout fixes this problem. */
28535c4bbdfSmrg                if (LoadKeyboardLayout("00000409", KLF_ACTIVATE) != NULL)
28635c4bbdfSmrg                    winMsg(X_INFO, "Loading US keyboard layout.\n");
28735c4bbdfSmrg                else
28835c4bbdfSmrg                    winMsg(X_ERROR, "LoadKeyboardLayout failed.\n");
28935c4bbdfSmrg            }
29035c4bbdfSmrg        }
2919ace9065Smrg
29235c4bbdfSmrg        /* Discover the friendly name of the current layout */
29335c4bbdfSmrg        {
29435c4bbdfSmrg            HKEY regkey = NULL;
29535c4bbdfSmrg            const char regtempl[] =
29635c4bbdfSmrg                "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
29735c4bbdfSmrg            char *regpath;
29835c4bbdfSmrg            DWORD namesize = sizeof(layoutFriendlyName);
29935c4bbdfSmrg
30035c4bbdfSmrg            regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1);
30135c4bbdfSmrg            strcpy(regpath, regtempl);
30235c4bbdfSmrg            strcat(regpath, layoutName);
30335c4bbdfSmrg
30435c4bbdfSmrg            if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, &regkey))
30535c4bbdfSmrg                RegQueryValueEx(regkey, "Layout Text", 0, NULL,
30635c4bbdfSmrg                                layoutFriendlyName, &namesize);
30735c4bbdfSmrg
30835c4bbdfSmrg            /* Close registry key */
30935c4bbdfSmrg            if (regkey)
31035c4bbdfSmrg                RegCloseKey(regkey);
31135c4bbdfSmrg            free(regpath);
31235c4bbdfSmrg        }
3139ace9065Smrg
3149ace9065Smrg        winMsg(X_PROBED,
31535c4bbdfSmrg               "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
31635c4bbdfSmrg               layoutName, layoutNum, layoutFriendlyName, keyboardType);
31735c4bbdfSmrg
31835c4bbdfSmrg        deviceIdentifier = layoutNum >> 16;
31935c4bbdfSmrg        for (pass = 0; pass < 2; pass++) {
320ed6184dfSmrg            /* If we didn't find an exact match for the input locale identifier,
32135c4bbdfSmrg               try to find an match on the language identifier part only  */
32235c4bbdfSmrg            if (pass == 1)
32335c4bbdfSmrg                layoutNum = (layoutNum & 0xffff);
32435c4bbdfSmrg
32535c4bbdfSmrg            for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
32635c4bbdfSmrg                if (pLayout->winlayout != layoutNum)
32735c4bbdfSmrg                    continue;
32835c4bbdfSmrg                if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
32935c4bbdfSmrg                    continue;
33035c4bbdfSmrg
33135c4bbdfSmrg                bfound = TRUE;
33235c4bbdfSmrg                winMsg(X_PROBED,
33335c4bbdfSmrg                       "Found matching XKB configuration \"%s\"\n",
33435c4bbdfSmrg                       pLayout->layoutname);
33535c4bbdfSmrg
33635c4bbdfSmrg                winMsg(X_PROBED,
33735c4bbdfSmrg                       "Model = \"%s\" Layout = \"%s\""
33835c4bbdfSmrg                       " Variant = \"%s\" Options = \"%s\"\n",
33935c4bbdfSmrg                       pLayout->xkbmodel ? pLayout->xkbmodel : "none",
34035c4bbdfSmrg                       pLayout->xkblayout ? pLayout->xkblayout : "none",
34135c4bbdfSmrg                       pLayout->xkbvariant ? pLayout->xkbvariant : "none",
34235c4bbdfSmrg                       pLayout->xkboptions ? pLayout->xkboptions : "none");
34335c4bbdfSmrg
34435c4bbdfSmrg                g_winInfo.xkb.model = pLayout->xkbmodel;
34535c4bbdfSmrg                g_winInfo.xkb.layout = pLayout->xkblayout;
34635c4bbdfSmrg                g_winInfo.xkb.variant = pLayout->xkbvariant;
34735c4bbdfSmrg                g_winInfo.xkb.options = pLayout->xkboptions;
34835c4bbdfSmrg
34935c4bbdfSmrg                if (deviceIdentifier == 0xa000) {
35035c4bbdfSmrg                    winMsg(X_PROBED, "Windows keyboard layout device identifier indicates Macintosh, setting Model = \"macintosh\"");
35135c4bbdfSmrg                    g_winInfo.xkb.model = "macintosh";
35235c4bbdfSmrg                }
35335c4bbdfSmrg
35435c4bbdfSmrg                break;
35535c4bbdfSmrg            }
3569ace9065Smrg
35735c4bbdfSmrg            if (bfound)
35835c4bbdfSmrg                break;
35935c4bbdfSmrg        }
3609ace9065Smrg
36135c4bbdfSmrg        if (!bfound) {
36235c4bbdfSmrg            winMsg(X_ERROR,
36335c4bbdfSmrg                   "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n",
36435c4bbdfSmrg                   layoutFriendlyName, layoutName);
36535c4bbdfSmrg        }
36635c4bbdfSmrg    }
3679ace9065Smrg
36835c4bbdfSmrg    /* parse the configuration */
36905b261ecSmrg#ifdef XWIN_XF86CONFIG
37035c4bbdfSmrg    if (g_cmdline.keyboard)
37135c4bbdfSmrg        kbdfrom = X_CMDLINE;
37235c4bbdfSmrg
37335c4bbdfSmrg    /*
37435c4bbdfSmrg     * Until the layout code is finished, I search for the keyboard
37535c4bbdfSmrg     * device and configure the server with it.
37635c4bbdfSmrg     */
37735c4bbdfSmrg
37835c4bbdfSmrg    if (g_xf86configptr != NULL)
37935c4bbdfSmrg        input_list = g_xf86configptr->conf_input_lst;
38035c4bbdfSmrg
38135c4bbdfSmrg    while (input_list != NULL) {
38235c4bbdfSmrg        if (winNameCompare(input_list->inp_driver, "keyboard") == 0) {
38335c4bbdfSmrg            /* Check if device name matches requested name */
38435c4bbdfSmrg            if (g_cmdline.keyboard && winNameCompare(input_list->inp_identifier,
38535c4bbdfSmrg                                                     g_cmdline.keyboard))
38635c4bbdfSmrg                continue;
38735c4bbdfSmrg            kbd = input_list;
38835c4bbdfSmrg        }
38935c4bbdfSmrg        input_list = input_list->list.next;
39005b261ecSmrg    }
39105b261ecSmrg
39235c4bbdfSmrg    if (kbd != NULL) {
39335c4bbdfSmrg
39435c4bbdfSmrg        if (kbd->inp_identifier)
39535c4bbdfSmrg            winMsg(kbdfrom, "Using keyboard \"%s\" as primary keyboard\n",
39635c4bbdfSmrg                   kbd->inp_identifier);
39735c4bbdfSmrg
39835c4bbdfSmrg        if ((s = winSetStrOption(kbd->inp_option_lst, "AutoRepeat", NULL))) {
39935c4bbdfSmrg            if ((sscanf(s, "%ld %ld", &g_winInfo.keyboard.delay,
40035c4bbdfSmrg                        &g_winInfo.keyboard.rate) != 2) ||
40135c4bbdfSmrg                (g_winInfo.keyboard.delay < 1) ||
40235c4bbdfSmrg                (g_winInfo.keyboard.rate == 0) ||
40335c4bbdfSmrg                (1000 / g_winInfo.keyboard.rate) < 1) {
40435c4bbdfSmrg                winErrorFVerb(2, "\"%s\" is not a valid AutoRepeat value", s);
40535c4bbdfSmrg                free(s);
40635c4bbdfSmrg                return FALSE;
40705b261ecSmrg            }
40835c4bbdfSmrg            free(s);
40935c4bbdfSmrg            winMsg(X_CONFIG, "AutoRepeat: %ld %ld\n",
41035c4bbdfSmrg                   g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
41105b261ecSmrg        }
41205b261ecSmrg#endif
41335c4bbdfSmrg
4146747b715Smrg        s = NULL;
41535c4bbdfSmrg        if (g_cmdline.xkbRules) {
4166747b715Smrg            s = g_cmdline.xkbRules;
4176747b715Smrg            from = X_CMDLINE;
41835c4bbdfSmrg        }
41905b261ecSmrg#ifdef XWIN_XF86CONFIG
42035c4bbdfSmrg        else {
42135c4bbdfSmrg            s = winSetStrOption(kbd->inp_option_lst, "XkbRules", NULL);
4226747b715Smrg            from = X_CONFIG;
42335c4bbdfSmrg        }
42405b261ecSmrg#endif
42535c4bbdfSmrg        if (s) {
42635c4bbdfSmrg            g_winInfo.xkb.rules = NULL_IF_EMPTY(s);
42735c4bbdfSmrg            winMsg(from, "XKB: rules: \"%s\"\n", s);
42835c4bbdfSmrg        }
42935c4bbdfSmrg
4306747b715Smrg        s = NULL;
43135c4bbdfSmrg        if (g_cmdline.xkbModel) {
4326747b715Smrg            s = g_cmdline.xkbModel;
4336747b715Smrg            from = X_CMDLINE;
43435c4bbdfSmrg        }
43505b261ecSmrg#ifdef XWIN_XF86CONFIG
43635c4bbdfSmrg        else {
43735c4bbdfSmrg            s = winSetStrOption(kbd->inp_option_lst, "XkbModel", NULL);
4386747b715Smrg            from = X_CONFIG;
43935c4bbdfSmrg        }
44005b261ecSmrg#endif
44135c4bbdfSmrg        if (s) {
44235c4bbdfSmrg            g_winInfo.xkb.model = NULL_IF_EMPTY(s);
44335c4bbdfSmrg            winMsg(from, "XKB: model: \"%s\"\n", s);
44435c4bbdfSmrg        }
44505b261ecSmrg
4466747b715Smrg        s = NULL;
44735c4bbdfSmrg        if (g_cmdline.xkbLayout) {
4486747b715Smrg            s = g_cmdline.xkbLayout;
4496747b715Smrg            from = X_CMDLINE;
45035c4bbdfSmrg        }
45105b261ecSmrg#ifdef XWIN_XF86CONFIG
45235c4bbdfSmrg        else {
45335c4bbdfSmrg            s = winSetStrOption(kbd->inp_option_lst, "XkbLayout", NULL);
4546747b715Smrg            from = X_CONFIG;
45535c4bbdfSmrg        }
45605b261ecSmrg#endif
45735c4bbdfSmrg        if (s) {
45835c4bbdfSmrg            g_winInfo.xkb.layout = NULL_IF_EMPTY(s);
45935c4bbdfSmrg            winMsg(from, "XKB: layout: \"%s\"\n", s);
46035c4bbdfSmrg        }
46105b261ecSmrg
4626747b715Smrg        s = NULL;
46335c4bbdfSmrg        if (g_cmdline.xkbVariant) {
4646747b715Smrg            s = g_cmdline.xkbVariant;
4656747b715Smrg            from = X_CMDLINE;
46635c4bbdfSmrg        }
46705b261ecSmrg#ifdef XWIN_XF86CONFIG
46835c4bbdfSmrg        else {
46935c4bbdfSmrg            s = winSetStrOption(kbd->inp_option_lst, "XkbVariant", NULL);
4706747b715Smrg            from = X_CONFIG;
47135c4bbdfSmrg        }
47205b261ecSmrg#endif
47335c4bbdfSmrg        if (s) {
47435c4bbdfSmrg            g_winInfo.xkb.variant = NULL_IF_EMPTY(s);
47535c4bbdfSmrg            winMsg(from, "XKB: variant: \"%s\"\n", s);
47635c4bbdfSmrg        }
47705b261ecSmrg
4786747b715Smrg        s = NULL;
47935c4bbdfSmrg        if (g_cmdline.xkbOptions) {
4806747b715Smrg            s = g_cmdline.xkbOptions;
4816747b715Smrg            from = X_CMDLINE;
48235c4bbdfSmrg        }
48305b261ecSmrg#ifdef XWIN_XF86CONFIG
48435c4bbdfSmrg        else {
48535c4bbdfSmrg            s = winSetStrOption(kbd->inp_option_lst, "XkbOptions", NULL);
4866747b715Smrg            from = X_CONFIG;
48735c4bbdfSmrg        }
48805b261ecSmrg#endif
48935c4bbdfSmrg        if (s) {
49035c4bbdfSmrg            g_winInfo.xkb.options = NULL_IF_EMPTY(s);
49135c4bbdfSmrg            winMsg(from, "XKB: options: \"%s\"\n", s);
49235c4bbdfSmrg        }
49305b261ecSmrg
49405b261ecSmrg#ifdef XWIN_XF86CONFIG
49505b261ecSmrg    }
49605b261ecSmrg#endif
49705b261ecSmrg
49835c4bbdfSmrg    return TRUE;
49905b261ecSmrg}
50005b261ecSmrg
50105b261ecSmrg#ifdef XWIN_XF86CONFIG
50205b261ecSmrgBool
50335c4bbdfSmrgwinConfigMouse(DeviceIntPtr pDevice)
50405b261ecSmrg{
50535c4bbdfSmrg    MessageType mousefrom = X_CONFIG;
50605b261ecSmrg
50735c4bbdfSmrg    XF86ConfInputPtr mouse = NULL;
50835c4bbdfSmrg    XF86ConfInputPtr input_list = NULL;
50905b261ecSmrg
51035c4bbdfSmrg    if (g_cmdline.mouse)
51135c4bbdfSmrg        mousefrom = X_CMDLINE;
51205b261ecSmrg
51335c4bbdfSmrg    if (g_xf86configptr != NULL)
51435c4bbdfSmrg        input_list = g_xf86configptr->conf_input_lst;
51505b261ecSmrg
51635c4bbdfSmrg    while (input_list != NULL) {
51735c4bbdfSmrg        if (winNameCompare(input_list->inp_driver, "mouse") == 0) {
51835c4bbdfSmrg            /* Check if device name matches requested name */
51935c4bbdfSmrg            if (g_cmdline.mouse && winNameCompare(input_list->inp_identifier,
52035c4bbdfSmrg                                                  g_cmdline.mouse))
52135c4bbdfSmrg                continue;
52235c4bbdfSmrg            mouse = input_list;
52335c4bbdfSmrg        }
52435c4bbdfSmrg        input_list = input_list->list.next;
52505b261ecSmrg    }
52605b261ecSmrg
52735c4bbdfSmrg    if (mouse != NULL) {
52835c4bbdfSmrg        if (mouse->inp_identifier)
52935c4bbdfSmrg            winMsg(mousefrom, "Using pointer \"%s\" as primary pointer\n",
53035c4bbdfSmrg                   mouse->inp_identifier);
53135c4bbdfSmrg
53235c4bbdfSmrg        g_winInfo.pointer.emulate3Buttons =
53335c4bbdfSmrg            winSetBoolOption(mouse->inp_option_lst, "Emulate3Buttons", FALSE);
53435c4bbdfSmrg        if (g_cmdline.emulate3buttons)
53535c4bbdfSmrg            g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons;
53635c4bbdfSmrg
53735c4bbdfSmrg        g_winInfo.pointer.emulate3Timeout =
53835c4bbdfSmrg            winSetIntOption(mouse->inp_option_lst, "Emulate3Timeout", 50);
53935c4bbdfSmrg        if (g_cmdline.emulate3timeout)
54035c4bbdfSmrg            g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout;
54105b261ecSmrg    }
54235c4bbdfSmrg    else {
54335c4bbdfSmrg        winMsg(X_ERROR, "No primary pointer configured\n");
54435c4bbdfSmrg        winMsg(X_DEFAULT, "Using compiletime defaults for pointer\n");
54505b261ecSmrg    }
54605b261ecSmrg
54735c4bbdfSmrg    return TRUE;
54805b261ecSmrg}
54905b261ecSmrg
55005b261ecSmrgBool
55135c4bbdfSmrgwinConfigFiles()
55205b261ecSmrg{
55335c4bbdfSmrg    MessageType from;
55435c4bbdfSmrg    XF86ConfFilesPtr filesptr = NULL;
55505b261ecSmrg
55635c4bbdfSmrg    /* set some shortcuts */
55735c4bbdfSmrg    if (g_xf86configptr != NULL) {
55835c4bbdfSmrg        filesptr = g_xf86configptr->conf_files;
55905b261ecSmrg    }
56005b261ecSmrg
56135c4bbdfSmrg    /* Fontpath */
56235c4bbdfSmrg    from = X_DEFAULT;
56305b261ecSmrg
56435c4bbdfSmrg    if (g_cmdline.fontPath) {
56535c4bbdfSmrg        from = X_CMDLINE;
56635c4bbdfSmrg        defaultFontPath = g_cmdline.fontPath;
56705b261ecSmrg    }
56835c4bbdfSmrg    else if (filesptr != NULL && filesptr->file_fontpath) {
56935c4bbdfSmrg        from = X_CONFIG;
57035c4bbdfSmrg        defaultFontPath = strdup(filesptr->file_fontpath);
57105b261ecSmrg    }
57235c4bbdfSmrg    winMsg(from, "FontPath set to \"%s\"\n", defaultFontPath);
57305b261ecSmrg
57435c4bbdfSmrg    return TRUE;
57505b261ecSmrg}
57605b261ecSmrg#else
57705b261ecSmrgBool
57835c4bbdfSmrgwinConfigFiles(void)
57905b261ecSmrg{
58035c4bbdfSmrg    /* Fontpath */
58135c4bbdfSmrg    if (g_cmdline.fontPath) {
58235c4bbdfSmrg        defaultFontPath = g_cmdline.fontPath;
58335c4bbdfSmrg        winMsg(X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath);
58405b261ecSmrg    }
58505b261ecSmrg
58635c4bbdfSmrg    return TRUE;
58705b261ecSmrg}
58805b261ecSmrg#endif
58905b261ecSmrg
59005b261ecSmrgBool
59135c4bbdfSmrgwinConfigOptions(void)
59205b261ecSmrg{
59335c4bbdfSmrg    return TRUE;
59405b261ecSmrg}
59505b261ecSmrg
59605b261ecSmrgBool
59735c4bbdfSmrgwinConfigScreens(void)
59805b261ecSmrg{
59935c4bbdfSmrg    return TRUE;
60005b261ecSmrg}
60105b261ecSmrg
60205b261ecSmrg#ifdef XWIN_XF86CONFIG
60305b261ecSmrgchar *
60435c4bbdfSmrgwinSetStrOption(void *optlist, const char *name, char *deflt)
60505b261ecSmrg{
60635c4bbdfSmrg    OptionInfoRec o;
60735c4bbdfSmrg
60835c4bbdfSmrg    o.name = name;
60935c4bbdfSmrg    o.type = OPTV_STRING;
61035c4bbdfSmrg    if (ParseOptionValue(-1, optlist, &o))
61135c4bbdfSmrg        deflt = o.value.str;
61235c4bbdfSmrg    if (deflt)
61335c4bbdfSmrg        return strdup(deflt);
61435c4bbdfSmrg    else
61535c4bbdfSmrg        return NULL;
61605b261ecSmrg}
61705b261ecSmrg
61805b261ecSmrgint
61935c4bbdfSmrgwinSetBoolOption(void *optlist, const char *name, int deflt)
62005b261ecSmrg{
62135c4bbdfSmrg    OptionInfoRec o;
62205b261ecSmrg
62335c4bbdfSmrg    o.name = name;
62435c4bbdfSmrg    o.type = OPTV_BOOLEAN;
62535c4bbdfSmrg    if (ParseOptionValue(-1, optlist, &o))
626ed6184dfSmrg        deflt = o.value.boolean;
62735c4bbdfSmrg    return deflt;
62805b261ecSmrg}
62905b261ecSmrg
63005b261ecSmrgint
63135c4bbdfSmrgwinSetIntOption(void *optlist, const char *name, int deflt)
63205b261ecSmrg{
63335c4bbdfSmrg    OptionInfoRec o;
63405b261ecSmrg
63535c4bbdfSmrg    o.name = name;
63635c4bbdfSmrg    o.type = OPTV_INTEGER;
63735c4bbdfSmrg    if (ParseOptionValue(-1, optlist, &o))
63835c4bbdfSmrg        deflt = o.value.num;
63935c4bbdfSmrg    return deflt;
64005b261ecSmrg}
64105b261ecSmrg
64205b261ecSmrgdouble
64335c4bbdfSmrgwinSetRealOption(void *optlist, const char *name, double deflt)
64405b261ecSmrg{
64535c4bbdfSmrg    OptionInfoRec o;
64605b261ecSmrg
64735c4bbdfSmrg    o.name = name;
64835c4bbdfSmrg    o.type = OPTV_REAL;
64935c4bbdfSmrg    if (ParseOptionValue(-1, optlist, &o))
65035c4bbdfSmrg        deflt = o.value.realnum;
65135c4bbdfSmrg    return deflt;
65205b261ecSmrg}
6536747b715Smrg
6546747b715Smrgdouble
65535c4bbdfSmrgwinSetPercentOption(void *optlist, const char *name, double deflt)
6566747b715Smrg{
65735c4bbdfSmrg    OptionInfoRec o;
6586747b715Smrg
65935c4bbdfSmrg    o.name = name;
66035c4bbdfSmrg    o.type = OPTV_PERCENT;
66135c4bbdfSmrg    if (ParseOptionValue(-1, optlist, &o))
66235c4bbdfSmrg        deflt = o.value.realnum;
66335c4bbdfSmrg    return deflt;
6646747b715Smrg}
66505b261ecSmrg#endif
66605b261ecSmrg
66705b261ecSmrg/*
66805b261ecSmrg * Compare two strings for equality. This is caseinsensitive  and
66935c4bbdfSmrg * The characters '_', ' ' (space) and '\t' (tab) are treated as
67005b261ecSmrg * not existing.
67105b261ecSmrg */
67205b261ecSmrg
67305b261ecSmrgint
67435c4bbdfSmrgwinNameCompare(const char *s1, const char *s2)
67505b261ecSmrg{
67635c4bbdfSmrg    char c1, c2;
67705b261ecSmrg
67835c4bbdfSmrg    if (!s1 || *s1 == 0) {
67935c4bbdfSmrg        if (!s2 || *s2 == 0)
68035c4bbdfSmrg            return 0;
68135c4bbdfSmrg        else
68235c4bbdfSmrg            return 1;
68305b261ecSmrg    }
68405b261ecSmrg
68535c4bbdfSmrg    while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
68635c4bbdfSmrg        s1++;
68735c4bbdfSmrg    while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
68835c4bbdfSmrg        s2++;
68905b261ecSmrg
69035c4bbdfSmrg    c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
69135c4bbdfSmrg    c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
69205b261ecSmrg
69335c4bbdfSmrg    while (c1 == c2) {
69435c4bbdfSmrg        if (c1 == 0)
69535c4bbdfSmrg            return 0;
69635c4bbdfSmrg        s1++;
69735c4bbdfSmrg        s2++;
69835c4bbdfSmrg
69935c4bbdfSmrg        while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
70035c4bbdfSmrg            s1++;
70135c4bbdfSmrg        while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
70235c4bbdfSmrg            s2++;
70335c4bbdfSmrg
70435c4bbdfSmrg        c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
70535c4bbdfSmrg        c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
70605b261ecSmrg    }
70735c4bbdfSmrg    return c1 - c2;
70805b261ecSmrg}
70905b261ecSmrg
71005b261ecSmrg#ifdef XWIN_XF86CONFIG
71105b261ecSmrg/*
71235c4bbdfSmrg * Find the named option in the list.
71305b261ecSmrg * @return the pointer to the option record, or NULL if not found.
71405b261ecSmrg */
71505b261ecSmrg
71605b261ecSmrgXF86OptionPtr
71735c4bbdfSmrgwinFindOption(XF86OptionPtr list, const char *name)
71805b261ecSmrg{
71935c4bbdfSmrg    while (list) {
72035c4bbdfSmrg        if (winNameCompare(list->opt_name, name) == 0)
72135c4bbdfSmrg            return list;
72235c4bbdfSmrg        list = list->list.next;
72305b261ecSmrg    }
72435c4bbdfSmrg    return NULL;
72505b261ecSmrg}
72605b261ecSmrg
72705b261ecSmrg/*
72805b261ecSmrg * Find the Value of an named option.
72905b261ecSmrg * @return The option value or NULL if not found.
73005b261ecSmrg */
73105b261ecSmrg
73205b261ecSmrgchar *
73335c4bbdfSmrgwinFindOptionValue(XF86OptionPtr list, const char *name)
73405b261ecSmrg{
73535c4bbdfSmrg    list = winFindOption(list, name);
73635c4bbdfSmrg    if (list) {
73735c4bbdfSmrg        if (list->opt_val)
73835c4bbdfSmrg            return list->opt_val;
73935c4bbdfSmrg        else
74035c4bbdfSmrg            return "";
74105b261ecSmrg    }
74235c4bbdfSmrg    return NULL;
74305b261ecSmrg}
74405b261ecSmrg
74505b261ecSmrg/*
74605b261ecSmrg * Parse the option.
74705b261ecSmrg */
74805b261ecSmrg
74905b261ecSmrgstatic Bool
75035c4bbdfSmrgParseOptionValue(int scrnIndex, void *options, OptionInfoPtr p)
75105b261ecSmrg{
75235c4bbdfSmrg    char *s, *end;
75335c4bbdfSmrg
75435c4bbdfSmrg    if ((s = winFindOptionValue(options, p->name)) != NULL) {
75535c4bbdfSmrg        switch (p->type) {
75635c4bbdfSmrg        case OPTV_INTEGER:
75735c4bbdfSmrg            if (*s == '\0') {
75835c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
75935c4bbdfSmrg                          "Option \"%s\" requires an integer value\n", p->name);
76035c4bbdfSmrg                p->found = FALSE;
76135c4bbdfSmrg            }
76235c4bbdfSmrg            else {
76335c4bbdfSmrg                p->value.num = strtoul(s, &end, 0);
76435c4bbdfSmrg                if (*end == '\0') {
76535c4bbdfSmrg                    p->found = TRUE;
76635c4bbdfSmrg                }
76735c4bbdfSmrg                else {
76835c4bbdfSmrg                    winDrvMsg(scrnIndex, X_WARNING,
76935c4bbdfSmrg                              "Option \"%s\" requires an integer value\n",
77035c4bbdfSmrg                              p->name);
77135c4bbdfSmrg                    p->found = FALSE;
77235c4bbdfSmrg                }
77335c4bbdfSmrg            }
77435c4bbdfSmrg            break;
77535c4bbdfSmrg        case OPTV_STRING:
77635c4bbdfSmrg            if (*s == '\0') {
77735c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
77835c4bbdfSmrg                          "Option \"%s\" requires a string value\n", p->name);
77935c4bbdfSmrg                p->found = FALSE;
78035c4bbdfSmrg            }
78135c4bbdfSmrg            else {
78235c4bbdfSmrg                p->value.str = s;
78335c4bbdfSmrg                p->found = TRUE;
78435c4bbdfSmrg            }
78535c4bbdfSmrg            break;
78635c4bbdfSmrg        case OPTV_ANYSTR:
78735c4bbdfSmrg            p->value.str = s;
78835c4bbdfSmrg            p->found = TRUE;
78935c4bbdfSmrg            break;
79035c4bbdfSmrg        case OPTV_REAL:
79135c4bbdfSmrg            if (*s == '\0') {
79235c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
79335c4bbdfSmrg                          "Option \"%s\" requires a floating point value\n",
79435c4bbdfSmrg                          p->name);
79535c4bbdfSmrg                p->found = FALSE;
79635c4bbdfSmrg            }
79735c4bbdfSmrg            else {
79835c4bbdfSmrg                p->value.realnum = strtod(s, &end);
79935c4bbdfSmrg                if (*end == '\0') {
80035c4bbdfSmrg                    p->found = TRUE;
80135c4bbdfSmrg                }
80235c4bbdfSmrg                else {
80335c4bbdfSmrg                    winDrvMsg(scrnIndex, X_WARNING,
80435c4bbdfSmrg                              "Option \"%s\" requires a floating point value\n",
80535c4bbdfSmrg                              p->name);
80635c4bbdfSmrg                    p->found = FALSE;
80735c4bbdfSmrg                }
80835c4bbdfSmrg            }
80935c4bbdfSmrg            break;
81035c4bbdfSmrg        case OPTV_BOOLEAN:
81135c4bbdfSmrg            if (GetBoolValue(p, s)) {
81235c4bbdfSmrg                p->found = TRUE;
81335c4bbdfSmrg            }
81435c4bbdfSmrg            else {
81535c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
81635c4bbdfSmrg                          "Option \"%s\" requires a boolean value\n", p->name);
81735c4bbdfSmrg                p->found = FALSE;
81835c4bbdfSmrg            }
81935c4bbdfSmrg            break;
82035c4bbdfSmrg        case OPTV_PERCENT:
82135c4bbdfSmrg            if (*s == '\0') {
82235c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
82335c4bbdfSmrg                          "Option \"%s\" requires a percent value\n", p->name);
82435c4bbdfSmrg                p->found = FALSE;
82535c4bbdfSmrg            }
82635c4bbdfSmrg            else {
82735c4bbdfSmrg                double percent = strtod(s, &end);
82835c4bbdfSmrg
82935c4bbdfSmrg                if (end != s && winNameCompare(end, "%")) {
83035c4bbdfSmrg                    p->found = TRUE;
83135c4bbdfSmrg                    p->value.realnum = percent;
83235c4bbdfSmrg                }
83335c4bbdfSmrg                else {
83435c4bbdfSmrg                    winDrvMsg(scrnIndex, X_WARNING,
83535c4bbdfSmrg                              "Option \"%s\" requires a frequency value\n",
83635c4bbdfSmrg                              p->name);
83735c4bbdfSmrg                    p->found = FALSE;
83835c4bbdfSmrg                }
83935c4bbdfSmrg            }
84035c4bbdfSmrg        case OPTV_FREQ:
84135c4bbdfSmrg            if (*s == '\0') {
84235c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
84335c4bbdfSmrg                          "Option \"%s\" requires a frequency value\n",
84435c4bbdfSmrg                          p->name);
84535c4bbdfSmrg                p->found = FALSE;
84635c4bbdfSmrg            }
84735c4bbdfSmrg            else {
84835c4bbdfSmrg                double freq = strtod(s, &end);
84935c4bbdfSmrg                int units = 0;
85035c4bbdfSmrg
85135c4bbdfSmrg                if (end != s) {
85235c4bbdfSmrg                    p->found = TRUE;
85335c4bbdfSmrg                    if (!winNameCompare(end, "Hz"))
85435c4bbdfSmrg                        units = 1;
85535c4bbdfSmrg                    else if (!winNameCompare(end, "kHz") ||
85635c4bbdfSmrg                             !winNameCompare(end, "k"))
85735c4bbdfSmrg                        units = 1000;
85835c4bbdfSmrg                    else if (!winNameCompare(end, "MHz") ||
85935c4bbdfSmrg                             !winNameCompare(end, "M"))
86035c4bbdfSmrg                        units = 1000000;
86135c4bbdfSmrg                    else {
86235c4bbdfSmrg                        winDrvMsg(scrnIndex, X_WARNING,
86335c4bbdfSmrg                                  "Option \"%s\" requires a frequency value\n",
86435c4bbdfSmrg                                  p->name);
86535c4bbdfSmrg                        p->found = FALSE;
86635c4bbdfSmrg                    }
86735c4bbdfSmrg                    if (p->found)
86835c4bbdfSmrg                        freq *= (double) units;
86935c4bbdfSmrg                }
87035c4bbdfSmrg                else {
87135c4bbdfSmrg                    winDrvMsg(scrnIndex, X_WARNING,
87235c4bbdfSmrg                              "Option \"%s\" requires a frequency value\n",
87335c4bbdfSmrg                              p->name);
87435c4bbdfSmrg                    p->found = FALSE;
87535c4bbdfSmrg                }
87635c4bbdfSmrg                if (p->found) {
87735c4bbdfSmrg                    p->value.freq.freq = freq;
87835c4bbdfSmrg                    p->value.freq.units = units;
87935c4bbdfSmrg                }
88035c4bbdfSmrg            }
88135c4bbdfSmrg            break;
88235c4bbdfSmrg        case OPTV_NONE:
88335c4bbdfSmrg            /* Should never get here */
88435c4bbdfSmrg            p->found = FALSE;
88535c4bbdfSmrg            break;
88635c4bbdfSmrg        }
88735c4bbdfSmrg        if (p->found) {
88835c4bbdfSmrg            winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name);
88935c4bbdfSmrg            if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
89035c4bbdfSmrg                winErrorFVerb(2, " \"%s\"", s);
89135c4bbdfSmrg            }
89235c4bbdfSmrg            winErrorFVerb(2, "\n");
89335c4bbdfSmrg        }
89405b261ecSmrg    }
89535c4bbdfSmrg    else if (p->type == OPTV_BOOLEAN) {
89635c4bbdfSmrg        /* Look for matches with options with or without a "No" prefix. */
89735c4bbdfSmrg        char *n, *newn;
89835c4bbdfSmrg        OptionInfoRec opt;
89935c4bbdfSmrg
90035c4bbdfSmrg        n = winNormalizeName(p->name);
90135c4bbdfSmrg        if (!n) {
90235c4bbdfSmrg            p->found = FALSE;
90335c4bbdfSmrg            return FALSE;
90435c4bbdfSmrg        }
90535c4bbdfSmrg        if (strncmp(n, "no", 2) == 0) {
90635c4bbdfSmrg            newn = n + 2;
90735c4bbdfSmrg        }
90835c4bbdfSmrg        else {
90935c4bbdfSmrg            free(n);
91035c4bbdfSmrg            n = malloc(strlen(p->name) + 2 + 1);
91135c4bbdfSmrg            if (!n) {
91235c4bbdfSmrg                p->found = FALSE;
91335c4bbdfSmrg                return FALSE;
91435c4bbdfSmrg            }
91535c4bbdfSmrg            strcpy(n, "No");
91635c4bbdfSmrg            strcat(n, p->name);
91735c4bbdfSmrg            newn = n;
91835c4bbdfSmrg        }
91935c4bbdfSmrg        if ((s = winFindOptionValue(options, newn)) != NULL) {
92035c4bbdfSmrg            if (GetBoolValue(&opt, s)) {
921ed6184dfSmrg                p->value.boolean = !opt.value.boolean;
92235c4bbdfSmrg                p->found = TRUE;
92335c4bbdfSmrg            }
92435c4bbdfSmrg            else {
92535c4bbdfSmrg                winDrvMsg(scrnIndex, X_WARNING,
92635c4bbdfSmrg                          "Option \"%s\" requires a boolean value\n", newn);
92735c4bbdfSmrg                p->found = FALSE;
92835c4bbdfSmrg            }
92935c4bbdfSmrg        }
93035c4bbdfSmrg        else {
93135c4bbdfSmrg            p->found = FALSE;
93235c4bbdfSmrg        }
93335c4bbdfSmrg        if (p->found) {
93435c4bbdfSmrg            winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
93535c4bbdfSmrg            if (*s != 0) {
93635c4bbdfSmrg                winErrorFVerb(2, " \"%s\"", s);
93735c4bbdfSmrg            }
93835c4bbdfSmrg            winErrorFVerb(2, "\n");
93935c4bbdfSmrg        }
94035c4bbdfSmrg        free(n);
94105b261ecSmrg    }
94235c4bbdfSmrg    else {
94335c4bbdfSmrg        p->found = FALSE;
94405b261ecSmrg    }
94535c4bbdfSmrg    return p->found;
94605b261ecSmrg}
94705b261ecSmrg
94805b261ecSmrgstatic Bool
94935c4bbdfSmrgconfigLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
95035c4bbdfSmrg             char *default_layout)
95105b261ecSmrg{
95205b261ecSmrg#if 0
95305b261ecSmrg#pragma warn UNIMPLEMENTED
95405b261ecSmrg#endif
95535c4bbdfSmrg    return TRUE;
95605b261ecSmrg}
95705b261ecSmrg
95805b261ecSmrgstatic Bool
95935c4bbdfSmrgconfigImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen)
96005b261ecSmrg{
96105b261ecSmrg#if 0
96205b261ecSmrg#pragma warn UNIMPLEMENTED
96305b261ecSmrg#endif
96435c4bbdfSmrg    return TRUE;
96505b261ecSmrg}
96605b261ecSmrg
96705b261ecSmrgstatic Bool
96835c4bbdfSmrgGetBoolValue(OptionInfoPtr p, const char *s)
96905b261ecSmrg{
97035c4bbdfSmrg    if (*s == 0) {
971ed6184dfSmrg        p->value.boolean = TRUE;
97205b261ecSmrg    }
97335c4bbdfSmrg    else {
97435c4bbdfSmrg        if (winNameCompare(s, "1") == 0)
975ed6184dfSmrg            p->value.boolean = TRUE;
97635c4bbdfSmrg        else if (winNameCompare(s, "on") == 0)
977ed6184dfSmrg            p->value.boolean = TRUE;
97835c4bbdfSmrg        else if (winNameCompare(s, "true") == 0)
979ed6184dfSmrg            p->value.boolean = TRUE;
98035c4bbdfSmrg        else if (winNameCompare(s, "yes") == 0)
981ed6184dfSmrg            p->value.boolean = TRUE;
98235c4bbdfSmrg        else if (winNameCompare(s, "0") == 0)
983ed6184dfSmrg            p->value.boolean = FALSE;
98435c4bbdfSmrg        else if (winNameCompare(s, "off") == 0)
985ed6184dfSmrg            p->value.boolean = FALSE;
98635c4bbdfSmrg        else if (winNameCompare(s, "false") == 0)
987ed6184dfSmrg            p->value.boolean = FALSE;
98835c4bbdfSmrg        else if (winNameCompare(s, "no") == 0)
989ed6184dfSmrg            p->value.boolean = FALSE;
99005b261ecSmrg    }
99135c4bbdfSmrg    return TRUE;
99205b261ecSmrg}
99305b261ecSmrg#endif
99405b261ecSmrg
99505b261ecSmrgchar *
99635c4bbdfSmrgwinNormalizeName(const char *s)
99705b261ecSmrg{
99835c4bbdfSmrg    char *ret, *q;
99935c4bbdfSmrg    const char *p;
100035c4bbdfSmrg
100135c4bbdfSmrg    if (s == NULL)
100235c4bbdfSmrg        return NULL;
100335c4bbdfSmrg
100435c4bbdfSmrg    ret = malloc(strlen(s) + 1);
100535c4bbdfSmrg    for (p = s, q = ret; *p != 0; p++) {
100635c4bbdfSmrg        switch (*p) {
100735c4bbdfSmrg        case '_':
100835c4bbdfSmrg        case ' ':
100935c4bbdfSmrg        case '\t':
101035c4bbdfSmrg            continue;
101135c4bbdfSmrg        default:
101235c4bbdfSmrg            if (isupper((int) *p))
101335c4bbdfSmrg                *q++ = tolower((int) *p);
101435c4bbdfSmrg            else
101535c4bbdfSmrg                *q++ = *p;
101635c4bbdfSmrg        }
101705b261ecSmrg    }
101835c4bbdfSmrg    *q = '\0';
101935c4bbdfSmrg    return ret;
102005b261ecSmrg}
1021