1021 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1021 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *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"
 | |
| 
 | |
| #include "xkbsrv.h"
 | |
| 
 | |
| #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
 | |
| #ifndef CONFIGDIRPATH
 | |
| #define CONFIGDIRPATH  "/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 */
 | |
|     NULL,                       /* configDir */
 | |
| #endif
 | |
|     NULL,                       /* fontPath */
 | |
| #ifdef XWIN_XF86CONFIG
 | |
|     NULL,                       /* keyboard */
 | |
| #endif
 | |
|     NULL,                       /* xkbRules */
 | |
|     NULL,                       /* xkbModel */
 | |
|     NULL,                       /* xkbLayout */
 | |
|     NULL,                       /* xkbVariant */
 | |
|     NULL,                       /* xkbOptions */
 | |
|     NULL,                       /* screenname */
 | |
|     NULL,                       /* mousename */
 | |
|     FALSE,                      /* emulate3Buttons */
 | |
|     0                           /* emulate3Timeout */
 | |
| };
 | |
| 
 | |
| winInfoRec g_winInfo = {
 | |
|     {                           /* keyboard */
 | |
|      0,                         /* leds */
 | |
|      500,                       /* delay */
 | |
|      30                         /* rate */
 | |
|      }
 | |
|     ,
 | |
|     {                           /* xkb */
 | |
|      NULL,                      /* rules */
 | |
|      NULL,                      /* model */
 | |
|      NULL,                      /* layout */
 | |
|      NULL,                      /* variant */
 | |
|      NULL,                      /* options */
 | |
|      }
 | |
|     ,
 | |
|     {
 | |
|      FALSE,
 | |
|      50}
 | |
| };
 | |
| 
 | |
| #define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
 | |
| 
 | |
| #ifdef XWIN_XF86CONFIG
 | |
| serverLayoutRec g_winConfigLayout;
 | |
| 
 | |
| static Bool ParseOptionValue(int scrnIndex, void *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;
 | |
|     char *filename, *dirname;
 | |
|     MessageType filefrom = X_DEFAULT;
 | |
|     MessageType dirfrom = X_DEFAULT;
 | |
|     char *xf86ConfigFile = NULL;
 | |
|     char *xf86ConfigDir = NULL;
 | |
| 
 | |
|     if (g_cmdline.configFile) {
 | |
|         filefrom = X_CMDLINE;
 | |
|         xf86ConfigFile = g_cmdline.configFile;
 | |
|     }
 | |
|     if (g_cmdline.configDir) {
 | |
|         dirfrom = X_CMDLINE;
 | |
|         xf86ConfigDir = g_cmdline.configDir;
 | |
|     }
 | |
| 
 | |
|     /* Parse config file into data structure */
 | |
|     xf86initConfigFiles();
 | |
|     dirname = xf86openConfigDirFiles(CONFIGDIRPATH, xf86ConfigDir, PROJECTROOT);
 | |
|     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");
 | |
|     }
 | |
|     if (dirname) {
 | |
|         winMsg(from, "Using config directory: \"%s\"\n", dirname);
 | |
|     }
 | |
|     else {
 | |
|         winMsg(X_ERROR, "Unable to locate/open config directory");
 | |
|         if (xf86ConfigDir)
 | |
|             ErrorF(": \"%s\"", xf86ConfigDir);
 | |
|         ErrorF("\n");
 | |
|     }
 | |
|     if (!filename && !dirname) {
 | |
|         return FALSE;
 | |
|     }
 | |
|     free(filename);
 | |
|     free(dirname);
 | |
|     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;
 | |
|             void *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)
 | |
| {
 | |
|     char layoutName[KL_NAMELENGTH];
 | |
|     unsigned char layoutFriendlyName[256];
 | |
|     unsigned int layoutNum = 0;
 | |
|     unsigned int deviceIdentifier = 0;
 | |
|     int keyboardType;
 | |
| 
 | |
| #ifdef XWIN_XF86CONFIG
 | |
|     XF86ConfInputPtr kbd = NULL;
 | |
|     XF86ConfInputPtr input_list = NULL;
 | |
|     MessageType kbdfrom = X_CONFIG;
 | |
| #endif
 | |
|     MessageType from = X_DEFAULT;
 | |
|     char *s = NULL;
 | |
| 
 | |
|     /* Setup defaults */
 | |
|     XkbGetRulesDflts(&g_winInfo.xkb);
 | |
| 
 | |
|     /*
 | |
|      * Query the windows autorepeat settings and change the xserver defaults.
 | |
|      */
 | |
|     {
 | |
|         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;
 | |
|             winMsg(X_PROBED, "Setting autorepeat to delay=%ld, rate=%ld\n",
 | |
|                    g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
 | |
| 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     keyboardType = GetKeyboardType(0);
 | |
|     if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) {
 | |
|         WinKBLayoutPtr pLayout;
 | |
|         Bool bfound = FALSE;
 | |
|         int pass;
 | |
| 
 | |
|         layoutNum = strtoul(layoutName, (char **) NULL, 16);
 | |
|         if ((layoutNum & 0xffff) == 0x411) {
 | |
|             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, "LoadKeyboardLayout failed.\n");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* Discover the friendly name of the current layout */
 | |
|         {
 | |
|             HKEY regkey = NULL;
 | |
|             const char regtempl[] =
 | |
|                 "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
 | |
|             char *regpath;
 | |
|             DWORD namesize = sizeof(layoutFriendlyName);
 | |
| 
 | |
|             regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1);
 | |
|             strcpy(regpath, regtempl);
 | |
|             strcat(regpath, layoutName);
 | |
| 
 | |
|             if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, ®key))
 | |
|                 RegQueryValueEx(regkey, "Layout Text", 0, NULL,
 | |
|                                 layoutFriendlyName, &namesize);
 | |
| 
 | |
|             /* Close registry key */
 | |
|             if (regkey)
 | |
|                 RegCloseKey(regkey);
 | |
|             free(regpath);
 | |
|         }
 | |
