summaryrefslogtreecommitdiff
path: root/hw/xwin/winconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xwin/winconfig.c')
-rw-r--r--hw/xwin/winconfig.c1150
1 files changed, 1150 insertions, 0 deletions
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
new file mode 100644
index 000000000..38966bf96
--- /dev/null
+++ b/hw/xwin/winconfig.c
@@ -0,0 +1,1150 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Alexander Gottwald
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winconfig.h"
+#include "winmsg.h"
+#include "globals.h"
+
+#ifdef XKB
+#ifndef XKB_IN_SERVER
+#define XKB_IN_SERVER
+#endif
+#include <xkbsrv.h>
+#endif
+
+#ifdef XWIN_XF86CONFIG
+#ifndef CONFIGPATH
+#define CONFIGPATH "%A," "%R," \
+ "/etc/X11/%R," "%P/etc/X11/%R," \
+ "%E," "%F," \
+ "/etc/X11/%F," "%P/etc/X11/%F," \
+ "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
+ "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
+ "%P/etc/X11/%X," \
+ "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
+ "%P/lib/X11/%X"
+#endif
+
+XF86ConfigPtr g_xf86configptr = NULL;
+#endif
+
+WinCmdlineRec g_cmdline = {
+#ifdef XWIN_XF86CONFIG
+ NULL, /* configFile */
+#endif
+ NULL, /* fontPath */
+#ifdef XWIN_XF86CONFIG
+ NULL, /* keyboard */
+#endif
+#ifdef XKB
+ FALSE, /* noXkbExtension */
+ NULL, /* xkbMap */
+ NULL, /* xkbRules */
+ NULL, /* xkbModel */
+ NULL, /* xkbLayout */
+ NULL, /* xkbVariant */
+ NULL, /* xkbOptions */
+#endif
+ NULL, /* screenname */
+ NULL, /* mousename */
+ FALSE, /* emulate3Buttons */
+ 0 /* emulate3Timeout */
+};
+
+winInfoRec g_winInfo = {
+ { /* keyboard */
+ 0, /* leds */
+ 500, /* delay */
+ 30 /* rate */
+#ifdef XKB
+ }
+ ,
+ { /* xkb */
+ FALSE, /* disable */
+ NULL, /* rules */
+ NULL, /* model */
+ NULL, /* layout */
+ NULL, /* variant */
+ NULL, /* options */
+ NULL, /* initialMap */
+ NULL, /* keymap */
+ NULL, /* types */
+ NULL, /* compat */
+ NULL, /* keycodes */
+ NULL, /* symbols */
+ NULL /* geometry */
+#endif
+ }
+ ,
+ {
+ FALSE,
+ 50}
+};
+
+#define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
+
+#ifdef XWIN_XF86CONFIG
+serverLayoutRec g_winConfigLayout;
+
+static Bool ParseOptionValue (int scrnIndex, pointer options,
+ OptionInfoPtr p);
+static Bool configLayout (serverLayoutPtr, XF86ConfLayoutPtr, char *);
+static Bool configImpliedLayout (serverLayoutPtr, XF86ConfScreenPtr);
+static Bool GetBoolValue (OptionInfoPtr p, const char *s);
+
+
+Bool
+winReadConfigfile ()
+{
+ Bool retval = TRUE;
+ const char *filename;
+ MessageType from = X_DEFAULT;
+ char *xf86ConfigFile = NULL;
+
+ if (g_cmdline.configFile)
+ {
+ from = X_CMDLINE;
+ xf86ConfigFile = g_cmdline.configFile;
+ }
+
+ /* Parse config file into data structure */
+
+ filename = xf86openConfigFile (CONFIGPATH, xf86ConfigFile, PROJECTROOT);
+
+ /* Hack for backward compatibility */
+ if (!filename && from == X_DEFAULT)
+ filename = xf86openConfigFile (CONFIGPATH, "XF86Config", PROJECTROOT);
+
+ if (filename)
+ {
+ winMsg (from, "Using config file: \"%s\"\n", filename);
+ }
+ else
+ {
+ winMsg (X_ERROR, "Unable to locate/open config file");
+ if (xf86ConfigFile)
+ ErrorF (": \"%s\"", xf86ConfigFile);
+ ErrorF ("\n");
+ return FALSE;
+ }
+ if ((g_xf86configptr = xf86readConfigFile ()) == NULL)
+ {
+ winMsg (X_ERROR, "Problem parsing the config file\n");
+ return FALSE;
+ }
+ xf86closeConfigFile ();
+
+ LogPrintMarkers();
+
+ /* set options from data structure */
+
+ if (g_xf86configptr->conf_layout_lst == NULL || g_cmdline.screenname != NULL)
+ {
+ if (g_cmdline.screenname == NULL)
+ {
+ winMsg (X_WARNING,
+ "No Layout section. Using the first Screen section.\n");
+ }
+ if (!configImpliedLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_screen_lst))
+ {
+ winMsg (X_ERROR, "Unable to determine the screen layout\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Check if layout is given in the config file */
+ if (g_xf86configptr->conf_flags != NULL)
+ {
+ char *dfltlayout = NULL;
+ pointer optlist = g_xf86configptr->conf_flags->flg_option_lst;
+
+ if (optlist && winFindOption (optlist, "defaultserverlayout"))
+ dfltlayout =
+ winSetStrOption (optlist, "defaultserverlayout", NULL);
+
+ if (!configLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_layout_lst,
+ dfltlayout))
+ {
+ winMsg (X_ERROR, "Unable to determine the screen layout\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!configLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_layout_lst,
+ NULL))
+ {
+ winMsg (X_ERROR, "Unable to determine the screen layout\n");
+ return FALSE;
+ }
+ }
+ }
+
+ /* setup special config files */
+ winConfigFiles ();
+ return retval;
+}
+#endif
+
+/* load layout definitions */
+#include "winlayouts.h"
+
+/* Set the keyboard configuration */
+Bool
+winConfigKeyboard (DeviceIntPtr pDevice)
+{
+#ifdef XKB
+ char layoutName[KL_NAMELENGTH];
+ static unsigned int layoutNum = 0;
+ int keyboardType;
+#endif
+#ifdef XWIN_XF86CONFIG
+ XF86ConfInputPtr kbd = NULL;
+ XF86ConfInputPtr input_list = NULL;
+ MessageType kbdfrom = X_CONFIG;
+#endif
+ MessageType from = X_DEFAULT;
+ char *s = NULL;
+
+ /* Setup defaults */
+#ifdef XKB
+ g_winInfo.xkb.disable = FALSE;
+# ifdef PC98 /* japanese */ /* not implemented */
+ g_winInfo.xkb.rules = "xfree98";
+ g_winInfo.xkb.model = "pc98";
+ g_winInfo.xkb.layout = "nex/jp";
+ g_winInfo.xkb.variant = NULL;
+ g_winInfo.xkb.options = NULL;
+# else
+ g_winInfo.xkb.rules = "xorg";
+ g_winInfo.xkb.model = "pc101";
+ g_winInfo.xkb.layout = "us";
+ g_winInfo.xkb.variant = NULL;
+ g_winInfo.xkb.options = NULL;
+# endif /* PC98 */
+
+ /*
+ * Query the windows autorepeat settings and change the xserver defaults.
+ * If XKB is disabled then windows handles the autorepeat and the special
+ * treatment is not needed
+ */
+ {
+ int kbd_delay;
+ DWORD kbd_speed;
+ if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) &&
+ SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0))
+ {
+ switch (kbd_delay)
+ {
+ case 0: g_winInfo.keyboard.delay = 250; break;
+ case 1: g_winInfo.keyboard.delay = 500; break;
+ case 2: g_winInfo.keyboard.delay = 750; break;
+ default:
+ case 3: g_winInfo.keyboard.delay = 1000; break;
+ }
+ g_winInfo.keyboard.rate = (kbd_speed>0)?kbd_speed:1;
+ winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%d, rate=%d\n",
+ g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
+ }
+ }
+
+
+ keyboardType = GetKeyboardType (0);
+ if (keyboardType > 0 && GetKeyboardLayoutName (layoutName))
+ {
+ WinKBLayoutPtr pLayout;
+ Bool bfound = FALSE;
+
+ if (! layoutNum)
+ layoutNum = strtoul (layoutName, (char **)NULL, 16);
+ if ((layoutNum & 0xffff) == 0x411) {
+ /* The japanese layouts know a lot of different IMEs which all have
+ different layout numbers set. Map them to a single entry.
+ Same might apply for chinese, korean and other symbol languages
+ too */
+ layoutNum = (layoutNum & 0xffff);
+ if (keyboardType == 7)
+ {
+ /* Japanese layouts have problems with key event messages
+ such as the lack of WM_KEYUP for Caps Lock key.
+ Loading US layout fixes this problem. */
+ if (LoadKeyboardLayout("00000409", KLF_ACTIVATE) != NULL)
+ winMsg (X_INFO, "Loading US keyboard layout.\n");
+ else
+ winMsg (X_ERROR, "LoadKeyboardLaout failed.\n");
+ }
+ }
+ winMsg (X_PROBED, "winConfigKeyboard - Layout: \"%s\" (%08x) \n",
+ layoutName, layoutNum);
+
+ for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++)
+ {
+ if (pLayout->winlayout != layoutNum)
+ continue;
+ if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
+ continue;
+
+ bfound = TRUE;
+ winMsg (X_PROBED,
+ "Using preset keyboard for \"%s\" (%x), type \"%d\"\n",
+ pLayout->layoutname, pLayout->winlayout, keyboardType);
+
+ g_winInfo.xkb.model = pLayout->xkbmodel;
+ g_winInfo.xkb.layout = pLayout->xkblayout;
+ g_winInfo.xkb.variant = pLayout->xkbvariant;
+ g_winInfo.xkb.options = pLayout->xkboptions;
+ break;
+ }
+
+ if (!bfound)
+ {
+ HKEY regkey = NULL;
+ const char regtempl[] =
+ "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
+ char *regpath;
+ char lname[256];
+ DWORD namesize = sizeof(lname);
+
+ regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1);
+ strcpy(regpath, regtempl);
+ strcat(regpath, layoutName);
+
+ if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, &regkey) &&
+ !RegQueryValueEx(regkey, "Layout Text", 0, NULL, lname, &namesize))
+ {
+ winMsg (X_ERROR,
+ "Keyboardlayout \"%s\" (%s) is unknown\n", lname, layoutName);
+ }
+
+ /* Close registry key */
+ if (regkey)
+ RegCloseKey (regkey);
+ free(regpath);
+ }
+ }
+
+ g_winInfo.xkb.initialMap = NULL;
+ g_winInfo.xkb.keymap = NULL;
+ g_winInfo.xkb.types = NULL;
+ g_winInfo.xkb.compat = NULL;
+ g_winInfo.xkb.keycodes = NULL;
+ g_winInfo.xkb.symbols = NULL;
+ g_winInfo.xkb.geometry = NULL;
+#endif /* XKB */
+
+ /* parse the configuration */
+#ifdef XWIN_XF86CONFIG
+ if (g_cmdline.keyboard)
+ kbdfrom = X_CMDLINE;
+
+ /*
+ * Until the layout code is finished, I search for the keyboard
+ * device and configure the server with it.
+ */
+
+ if (g_xf86configptr != NULL)
+ input_list = g_xf86configptr->conf_input_lst;
+
+ while (input_list != NULL)
+ {
+ if (winNameCompare (input_list->inp_driver, "keyboard") == 0)
+ {
+ /* Check if device name matches requested name */
+ if (g_cmdline.keyboard && winNameCompare (input_list->inp_identifier,
+ g_cmdline.keyboard))
+ continue;
+ kbd = input_list;
+ }
+ input_list = input_list->list.next;
+ }
+
+ if (kbd != NULL)
+ {
+
+ if (kbd->inp_identifier)
+ winMsg (kbdfrom, "Using keyboard \"%s\" as primary keyboard\n",
+ kbd->inp_identifier);
+
+ if ((s = winSetStrOption(kbd->inp_option_lst, "AutoRepeat", NULL)))
+ {
+ if ((sscanf(s, "%ld %ld", &g_winInfo.keyboard.delay,
+ &g_winInfo.keyboard.rate) != 2) ||
+ (g_winInfo.keyboard.delay < 1) ||
+ (g_winInfo.keyboard.rate == 0) ||
+ (1000 / g_winInfo.keyboard.rate) < 1)
+ {
+ winErrorFVerb (2, "\"%s\" is not a valid AutoRepeat value", s);
+ xfree(s);
+ return FALSE;
+ }
+ xfree(s);
+ winMsg (X_CONFIG, "AutoRepeat: %ld %ld\n",
+ g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
+ }
+#endif
+
+#ifdef XKB
+ from = X_DEFAULT;
+ if (g_cmdline.noXkbExtension)
+ {
+ from = X_CMDLINE;
+ g_winInfo.xkb.disable = TRUE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else if (kbd->inp_option_lst)
+ {
+ int b = winSetBoolOption (kbd->inp_option_lst, "XkbDisable", FALSE);
+ if (b)
+ {
+ from = X_CONFIG;
+ g_winInfo.xkb.disable = TRUE;
+ }
+ }
+#endif
+ if (g_winInfo.xkb.disable)
+ {
+ winMsg (from, "XkbExtension disabled\n");
+ }
+ else
+ {
+ s = NULL;
+ if (g_cmdline.xkbRules)
+ {
+ s = g_cmdline.xkbRules;
+ from = X_CMDLINE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else
+ {
+ s = winSetStrOption (kbd->inp_option_lst, "XkbRules", NULL);
+ from = X_CONFIG;
+ }
+#endif
+ if (s)
+ {
+ g_winInfo.xkb.rules = NULL_IF_EMPTY (s);
+ winMsg (from, "XKB: rules: \"%s\"\n", s);
+ }
+
+ s = NULL;
+ if (g_cmdline.xkbModel)
+ {
+ s = g_cmdline.xkbModel;
+ from = X_CMDLINE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else
+ {
+ s = winSetStrOption (kbd->inp_option_lst, "XkbModel", NULL);
+ from = X_CONFIG;
+ }
+#endif
+ if (s)
+ {
+ g_winInfo.xkb.model = NULL_IF_EMPTY (s);
+ winMsg (from, "XKB: model: \"%s\"\n", s);
+ }
+
+ s = NULL;
+ if (g_cmdline.xkbLayout)
+ {
+ s = g_cmdline.xkbLayout;
+ from = X_CMDLINE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else
+ {
+ s = winSetStrOption (kbd->inp_option_lst, "XkbLayout", NULL);
+ from = X_CONFIG;
+ }
+#endif
+ if (s)
+ {
+ g_winInfo.xkb.layout = NULL_IF_EMPTY (s);
+ winMsg (from, "XKB: layout: \"%s\"\n", s);
+ }
+
+ s = NULL;
+ if (g_cmdline.xkbVariant)
+ {
+ s = g_cmdline.xkbVariant;
+ from = X_CMDLINE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else
+ {
+ s = winSetStrOption (kbd->inp_option_lst, "XkbVariant", NULL);
+ from = X_CONFIG;
+ }
+#endif
+ if (s)
+ {
+ g_winInfo.xkb.variant = NULL_IF_EMPTY (s);
+ winMsg (from, "XKB: variant: \"%s\"\n", s);
+ }
+
+ s = NULL;
+ if (g_cmdline.xkbOptions)
+ {
+ s = g_cmdline.xkbOptions;
+ from = X_CMDLINE;
+ }
+#ifdef XWIN_XF86CONFIG
+ else
+ {
+ s = winSetStrOption (kbd->inp_option_lst, "XkbOptions", NULL);
+ from = X_CONFIG;
+ }
+#endif
+ if (s)
+ {
+ g_winInfo.xkb.options = NULL_IF_EMPTY (s);
+ winMsg (from, "XKB: options: \"%s\"\n", s);
+ }
+
+#ifdef XWIN_XF86CONFIG
+ from = X_CMDLINE;
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbKeymap", NULL)))
+ {
+ g_winInfo.xkb.keymap = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: keymap: \"%s\" "
+ " (overrides other XKB settings)\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbCompat", NULL)))
+ {
+ g_winInfo.xkb.compat = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: compat: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbTypes", NULL)))
+ {
+ g_winInfo.xkb.types = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: types: \"%s\"\n", s);
+ }
+
+ if ((s =
+ winSetStrOption (kbd->inp_option_lst, "XkbKeycodes", NULL)))
+ {
+ g_winInfo.xkb.keycodes = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: keycodes: \"%s\"\n", s);
+ }
+
+ if ((s =
+ winSetStrOption (kbd->inp_option_lst, "XkbGeometry", NULL)))
+ {
+ g_winInfo.xkb.geometry = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: geometry: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbSymbols", NULL)))
+ {
+ g_winInfo.xkb.symbols = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: symbols: \"%s\"\n", s);
+ }
+#endif
+#endif
+ }
+#ifdef XWIN_XF86CONFIG
+ }
+#endif
+
+ return TRUE;
+}
+
+
+#ifdef XWIN_XF86CONFIG
+Bool
+winConfigMouse (DeviceIntPtr pDevice)
+{
+ MessageType mousefrom = X_CONFIG;
+
+ XF86ConfInputPtr mouse = NULL;
+ XF86ConfInputPtr input_list = NULL;
+
+ if (g_cmdline.mouse)
+ mousefrom = X_CMDLINE;
+
+ if (g_xf86configptr != NULL)
+ input_list = g_xf86configptr->conf_input_lst;
+
+ while (input_list != NULL)
+ {
+ if (winNameCompare (input_list->inp_driver, "mouse") == 0)
+ {
+ /* Check if device name matches requested name */
+ if (g_cmdline.mouse && winNameCompare (input_list->inp_identifier,
+ g_cmdline.mouse))
+ continue;
+ mouse = input_list;
+ }
+ input_list = input_list->list.next;
+ }
+
+ if (mouse != NULL)
+ {
+ if (mouse->inp_identifier)
+ winMsg (mousefrom, "Using pointer \"%s\" as primary pointer\n",
+ mouse->inp_identifier);
+
+ g_winInfo.pointer.emulate3Buttons =
+ winSetBoolOption (mouse->inp_option_lst, "Emulate3Buttons", FALSE);
+ if (g_cmdline.emulate3buttons)
+ g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons;
+
+ g_winInfo.pointer.emulate3Timeout =
+ winSetIntOption (mouse->inp_option_lst, "Emulate3Timeout", 50);
+ if (g_cmdline.emulate3timeout)
+ g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout;
+ }
+ else
+ {
+ winMsg (X_ERROR, "No primary pointer configured\n");
+ winMsg (X_DEFAULT, "Using compiletime defaults for pointer\n");
+ }
+
+ return TRUE;
+}
+
+
+Bool
+winConfigFiles ()
+{
+ MessageType from;
+ XF86ConfFilesPtr filesptr = NULL;
+
+ /* set some shortcuts */
+ if (g_xf86configptr != NULL)
+ {
+ filesptr = g_xf86configptr->conf_files;
+ }
+
+
+ /* Fontpath */
+ from = X_DEFAULT;
+
+ if (g_cmdline.fontPath)
+ {
+ from = X_CMDLINE;
+ defaultFontPath = g_cmdline.fontPath;
+ }
+ else if (filesptr != NULL && filesptr->file_fontpath)
+ {
+ from = X_CONFIG;
+ defaultFontPath = xstrdup (filesptr->file_fontpath);
+ }
+ winMsg (from, "FontPath set to \"%s\"\n", defaultFontPath);
+
+ return TRUE;
+}
+#else
+Bool
+winConfigFiles ()
+{
+ MessageType from;
+
+ /* Fontpath */
+ if (g_cmdline.fontPath)
+ {
+ defaultFontPath = g_cmdline.fontPath;
+ winMsg (X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath);
+ }
+
+ return TRUE;
+}
+#endif
+
+
+Bool
+winConfigOptions ()
+{
+ return TRUE;
+}
+
+
+Bool
+winConfigScreens ()
+{
+ return TRUE;
+}
+
+
+#ifdef XWIN_XF86CONFIG
+char *
+winSetStrOption (pointer optlist, const char *name, char *deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_STRING;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.str;
+ if (deflt)
+ return xstrdup (deflt);
+ else
+ return NULL;
+}
+
+
+int
+winSetBoolOption (pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_BOOLEAN;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.bool;
+ return deflt;
+}
+
+
+int
+winSetIntOption (pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_INTEGER;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.num;
+ return deflt;
+}
+
+
+double
+winSetRealOption (pointer optlist, const char *name, double deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_REAL;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.realnum;
+ return deflt;
+}
+#endif
+
+
+/*
+ * Compare two strings for equality. This is caseinsensitive and
+ * The characters '_', ' ' (space) and '\t' (tab) are treated as
+ * not existing.
+ */
+
+int
+winNameCompare (const char *s1, const char *s2)
+{
+ char c1, c2;
+
+ if (!s1 || *s1 == 0)
+ {
+ if (!s2 || *s2 == 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+
+ c1 = (isupper (*s1) ? tolower (*s1) : *s1);
+ c2 = (isupper (*s2) ? tolower (*s2) : *s2);
+
+ while (c1 == c2)
+ {
+ if (c1 == 0)
+ return 0;
+ s1++;
+ s2++;
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+
+ c1 = (isupper (*s1) ? tolower (*s1) : *s1);
+ c2 = (isupper (*s2) ? tolower (*s2) : *s2);
+ }
+ return (c1 - c2);
+}
+
+
+#ifdef XWIN_XF86CONFIG
+/*
+ * Find the named option in the list.
+ * @return the pointer to the option record, or NULL if not found.
+ */
+
+XF86OptionPtr
+winFindOption (XF86OptionPtr list, const char *name)
+{
+ while (list)
+ {
+ if (winNameCompare (list->opt_name, name) == 0)
+ return list;
+ list = list->list.next;
+ }
+ return NULL;
+}
+
+
+/*
+ * Find the Value of an named option.
+ * @return The option value or NULL if not found.
+ */
+
+char *
+winFindOptionValue (XF86OptionPtr list, const char *name)
+{
+ list = winFindOption (list, name);
+ if (list)
+ {
+ if (list->opt_val)
+ return (list->opt_val);
+ else
+ return "";
+ }
+ return (NULL);
+}
+
+
+/*
+ * Parse the option.
+ */
+
+static Bool
+ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p)
+{
+ char *s, *end;
+
+ if ((s = winFindOptionValue (options, p->name)) != NULL)
+ {
+ switch (p->type)
+ {
+ case OPTV_INTEGER:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.num = strtoul (s, &end, 0);
+ if (*end == '\0')
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_STRING:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an string value\n", p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.str = s;
+ p->found = TRUE;
+ }
+ break;
+ case OPTV_ANYSTR:
+ p->value.str = s;
+ p->found = TRUE;
+ break;
+ case OPTV_REAL:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.realnum = strtod (s, &end);
+ if (*end == '\0')
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_BOOLEAN:
+ if (GetBoolValue (p, s))
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", p->name);
+ p->found = FALSE;
+ }
+ break;
+ case OPTV_FREQ:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ double freq = strtod (s, &end);
+ int units = 0;
+
+ if (end != s)
+ {
+ p->found = TRUE;
+ if (!winNameCompare (end, "Hz"))
+ units = 1;
+ else if (!winNameCompare (end, "kHz") ||
+ !winNameCompare (end, "k"))
+ units = 1000;
+ else if (!winNameCompare (end, "MHz") ||
+ !winNameCompare (end, "M"))
+ units = 1000000;
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found)
+ freq *= (double) units;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found)
+ {
+ p->value.freq.freq = freq;
+ p->value.freq.units = units;
+ }
+ }
+ break;
+ case OPTV_NONE:
+ /* Should never get here */
+ p->found = FALSE;
+ break;
+ }
+ if (p->found)
+ {
+ winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name);
+ if (!(p->type == OPTV_BOOLEAN && *s == 0))
+ {
+ winErrorFVerb (2, " \"%s\"", s);
+ }
+ winErrorFVerb (2, "\n");
+ }
+ }
+ else if (p->type == OPTV_BOOLEAN)
+ {
+ /* Look for matches with options with or without a "No" prefix. */
+ char *n, *newn;
+ OptionInfoRec opt;
+
+ n = winNormalizeName (p->name);
+ if (!n)
+ {
+ p->found = FALSE;
+ return FALSE;
+ }
+ if (strncmp (n, "no", 2) == 0)
+ {
+ newn = n + 2;
+ }
+ else
+ {
+ free (n);
+ n = malloc (strlen (p->name) + 2 + 1);
+ if (!n)
+ {
+ p->found = FALSE;
+ return FALSE;
+ }
+ strcpy (n, "No");
+ strcat (n, p->name);
+ newn = n;
+ }
+ if ((s = winFindOptionValue (options, newn)) != NULL)
+ {
+ if (GetBoolValue (&opt, s))
+ {
+ p->value.bool = !opt.value.bool;
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", newn);
+ p->found = FALSE;
+ }
+ }
+ else
+ {
+ p->found = FALSE;
+ }
+ if (p->found)
+ {
+ winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
+ if (*s != 0)
+ {
+ winErrorFVerb (2, " \"%s\"", s);
+ }
+ winErrorFVerb (2, "\n");
+ }
+ free (n);
+ }
+ else
+ {
+ p->found = FALSE;
+ }
+ return p->found;
+}
+
+
+static Bool
+configLayout (serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
+ char *default_layout)
+{
+#if 0
+#pragma warn UNIMPLEMENTED
+#endif
+ return TRUE;
+}
+
+
+static Bool
+configImpliedLayout (serverLayoutPtr servlayoutp,
+ XF86ConfScreenPtr conf_screen)
+{
+#if 0
+#pragma warn UNIMPLEMENTED
+#endif
+ return TRUE;
+}
+
+
+static Bool
+GetBoolValue (OptionInfoPtr p, const char *s)
+{
+ if (*s == 0)
+ {
+ p->value.bool = TRUE;
+ }
+ else
+ {
+ if (winNameCompare (s, "1") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "on") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "true") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "yes") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "0") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "off") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "false") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "no") == 0)
+ p->value.bool = FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+
+char *
+winNormalizeName (const char *s)
+{
+ char *ret, *q;
+ const char *p;
+
+ if (s == NULL)
+ return NULL;
+
+ ret = malloc (strlen (s) + 1);
+ for (p = s, q = ret; *p != 0; p++)
+ {
+ switch (*p)
+ {
+ case '_':
+ case ' ':
+ case '\t':
+ continue;
+ default:
+ if (isupper (*p))
+ *q++ = tolower (*p);
+ else
+ *q++ = *p;
+ }
+ }
+ *q = '\0';
+ return ret;
+}
+