2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
28 * Authors: Alexander Gottwald
31 #ifdef HAVE_XWIN_CONFIG_H
32 #include <xwin-config.h>
35 #include "winconfig.h"
41 #ifdef XWIN_XF86CONFIG
43 #define CONFIGPATH "%A," "%R," \
44 "/etc/X11/%R," "%P/etc/X11/%R," \
46 "/etc/X11/%F," "%P/etc/X11/%F," \
47 "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
48 "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
50 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
54 #define CONFIGDIRPATH "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
55 "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
57 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
61 XF86ConfigPtr g_xf86configptr
= NULL
;
64 WinCmdlineRec g_cmdline
= {
65 #ifdef XWIN_XF86CONFIG
66 NULL
, /* configFile */
70 #ifdef XWIN_XF86CONFIG
76 NULL
, /* xkbVariant */
77 NULL
, /* xkbOptions */
78 NULL
, /* screenname */
80 FALSE
, /* emulate3Buttons */
81 0 /* emulate3Timeout */
84 winInfoRec g_winInfo
= {
104 #define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
106 #ifdef XWIN_XF86CONFIG
107 serverLayoutRec g_winConfigLayout
;
109 static Bool
ParseOptionValue(int scrnIndex
, pointer options
, OptionInfoPtr p
);
110 static Bool
configLayout(serverLayoutPtr
, XF86ConfLayoutPtr
, char *);
111 static Bool
configImpliedLayout(serverLayoutPtr
, XF86ConfScreenPtr
);
112 static Bool
GetBoolValue(OptionInfoPtr p
, const char *s
);
118 char *filename
, *dirname
;
119 MessageType filefrom
= X_DEFAULT
;
120 MessageType dirfrom
= X_DEFAULT
;
121 char *xf86ConfigFile
= NULL
;
122 char *xf86ConfigDir
= NULL
;
124 if (g_cmdline
.configFile
) {
125 filefrom
= X_CMDLINE
;
126 xf86ConfigFile
= g_cmdline
.configFile
;
128 if (g_cmdline
.configDir
) {
130 xf86ConfigDir
= g_cmdline
.configDir
;
133 /* Parse config file into data structure */
134 xf86initConfigFiles();
135 dirname
= xf86openConfigDirFiles(CONFIGDIRPATH
, xf86ConfigDir
, PROJECTROOT
);
136 filename
= xf86openConfigFile(CONFIGPATH
, xf86ConfigFile
, PROJECTROOT
);
138 /* Hack for backward compatibility */
139 if (!filename
&& from
== X_DEFAULT
)
140 filename
= xf86openConfigFile(CONFIGPATH
, "XF86Config", PROJECTROOT
);
143 winMsg(from
, "Using config file: \"%s\"\n", filename
);
146 winMsg(X_ERROR
, "Unable to locate/open config file");
148 ErrorF(": \"%s\"", xf86ConfigFile
);
152 winMsg(from
, "Using config directory: \"%s\"\n", dirname
);
155 winMsg(X_ERROR
, "Unable to locate/open config directory");
157 ErrorF(": \"%s\"", xf86ConfigDir
);
160 if (!filename
&& !dirname
) {
165 if ((g_xf86configptr
= xf86readConfigFile()) == NULL
) {
166 winMsg(X_ERROR
, "Problem parsing the config file\n");
169 xf86closeConfigFile();
173 /* set options from data structure */
175 if (g_xf86configptr
->conf_layout_lst
== NULL
||
176 g_cmdline
.screenname
!= NULL
) {
177 if (g_cmdline
.screenname
== NULL
) {
179 "No Layout section. Using the first Screen section.\n");
181 if (!configImpliedLayout(&g_winConfigLayout
,
182 g_xf86configptr
->conf_screen_lst
)) {
183 winMsg(X_ERROR
, "Unable to determine the screen layout\n");
188 /* Check if layout is given in the config file */
189 if (g_xf86configptr
->conf_flags
!= NULL
) {
190 char *dfltlayout
= NULL
;
191 pointer optlist
= g_xf86configptr
->conf_flags
->flg_option_lst
;
193 if (optlist
&& winFindOption(optlist
, "defaultserverlayout"))
195 winSetStrOption(optlist
, "defaultserverlayout", NULL
);
197 if (!configLayout(&g_winConfigLayout
,
198 g_xf86configptr
->conf_layout_lst
, dfltlayout
)) {
199 winMsg(X_ERROR
, "Unable to determine the screen layout\n");
204 if (!configLayout(&g_winConfigLayout
,
205 g_xf86configptr
->conf_layout_lst
, NULL
)) {
206 winMsg(X_ERROR
, "Unable to determine the screen layout\n");
212 /* setup special config files */
218 /* load layout definitions */
219 #include "winlayouts.h"
221 /* Set the keyboard configuration */
223 winConfigKeyboard(DeviceIntPtr pDevice
)
225 char layoutName
[KL_NAMELENGTH
];
226 unsigned char layoutFriendlyName
[256];
227 static unsigned int layoutNum
= 0;
230 #ifdef XWIN_XF86CONFIG
231 XF86ConfInputPtr kbd
= NULL
;
232 XF86ConfInputPtr input_list
= NULL
;
233 MessageType kbdfrom
= X_CONFIG
;
235 MessageType from
= X_DEFAULT
;
239 XkbGetRulesDflts(&g_winInfo
.xkb
);
242 * Query the windows autorepeat settings and change the xserver defaults.
248 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY
, 0, &kbd_delay
, 0) &&
249 SystemParametersInfo(SPI_GETKEYBOARDSPEED
, 0, &kbd_speed
, 0)) {
252 g_winInfo
.keyboard
.delay
= 250;
255 g_winInfo
.keyboard
.delay
= 500;
258 g_winInfo
.keyboard
.delay
= 750;
262 g_winInfo
.keyboard
.delay
= 1000;
265 g_winInfo
.keyboard
.rate
= (kbd_speed
> 0) ? kbd_speed
: 1;
266 winMsgVerb(X_PROBED
, 1, "Setting autorepeat to delay=%d, rate=%d\n",
267 g_winInfo
.keyboard
.delay
, g_winInfo
.keyboard
.rate
);
271 keyboardType
= GetKeyboardType(0);
272 if (keyboardType
> 0 && GetKeyboardLayoutName(layoutName
)) {
273 WinKBLayoutPtr pLayout
;
277 layoutNum
= strtoul(layoutName
, (char **) NULL
, 16);
278 if ((layoutNum
& 0xffff) == 0x411) {
279 /* The japanese layouts know a lot of different IMEs which all have
280 different layout numbers set. Map them to a single entry.
281 Same might apply for chinese, korean and other symbol languages
283 layoutNum
= (layoutNum
& 0xffff);
284 if (keyboardType
== 7) {
285 /* Japanese layouts have problems with key event messages
286 such as the lack of WM_KEYUP for Caps Lock key.
287 Loading US layout fixes this problem. */
288 if (LoadKeyboardLayout("00000409", KLF_ACTIVATE
) != NULL
)
289 winMsg(X_INFO
, "Loading US keyboard layout.\n");
291 winMsg(X_ERROR
, "LoadKeyboardLayout failed.\n");
295 /* Discover the friendly name of the current layout */
298 const char regtempl
[] =
299 "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
301 DWORD namesize
= sizeof(layoutFriendlyName
);
303 regpath
= malloc(sizeof(regtempl
) + KL_NAMELENGTH
+ 1);
304 strcpy(regpath
, regtempl
);
305 strcat(regpath
, layoutName
);
307 if (!RegOpenKey(HKEY_LOCAL_MACHINE
, regpath
, ®key
))
308 RegQueryValueEx(regkey
, "Layout Text", 0, NULL
,
309 layoutFriendlyName
, &namesize
);
311 /* Close registry key */
318 "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
319 layoutName
, layoutNum
, layoutFriendlyName
, keyboardType
);
321 for (pLayout
= winKBLayouts
; pLayout
->winlayout
!= -1; pLayout
++) {
322 if (pLayout
->winlayout
!= layoutNum
)
324 if (pLayout
->winkbtype
> 0 && pLayout
->winkbtype
!= keyboardType
)
329 "Found matching XKB configuration \"%s\"\n",
330 pLayout
->layoutname
);
333 "Model = \"%s\" Layout = \"%s\""
334 " Variant = \"%s\" Options = \"%s\"\n",
335 pLayout
->xkbmodel
? pLayout
->xkbmodel
: "none",
336 pLayout
->xkblayout
? pLayout
->xkblayout
: "none",
337 pLayout
->xkbvariant
? pLayout
->xkbvariant
: "none",
338 pLayout
->xkboptions
? pLayout
->xkboptions
: "none");
340 g_winInfo
.xkb
.model
= pLayout
->xkbmodel
;
341 g_winInfo
.xkb
.layout
= pLayout
->xkblayout
;
342 g_winInfo
.xkb
.variant
= pLayout
->xkbvariant
;
343 g_winInfo
.xkb
.options
= pLayout
->xkboptions
;
350 "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n",
351 layoutFriendlyName
, layoutName
);
355 /* parse the configuration */
356 #ifdef XWIN_XF86CONFIG
357 if (g_cmdline
.keyboard
)
361 * Until the layout code is finished, I search for the keyboard
362 * device and configure the server with it.
365 if (g_xf86configptr
!= NULL
)
366 input_list
= g_xf86configptr
->conf_input_lst
;
368 while (input_list
!= NULL
) {
369 if (winNameCompare(input_list
->inp_driver
, "keyboard") == 0) {
370 /* Check if device name matches requested name */
371 if (g_cmdline
.keyboard
&& winNameCompare(input_list
->inp_identifier
,
376 input_list
= input_list
->list
.next
;
381 if (kbd
->inp_identifier
)
382 winMsg(kbdfrom
, "Using keyboard \"%s\" as primary keyboard\n",
383 kbd
->inp_identifier
);
385 if ((s
= winSetStrOption(kbd
->inp_option_lst
, "AutoRepeat", NULL
))) {
386 if ((sscanf(s
, "%ld %ld", &g_winInfo
.keyboard
.delay
,
387 &g_winInfo
.keyboard
.rate
) != 2) ||
388 (g_winInfo
.keyboard
.delay
< 1) ||
389 (g_winInfo
.keyboard
.rate
== 0) ||
390 (1000 / g_winInfo
.keyboard
.rate
) < 1) {
391 winErrorFVerb(2, "\"%s\" is not a valid AutoRepeat value", s
);
396 winMsg(X_CONFIG
, "AutoRepeat: %ld %ld\n",
397 g_winInfo
.keyboard
.delay
, g_winInfo
.keyboard
.rate
);
402 if (g_cmdline
.xkbRules
) {
403 s
= g_cmdline
.xkbRules
;
406 #ifdef XWIN_XF86CONFIG
408 s
= winSetStrOption(kbd
->inp_option_lst
, "XkbRules", NULL
);
413 g_winInfo
.xkb
.rules
= NULL_IF_EMPTY(s
);
414 winMsg(from
, "XKB: rules: \"%s\"\n", s
);
418 if (g_cmdline
.xkbModel
) {
419 s
= g_cmdline
.xkbModel
;
422 #ifdef XWIN_XF86CONFIG
424 s
= winSetStrOption(kbd
->inp_option_lst
, "XkbModel", NULL
);
429 g_winInfo
.xkb
.model
= NULL_IF_EMPTY(s
);
430 winMsg(from
, "XKB: model: \"%s\"\n", s
);
434 if (g_cmdline
.xkbLayout
) {
435 s
= g_cmdline
.xkbLayout
;
438 #ifdef XWIN_XF86CONFIG
440 s
= winSetStrOption(kbd
->inp_option_lst
, "XkbLayout", NULL
);
445 g_winInfo
.xkb
.layout
= NULL_IF_EMPTY(s
);
446 winMsg(from
, "XKB: layout: \"%s\"\n", s
);
450 if (g_cmdline
.xkbVariant
) {
451 s
= g_cmdline
.xkbVariant
;
454 #ifdef XWIN_XF86CONFIG
456 s
= winSetStrOption(kbd
->inp_option_lst
, "XkbVariant", NULL
);
461 g_winInfo
.xkb
.variant
= NULL_IF_EMPTY(s
);
462 winMsg(from
, "XKB: variant: \"%s\"\n", s
);
466 if (g_cmdline
.xkbOptions
) {
467 s
= g_cmdline
.xkbOptions
;
470 #ifdef XWIN_XF86CONFIG
472 s
= winSetStrOption(kbd
->inp_option_lst
, "XkbOptions", NULL
);
477 g_winInfo
.xkb
.options
= NULL_IF_EMPTY(s
);
478 winMsg(from
, "XKB: options: \"%s\"\n", s
);
481 #ifdef XWIN_XF86CONFIG
488 #ifdef XWIN_XF86CONFIG
490 winConfigMouse(DeviceIntPtr pDevice
)
492 MessageType mousefrom
= X_CONFIG
;
494 XF86ConfInputPtr mouse
= NULL
;
495 XF86ConfInputPtr input_list
= NULL
;
498 mousefrom
= X_CMDLINE
;
500 if (g_xf86configptr
!= NULL
)
501 input_list
= g_xf86configptr
->conf_input_lst
;
503 while (input_list
!= NULL
) {
504 if (winNameCompare(input_list
->inp_driver
, "mouse") == 0) {
505 /* Check if device name matches requested name */
506 if (g_cmdline
.mouse
&& winNameCompare(input_list
->inp_identifier
,
511 input_list
= input_list
->list
.next
;
515 if (mouse
->inp_identifier
)
516 winMsg(mousefrom
, "Using pointer \"%s\" as primary pointer\n",
517 mouse
->inp_identifier
);
519 g_winInfo
.pointer
.emulate3Buttons
=
520 winSetBoolOption(mouse
->inp_option_lst
, "Emulate3Buttons", FALSE
);
521 if (g_cmdline
.emulate3buttons
)
522 g_winInfo
.pointer
.emulate3Buttons
= g_cmdline
.emulate3buttons
;
524 g_winInfo
.pointer
.emulate3Timeout
=
525 winSetIntOption(mouse
->inp_option_lst
, "Emulate3Timeout", 50);
526 if (g_cmdline
.emulate3timeout
)
527 g_winInfo
.pointer
.emulate3Timeout
= g_cmdline
.emulate3timeout
;
530 winMsg(X_ERROR
, "No primary pointer configured\n");
531 winMsg(X_DEFAULT
, "Using compiletime defaults for pointer\n");
541 XF86ConfFilesPtr filesptr
= NULL
;
543 /* set some shortcuts */
544 if (g_xf86configptr
!= NULL
) {
545 filesptr
= g_xf86configptr
->conf_files
;
551 if (g_cmdline
.fontPath
) {
553 defaultFontPath
= g_cmdline
.fontPath
;
555 else if (filesptr
!= NULL
&& filesptr
->file_fontpath
) {
557 defaultFontPath
= strdup(filesptr
->file_fontpath
);
559 winMsg(from
, "FontPath set to \"%s\"\n", defaultFontPath
);
568 if (g_cmdline
.fontPath
) {
569 defaultFontPath
= g_cmdline
.fontPath
;
570 winMsg(X_CMDLINE
, "FontPath set to \"%s\"\n", defaultFontPath
);
578 winConfigOptions(void)
584 winConfigScreens(void)
589 #ifdef XWIN_XF86CONFIG
591 winSetStrOption(pointer optlist
, const char *name
, char *deflt
)
596 o
.type
= OPTV_STRING
;
597 if (ParseOptionValue(-1, optlist
, &o
))
600 return strdup(deflt
);
606 winSetBoolOption(pointer optlist
, const char *name
, int deflt
)
611 o
.type
= OPTV_BOOLEAN
;
612 if (ParseOptionValue(-1, optlist
, &o
))
613 deflt
= o
.value
.bool;
618 winSetIntOption(pointer optlist
, const char *name
, int deflt
)
623 o
.type
= OPTV_INTEGER
;
624 if (ParseOptionValue(-1, optlist
, &o
))
630 winSetRealOption(pointer optlist
, const char *name
, double deflt
)
636 if (ParseOptionValue(-1, optlist
, &o
))
637 deflt
= o
.value
.realnum
;
642 winSetPercentOption(pointer optlist
, const char *name
, double deflt
)
647 o
.type
= OPTV_PERCENT
;
648 if (ParseOptionValue(-1, optlist
, &o
))
649 deflt
= o
.value
.realnum
;
655 * Compare two strings for equality. This is caseinsensitive and
656 * The characters '_', ' ' (space) and '\t' (tab) are treated as
661 winNameCompare(const char *s1
, const char *s2
)
665 if (!s1
|| *s1
== 0) {
672 while (*s1
== '_' || *s1
== ' ' || *s1
== '\t')
674 while (*s2
== '_' || *s2
== ' ' || *s2
== '\t')
677 c1
= (isupper((int) *s1
) ? tolower((int) *s1
) : *s1
);
678 c2
= (isupper((int) *s2
) ? tolower((int) *s2
) : *s2
);
686 while (*s1
== '_' || *s1
== ' ' || *s1
== '\t')
688 while (*s2
== '_' || *s2
== ' ' || *s2
== '\t')
691 c1
= (isupper((int) *s1
) ? tolower((int) *s1
) : *s1
);
692 c2
= (isupper((int) *s2
) ? tolower((int) *s2
) : *s2
);
697 #ifdef XWIN_XF86CONFIG
699 * Find the named option in the list.
700 * @return the pointer to the option record, or NULL if not found.
704 winFindOption(XF86OptionPtr list
, const char *name
)
707 if (winNameCompare(list
->opt_name
, name
) == 0)
709 list
= list
->list
.next
;
715 * Find the Value of an named option.
716 * @return The option value or NULL if not found.
720 winFindOptionValue(XF86OptionPtr list
, const char *name
)
722 list
= winFindOption(list
, name
);
725 return list
->opt_val
;
737 ParseOptionValue(int scrnIndex
, pointer options
, OptionInfoPtr p
)
741 if ((s
= winFindOptionValue(options
, p
->name
)) != NULL
) {
745 winDrvMsg(scrnIndex
, X_WARNING
,
746 "Option \"%s\" requires an integer value\n", p
->name
);
750 p
->value
.num
= strtoul(s
, &end
, 0);
755 winDrvMsg(scrnIndex
, X_WARNING
,
756 "Option \"%s\" requires an integer value\n",
764 winDrvMsg(scrnIndex
, X_WARNING
,
765 "Option \"%s\" requires a string value\n", p
->name
);
779 winDrvMsg(scrnIndex
, X_WARNING
,
780 "Option \"%s\" requires a floating point value\n",
785 p
->value
.realnum
= strtod(s
, &end
);
790 winDrvMsg(scrnIndex
, X_WARNING
,
791 "Option \"%s\" requires a floating point value\n",
798 if (GetBoolValue(p
, s
)) {
802 winDrvMsg(scrnIndex
, X_WARNING
,
803 "Option \"%s\" requires a boolean value\n", p
->name
);
809 winDrvMsg(scrnIndex
, X_WARNING
,
810 "Option \"%s\" requires a percent value\n", p
->name
);
814 double percent
= strtod(s
, &end
);
816 if (end
!= s
&& winNameCompare(end
, "%")) {
818 p
->value
.realnum
= percent
;
821 winDrvMsg(scrnIndex
, X_WARNING
,
822 "Option \"%s\" requires a frequency value\n",
829 winDrvMsg(scrnIndex
, X_WARNING
,
830 "Option \"%s\" requires a frequency value\n",
835 double freq
= strtod(s
, &end
);
840 if (!winNameCompare(end
, "Hz"))
842 else if (!winNameCompare(end
, "kHz") ||
843 !winNameCompare(end
, "k"))
845 else if (!winNameCompare(end
, "MHz") ||
846 !winNameCompare(end
, "M"))
849 winDrvMsg(scrnIndex
, X_WARNING
,
850 "Option \"%s\" requires a frequency value\n",
855 freq
*= (double) units
;
858 winDrvMsg(scrnIndex
, X_WARNING
,
859 "Option \"%s\" requires a frequency value\n",
864 p
->value
.freq
.freq
= freq
;
865 p
->value
.freq
.units
= units
;
870 /* Should never get here */
875 winDrvMsgVerb(scrnIndex
, X_CONFIG
, 2, "Option \"%s\"", p
->name
);
876 if (!(p
->type
== OPTV_BOOLEAN
&& *s
== 0)) {
877 winErrorFVerb(2, " \"%s\"", s
);
879 winErrorFVerb(2, "\n");
882 else if (p
->type
== OPTV_BOOLEAN
) {
883 /* Look for matches with options with or without a "No" prefix. */
887 n
= winNormalizeName(p
->name
);
892 if (strncmp(n
, "no", 2) == 0) {
897 n
= malloc(strlen(p
->name
) + 2 + 1);
906 if ((s
= winFindOptionValue(options
, newn
)) != NULL
) {
907 if (GetBoolValue(&opt
, s
)) {
908 p
->value
.bool = !opt
.value
.bool;
912 winDrvMsg(scrnIndex
, X_WARNING
,
913 "Option \"%s\" requires a boolean value\n", newn
);
921 winDrvMsgVerb(scrnIndex
, X_CONFIG
, 2, "Option \"%s\"", newn
);
923 winErrorFVerb(2, " \"%s\"", s
);
925 winErrorFVerb(2, "\n");
936 configLayout(serverLayoutPtr servlayoutp
, XF86ConfLayoutPtr conf_layout
,
937 char *default_layout
)
940 #pragma warn UNIMPLEMENTED
946 configImpliedLayout(serverLayoutPtr servlayoutp
, XF86ConfScreenPtr conf_screen
)
949 #pragma warn UNIMPLEMENTED
955 GetBoolValue(OptionInfoPtr p
, const char *s
)
958 p
->value
.bool = TRUE
;
961 if (winNameCompare(s
, "1") == 0)
962 p
->value
.bool = TRUE
;
963 else if (winNameCompare(s
, "on") == 0)
964 p
->value
.bool = TRUE
;
965 else if (winNameCompare(s
, "true") == 0)
966 p
->value
.bool = TRUE
;
967 else if (winNameCompare(s
, "yes") == 0)
968 p
->value
.bool = TRUE
;
969 else if (winNameCompare(s
, "0") == 0)
970 p
->value
.bool = FALSE
;
971 else if (winNameCompare(s
, "off") == 0)
972 p
->value
.bool = FALSE
;
973 else if (winNameCompare(s
, "false") == 0)
974 p
->value
.bool = FALSE
;
975 else if (winNameCompare(s
, "no") == 0)
976 p
->value
.bool = FALSE
;
983 winNormalizeName(const char *s
)
991 ret
= malloc(strlen(s
) + 1);
992 for (p
= s
, q
= ret
; *p
!= 0; p
++) {
999 if (isupper((int) *p
))
1000 *q
++ = tolower((int) *p
);