| 
 | |
|         winMsg(X_PROBED,
 | |
|                "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
 | |
|                layoutName, layoutNum, layoutFriendlyName, keyboardType);
 | |
| 
 | |
|         deviceIdentifier = layoutNum >> 16;
 | |
|         for (pass = 0; pass < 2; pass++) {
 | |
|             /* If we didn't find an exact match for the input locale identifer,
 | |
|                try to find an match on the language identifier part only  */
 | |
|             if (pass == 1)
 | |
|                 layoutNum = (layoutNum & 0xffff);
 | |
| 
 | |
|             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,
 | |
|                        "Found matching XKB configuration \"%s\"\n",
 | |
|                        pLayout->layoutname);
 | |
| 
 | |
|                 winMsg(X_PROBED,
 | |
|                        "Model = \"%s\" Layout = \"%s\""
 | |
|                        " Variant = \"%s\" Options = \"%s\"\n",
 | |
|                        pLayout->xkbmodel ? pLayout->xkbmodel : "none",
 | |
|                        pLayout->xkblayout ? pLayout->xkblayout : "none",
 | |
|                        pLayout->xkbvariant ? pLayout->xkbvariant : "none",
 | |
|                        pLayout->xkboptions ? pLayout->xkboptions : "none");
 | |
| 
 | |
|                 g_winInfo.xkb.model = pLayout->xkbmodel;
 | |
|                 g_winInfo.xkb.layout = pLayout->xkblayout;
 | |
|                 g_winInfo.xkb.variant = pLayout->xkbvariant;
 | |
|                 g_winInfo.xkb.options = pLayout->xkboptions;
 | |
| 
 | |
|                 if (deviceIdentifier == 0xa000) {
 | |
|                     winMsg(X_PROBED, "Windows keyboard layout device identifier indicates Macintosh, setting Model = \"macintosh\"");
 | |
|                     g_winInfo.xkb.model = "macintosh";
 | |
|                 }
 | |
| 
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if (bfound)
 | |
|                 break;
 | |
|         }
 | |
| 
 | |
|         if (!bfound) {
 | |
|             winMsg(X_ERROR,
 | |
|                    "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n",
 | |
|                    layoutFriendlyName, layoutName);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* 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);
 | |
|                 free(s);
 | |
|                 return FALSE;
 | |
|             }
 | |
|             free(s);
 | |
|             winMsg(X_CONFIG, "AutoRepeat: %ld %ld\n",
 | |
|                    g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         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
 | |
|     }
 | |
| #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 = strdup(filesptr->file_fontpath);
 | |
|     }
 | |
|     winMsg(from, "FontPath set to \"%s\"\n", defaultFontPath);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| #else
 | |
| Bool
 | |
| winConfigFiles(void)
 | |
| {
 | |
|     /* Fontpath */
 | |
|     if (g_cmdline.fontPath) {
 | |
|         defaultFontPath = g_cmdline.fontPath;
 | |
|         winMsg(X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath);
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| Bool
 | |
| winConfigOptions(void)
 | |
| {
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| winConfigScreens(void)
 | |
| {
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| #ifdef XWIN_XF86CONFIG
 | |
| char *
 | |
| winSetStrOption(void *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 strdup(deflt);
 | |
|     else
 | |
|         return NULL;
 | |
| }
 | |
| 
 | |
| int
 | |
| winSetBoolOption(void *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(void *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(void *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;
 | |
| }
 | |
| 
 | |
| double
 | |
| winSetPercentOption(void *optlist, const char *name, double deflt)
 | |
| {
 | |
|     OptionInfoRec o;
 | |
| 
 | |
|     o.name = name;
 | |
|     o.type = OPTV_PERCENT;
 | |
|     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((int) *s1) ? tolower((int) *s1) : *s1);
 | |
|     c2 = (isupper((int) *s2) ? tolower((int) *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((int) *s1) ? tolower((int) *s1) : *s1);
 | |
|         c2 = (isupper((int) *s2) ? tolower((int) *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, void *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 a 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_PERCENT:
 | |
|             if (*s == '\0') {
 | |
|                 winDrvMsg(scrnIndex, X_WARNING,
 | |
|                           "Option \"%s\" requires a percent value\n", p->name);
 | |
|                 p->found = FALSE;
 | |
|             }
 | |
|             else {
 | |
|                 double percent = strtod(s, &end);
 | |
| 
 | |
|                 if (end != s && winNameCompare(end, "%")) {
 | |
|                     p->found = TRUE;
 | |
|                     p->value.realnum = percent;
 | |
|                 }
 | |
|                 else {
 | |
|                     winDrvMsg(scrnIndex, X_WARNING,
 | |
|                               "Option \"%s\" requires a frequency value\n",
 | |
|                               p->name);
 | |
|                     p->found = FALSE;
 | |
|                 }
 | |
|             }
 | |
|         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((int) *p))
 | |
|                 *q++ = tolower((int) *p);
 | |
|             else
 | |
|                 *q++ = *p;
 | |
|         }
 | |
|     }
 | |
|     *q = '\0';
 | |
|     return ret;
 | |
| }
 |