1015 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1015 lines
		
	
	
		
			23 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	
 | |
|  */
 | |
| /* $XFree86: xc/programs/Xserver/hw/xwin/winconfig.c,v 1.4 2003/10/08 11:13:02 eich Exp $ */
 | |
| 
 | |
| #include "win.h"
 | |
| #include "winconfig.h"
 | |
| #include "winmsg.h"
 | |
| #include "globals.h"
 | |
| 
 | |
| #ifdef XKB
 | |
| #define XKB_IN_SERVER
 | |
| #include "XKBsrv.h"
 | |
| #endif
 | |
| 
 | |
| #ifndef CONFIGPATH
 | |
| #define CONFIGPATH  "%A," "%R," \
 | |
|                     "/etc/X11/%R," "%P/etc/X11/%R," \
 | |
|                     "%E," "%F," \
 | |
|                     "/etc/X11/%F," "%P/etc/X11/%F," \
 | |
|                     "%D/%X," \
 | |
|                     "/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;
 | |
| WinCmdlineRec g_cmdline = {
 | |
|   NULL,				/* configFile */
 | |
|   NULL,				/* fontPath */
 | |
|   NULL,				/* rgbPath */
 | |
|   NULL,				/* keyboard */
 | |
| #ifdef XKB
 | |
|   FALSE,			/* noXkbExtension */
 | |
|   NULL,				/* xkbMap */
 | |
| #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}
 | |
| };
 | |
| 
 | |
| 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);
 | |
| 
 | |
| #define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
 | |
| 
 | |
| 
 | |
| 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);
 | |
|   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 determin the screen layout\n");
 | |
| 	      return FALSE;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* setup special config files */
 | |
|   winConfigFiles ();
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Set the keyboard configuration */
 | |
| 
 | |
| typedef struct {
 | |
|     unsigned int winlayout;
 | |
|     int winkbtype;
 | |
|     char *xkbmodel;
 | |
|     char *xkblayout;
 | |
|     char *xkbvariant;
 | |
|     char *xkboptions;
 | |
|     char *layoutname;
 | |
| } WinKBLayoutRec, *WinKBLayoutPtr;
 | |
| 
 | |
| WinKBLayoutRec winKBLayouts[] = {
 | |
|     {  0x405, -1, "pc105", "cz",      NULL, NULL, "Czech"},
 | |
|     {  0x406, -1, "pc105", "dk",      NULL, NULL, "Danish"},
 | |
|     {  0x407, -1, "pc105", "de",      NULL, NULL, "German (Germany)"},
 | |
|     {0x10407, -1, "pc105", "de",      NULL, NULL, "German (Germany, IBM)"},
 | |
|     {  0x807, -1, "pc105", "de_CH",   NULL, NULL, "German (Switzerland)"},
 | |
|     {0x10409, -1, "pc105", "dvorak",  NULL, NULL, "English (USA, Dvorak)"}, 
 | |
|     {0x20409, -1, "pc105", "us_intl", NULL, NULL, "English (USA, International)"}, 
 | |
|     {  0x809, -1, "pc105", "gb",      NULL, NULL, "English (United Kingdom)"},
 | |
|     {  0x40a, -1, "pc105", "es",      NULL, NULL, "Spanish (Spain, Traditional Sort)"},
 | |
|     {  0x40b, -1, "pc105", "fi",      NULL, NULL, "Finnish"},
 | |
|     {  0x40c, -1, "pc105", "fr",      NULL, NULL, "French (Standard)"},
 | |
|     {  0x80c, -1, "pc105", "be",      NULL, NULL, "French (Belgian)"},
 | |
|     {  0x410, -1, "pc105", "it",      NULL, NULL, "Italian"},
 | |
|     {  0x411, -1, "jp",    "jp",      NULL, NULL, "Japanese"},
 | |
|     {  0x414, -1, "pc105", "no",      NULL, NULL, "Norwegian"},
 | |
|     {  0x416, -1, "pc105", "pt",      NULL, NULL, "Portuguese (Brazil, ABNT)"},
 | |
|     {0x10416, -1, "abnt2", "br",      NULL, NULL, "Portuguese (Brazil, ABNT2)"},
 | |
|     {  0x816, -1, "pc105", "pt",      NULL, NULL, "Portuguese (Portugal)"},
 | |
|     {  0x41d, -1, "pc105", "se",      NULL, NULL, "Swedish (Sweden)"},
 | |
|     {     -1, -1, NULL,    NULL,      NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| 
 | |
| Bool
 | |
| winConfigKeyboard (DeviceIntPtr pDevice)
 | |
| {
 | |
|   char                          layoutName[KL_NAMELENGTH];
 | |
|   unsigned int                  layoutNum;
 | |
|   int                           keyboardType;  
 | |
|   XF86ConfInputPtr		kbd = NULL;
 | |
|   XF86ConfInputPtr		input_list = NULL;
 | |
|   MessageType			from = X_DEFAULT;
 | |
|   MessageType			kbdfrom = X_CONFIG;
 | |
| 
 | |
|   /* 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 = "xfree86";
 | |
|   g_winInfo.xkb.model = "pc101";
 | |
|   g_winInfo.xkb.layout = "us";
 | |
|   g_winInfo.xkb.variant = NULL;
 | |
|   g_winInfo.xkb.options = NULL;
 | |
| # endif	/* PC98 */
 | |
| 
 | |
|   
 | |
| 
 | |
|   keyboardType = GetKeyboardType (0);
 | |
|   if (keyboardType > 0 && GetKeyboardLayoutName (layoutName)) 
 | |
|   {
 | |
|     WinKBLayoutPtr	pLayout;
 | |
|       
 | |
|     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);
 | |
|     }
 | |
|     winMsg (X_DEFAULT, "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;
 | |
| 	
 | |
| 	winMsg (X_DEFAULT,
 | |
| 		"Using preset keyboard for \"%s\" (%s), type \"%d\"\n",
 | |
| 		pLayout->layoutname, layoutName, 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;
 | |
|       }
 | |
|   }  
 | |
|   
 | |
|   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 */
 | |
| 
 | |
|   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);
 | |
| 
 | |
| #ifdef XKB
 | |
|       from = X_DEFAULT;
 | |
|       if (g_cmdline.noXkbExtension)
 | |
| 	{
 | |
| 	  from = X_CMDLINE;
 | |
| 	  g_winInfo.xkb.disable = TRUE;
 | |
| 	}
 | |
|       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;
 | |
| 	    }
 | |
| 	}
 | |
|       if (g_winInfo.xkb.disable)
 | |
| 	{
 | |
| 	  winMsg (from, "XkbExtension disabled\n");
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  char *s;
 | |
| 
 | |
| 	  if ((s = winSetStrOption (kbd->inp_option_lst, "XkbRules", NULL)))
 | |
| 	    {
 | |
| 	      g_winInfo.xkb.rules = NULL_IF_EMPTY (s);
 | |
| 	      winMsg (X_CONFIG, "XKB: rules: \"%s\"\n", s);
 | |
| 	    }
 | |
| 
 | |
| 	  if ((s = winSetStrOption (kbd->inp_option_lst, "XkbModel", NULL)))
 | |
| 	    {
 | |
| 	      g_winInfo.xkb.model = NULL_IF_EMPTY (s);
 | |
| 	      winMsg (X_CONFIG, "XKB: model: \"%s\"\n", s);
 | |
| 	    }
 | |
| 
 | |
| 	  if ((s = winSetStrOption (kbd->inp_option_lst, "XkbLayout", NULL)))
 | |
| 	    {
 | |
| 	      g_winInfo.xkb.layout = NULL_IF_EMPTY (s);
 | |
| 	      winMsg (X_CONFIG, "XKB: layout: \"%s\"\n", s);
 | |
| 	    }
 | |
| 
 | |
| 	  if ((s = winSetStrOption (kbd->inp_option_lst, "XkbVariant", NULL)))
 | |
| 	    {
 | |
| 	      g_winInfo.xkb.variant = NULL_IF_EMPTY (s);
 | |
| 	      winMsg (X_CONFIG, "XKB: variant: \"%s\"\n", s);
 | |
| 	    }
 | |
| 
 | |
| 	  if ((s = winSetStrOption (kbd->inp_option_lst, "XkbOptions", NULL)))
 | |
| 	    {
 | |
| 	      g_winInfo.xkb.options = NULL_IF_EMPTY (s);
 | |
| 	      winMsg (X_CONFIG, "XKB: options: \"%s\"\n", s);
 | |
| 	    }
 | |
| 
 | |
| 	  from = X_CMDLINE;
 | |
| 	  if (!XkbInitialMap)
 | |
| 	    {
 | |
| 	      s =
 | |
| 		winSetStrOption (kbd->inp_option_lst, "XkbInitialMap", NULL);
 | |
| 	      if (s)
 | |
| 		{
 | |
| 		  XkbInitialMap = NULL_IF_EMPTY (s);
 | |
| 		  from = X_CONFIG;
 | |
| 		}
 | |
| 	    }
 | |
| 
 | |
| 	  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
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       winMsg (X_ERROR, "No primary keyboard configured\n");
 | |
|       winMsg (X_DEFAULT, "Using compiletime defaults for keyboard\n");
 | |
|     }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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);
 | |
| 
 | |
|   /* RGBPath */
 | |
|   from = X_DEFAULT;
 | |
|   if (g_cmdline.rgbPath)
 | |
|     {
 | |
|       from = X_CMDLINE;
 | |
|       rgbPath = g_cmdline.rgbPath;
 | |
|     }
 | |
|   else if (filesptr != NULL && filesptr->file_rgbpath)
 | |
|     {
 | |
|       from = X_CONFIG;
 | |
|       rgbPath = xstrdup (filesptr->file_rgbpath);
 | |
|     }
 | |
|   winMsg (from, "RgbPath set to \"%s\"\n", rgbPath);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| Bool
 | |
| winConfigOptions ()
 | |
| {
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| Bool
 | |
| winConfigScreens ()
 | |
| {
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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;
 | |
| }
 |