Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / winconfig.c
CommitLineData
a09e091a
JB
1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
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:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
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.
22 *
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.
27 *
28 * Authors: Alexander Gottwald
29 */
30
31#ifdef HAVE_XWIN_CONFIG_H
32#include <xwin-config.h>
33#endif
34#include "win.h"
35#include "winconfig.h"
36#include "winmsg.h"
37#include "globals.h"
38
39#include "xkbsrv.h"
40
41#ifdef XWIN_XF86CONFIG
42#ifndef CONFIGPATH
43#define CONFIGPATH "%A," "%R," \
44 "/etc/X11/%R," "%P/etc/X11/%R," \
45 "%E," "%F," \
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," \
49 "%P/etc/X11/%X," \
50 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
51 "%P/lib/X11/%X"
52#endif
53#ifndef CONFIGDIRPATH
54#define CONFIGDIRPATH "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
55 "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
56 "%P/etc/X11/%X," \
57 "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
58 "%P/lib/X11/%X"
59#endif
60
61XF86ConfigPtr g_xf86configptr = NULL;
62#endif
63
64WinCmdlineRec g_cmdline = {
65#ifdef XWIN_XF86CONFIG
66 NULL, /* configFile */
67 NULL, /* configDir */
68#endif
69 NULL, /* fontPath */
70#ifdef XWIN_XF86CONFIG
71 NULL, /* keyboard */
72#endif
73 NULL, /* xkbRules */
74 NULL, /* xkbModel */
75 NULL, /* xkbLayout */
76 NULL, /* xkbVariant */
77 NULL, /* xkbOptions */
78 NULL, /* screenname */
79 NULL, /* mousename */
80 FALSE, /* emulate3Buttons */
81 0 /* emulate3Timeout */
82};
83
84winInfoRec g_winInfo = {
85 { /* keyboard */
86 0, /* leds */
87 500, /* delay */
88 30 /* rate */
89 }
90 ,
91 { /* xkb */
92 NULL, /* rules */
93 NULL, /* model */
94 NULL, /* layout */
95 NULL, /* variant */
96 NULL, /* options */
97 }
98 ,
99 {
100 FALSE,
101 50}
102};
103
104#define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
105
106#ifdef XWIN_XF86CONFIG
107serverLayoutRec g_winConfigLayout;
108
109static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p);
110static Bool configLayout(serverLayoutPtr, XF86ConfLayoutPtr, char *);
111static Bool configImpliedLayout(serverLayoutPtr, XF86ConfScreenPtr);
112static Bool GetBoolValue(OptionInfoPtr p, const char *s);
113
114Bool
115winReadConfigfile()
116{
117 Bool retval = TRUE;
118 char *filename, *dirname;
119 MessageType filefrom = X_DEFAULT;
120 MessageType dirfrom = X_DEFAULT;
121 char *xf86ConfigFile = NULL;
122 char *xf86ConfigDir = NULL;
123
124 if (g_cmdline.configFile) {
125 filefrom = X_CMDLINE;
126 xf86ConfigFile = g_cmdline.configFile;
127 }
128 if (g_cmdline.configDir) {
129 dirfrom = X_CMDLINE;
130 xf86ConfigDir = g_cmdline.configDir;
131 }
132
133 /* Parse config file into data structure */
134 xf86initConfigFiles();
135 dirname = xf86openConfigDirFiles(CONFIGDIRPATH, xf86ConfigDir, PROJECTROOT);
136 filename = xf86openConfigFile(CONFIGPATH, xf86ConfigFile, PROJECTROOT);
137
138 /* Hack for backward compatibility */
139 if (!filename && from == X_DEFAULT)
140 filename = xf86openConfigFile(CONFIGPATH, "XF86Config", PROJECTROOT);
141
142 if (filename) {
143 winMsg(from, "Using config file: \"%s\"\n", filename);
144 }
145 else {
146 winMsg(X_ERROR, "Unable to locate/open config file");
147 if (xf86ConfigFile)
148 ErrorF(": \"%s\"", xf86ConfigFile);
149 ErrorF("\n");
150 }
151 if (dirname) {
152 winMsg(from, "Using config directory: \"%s\"\n", dirname);
153 }
154 else {
155 winMsg(X_ERROR, "Unable to locate/open config directory");
156 if (xf86ConfigDir)
157 ErrorF(": \"%s\"", xf86ConfigDir);
158 ErrorF("\n");
159 }
160 if (!filename && !dirname) {
161 return FALSE;
162 }
163 free(filename);
164 free(dirname);
165 if ((g_xf86configptr = xf86readConfigFile()) == NULL) {
166 winMsg(X_ERROR, "Problem parsing the config file\n");
167 return FALSE;
168 }
169 xf86closeConfigFile();
170
171 LogPrintMarkers();
172
173 /* set options from data structure */
174
175 if (g_xf86configptr->conf_layout_lst == NULL ||
176 g_cmdline.screenname != NULL) {
177 if (g_cmdline.screenname == NULL) {
178 winMsg(X_WARNING,
179 "No Layout section. Using the first Screen section.\n");
180 }
181 if (!configImpliedLayout(&g_winConfigLayout,
182 g_xf86configptr->conf_screen_lst)) {
183 winMsg(X_ERROR, "Unable to determine the screen layout\n");
184 return FALSE;
185 }
186 }
187 else {
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;
192
193 if (optlist && winFindOption(optlist, "defaultserverlayout"))
194 dfltlayout =
195 winSetStrOption(optlist, "defaultserverlayout", NULL);
196
197 if (!configLayout(&g_winConfigLayout,
198 g_xf86configptr->conf_layout_lst, dfltlayout)) {
199 winMsg(X_ERROR, "Unable to determine the screen layout\n");
200 return FALSE;
201 }
202 }
203 else {
204 if (!configLayout(&g_winConfigLayout,
205 g_xf86configptr->conf_layout_lst, NULL)) {
206 winMsg(X_ERROR, "Unable to determine the screen layout\n");
207 return FALSE;
208 }
209 }
210 }
211
212 /* setup special config files */
213 winConfigFiles();
214 return retval;
215}
216#endif
217
218/* load layout definitions */
219#include "winlayouts.h"
220
221/* Set the keyboard configuration */
222Bool
223winConfigKeyboard(DeviceIntPtr pDevice)
224{
225 char layoutName[KL_NAMELENGTH];
226 unsigned char layoutFriendlyName[256];
227 static unsigned int layoutNum = 0;
228 int keyboardType;
229
230#ifdef XWIN_XF86CONFIG
231 XF86ConfInputPtr kbd = NULL;
232 XF86ConfInputPtr input_list = NULL;
233 MessageType kbdfrom = X_CONFIG;
234#endif
235 MessageType from = X_DEFAULT;
236 char *s = NULL;
237
238 /* Setup defaults */
239 XkbGetRulesDflts(&g_winInfo.xkb);
240
241 /*
242 * Query the windows autorepeat settings and change the xserver defaults.
243 */
244 {
245 int kbd_delay;
246 DWORD kbd_speed;
247
248 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &kbd_delay, 0) &&
249 SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &kbd_speed, 0)) {
250 switch (kbd_delay) {
251 case 0:
252 g_winInfo.keyboard.delay = 250;
253 break;
254 case 1:
255 g_winInfo.keyboard.delay = 500;
256 break;
257 case 2:
258 g_winInfo.keyboard.delay = 750;
259 break;
260 default:
261 case 3:
262 g_winInfo.keyboard.delay = 1000;
263 break;
264 }
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);
268 }
269 }
270
271 keyboardType = GetKeyboardType(0);
272 if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) {
273 WinKBLayoutPtr pLayout;
274 Bool bfound = FALSE;
275
276 if (!layoutNum)
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
282 too */
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");
290 else
291 winMsg(X_ERROR, "LoadKeyboardLayout failed.\n");
292 }
293 }
294
295 /* Discover the friendly name of the current layout */
296 {
297 HKEY regkey = NULL;
298 const char regtempl[] =
299 "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
300 char *regpath;
301 DWORD namesize = sizeof(layoutFriendlyName);
302
303 regpath = malloc(sizeof(regtempl) + KL_NAMELENGTH + 1);
304 strcpy(regpath, regtempl);
305 strcat(regpath, layoutName);
306
307 if (!RegOpenKey(HKEY_LOCAL_MACHINE, regpath, &regkey))
308 RegQueryValueEx(regkey, "Layout Text", 0, NULL,
309 layoutFriendlyName, &namesize);
310
311 /* Close registry key */
312 if (regkey)
313 RegCloseKey(regkey);
314 free(regpath);
315 }
316
317 winMsg(X_PROBED,
318 "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
319 layoutName, layoutNum, layoutFriendlyName, keyboardType);
320
321 for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
322 if (pLayout->winlayout != layoutNum)
323 continue;
324 if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
325 continue;
326
327 bfound = TRUE;
328 winMsg(X_PROBED,
329 "Found matching XKB configuration \"%s\"\n",
330 pLayout->layoutname);
331
332 winMsg(X_PROBED,
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");
339
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;
344
345 break;
346 }
347
348 if (!bfound) {
349 winMsg(X_ERROR,
350 "Keyboardlayout \"%s\" (%s) is unknown, using X server default layout\n",
351 layoutFriendlyName, layoutName);
352 }
353 }
354
355 /* parse the configuration */
356#ifdef XWIN_XF86CONFIG
357 if (g_cmdline.keyboard)
358 kbdfrom = X_CMDLINE;
359
360 /*
361 * Until the layout code is finished, I search for the keyboard
362 * device and configure the server with it.
363 */
364
365 if (g_xf86configptr != NULL)
366 input_list = g_xf86configptr->conf_input_lst;
367
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,
372 g_cmdline.keyboard))
373 continue;
374 kbd = input_list;
375 }
376 input_list = input_list->list.next;
377 }
378
379 if (kbd != NULL) {
380
381 if (kbd->inp_identifier)
382 winMsg(kbdfrom, "Using keyboard \"%s\" as primary keyboard\n",
383 kbd->inp_identifier);
384
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);
392 free(s);
393 return FALSE;
394 }
395 free(s);
396 winMsg(X_CONFIG, "AutoRepeat: %ld %ld\n",
397 g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
398 }
399#endif
400
401 s = NULL;
402 if (g_cmdline.xkbRules) {
403 s = g_cmdline.xkbRules;
404 from = X_CMDLINE;
405 }
406#ifdef XWIN_XF86CONFIG
407 else {
408 s = winSetStrOption(kbd->inp_option_lst, "XkbRules", NULL);
409 from = X_CONFIG;
410 }
411#endif
412 if (s) {
413 g_winInfo.xkb.rules = NULL_IF_EMPTY(s);
414 winMsg(from, "XKB: rules: \"%s\"\n", s);
415 }
416
417 s = NULL;
418 if (g_cmdline.xkbModel) {
419 s = g_cmdline.xkbModel;
420 from = X_CMDLINE;
421 }
422#ifdef XWIN_XF86CONFIG
423 else {
424 s = winSetStrOption(kbd->inp_option_lst, "XkbModel", NULL);
425 from = X_CONFIG;
426 }
427#endif
428 if (s) {
429 g_winInfo.xkb.model = NULL_IF_EMPTY(s);
430 winMsg(from, "XKB: model: \"%s\"\n", s);
431 }
432
433 s = NULL;
434 if (g_cmdline.xkbLayout) {
435 s = g_cmdline.xkbLayout;
436 from = X_CMDLINE;
437 }
438#ifdef XWIN_XF86CONFIG
439 else {
440 s = winSetStrOption(kbd->inp_option_lst, "XkbLayout", NULL);
441 from = X_CONFIG;
442 }
443#endif
444 if (s) {
445 g_winInfo.xkb.layout = NULL_IF_EMPTY(s);
446 winMsg(from, "XKB: layout: \"%s\"\n", s);
447 }
448
449 s = NULL;
450 if (g_cmdline.xkbVariant) {
451 s = g_cmdline.xkbVariant;
452 from = X_CMDLINE;
453 }
454#ifdef XWIN_XF86CONFIG
455 else {
456 s = winSetStrOption(kbd->inp_option_lst, "XkbVariant", NULL);
457 from = X_CONFIG;
458 }
459#endif
460 if (s) {
461 g_winInfo.xkb.variant = NULL_IF_EMPTY(s);
462 winMsg(from, "XKB: variant: \"%s\"\n", s);
463 }
464
465 s = NULL;
466 if (g_cmdline.xkbOptions) {
467 s = g_cmdline.xkbOptions;
468 from = X_CMDLINE;
469 }
470#ifdef XWIN_XF86CONFIG
471 else {
472 s = winSetStrOption(kbd->inp_option_lst, "XkbOptions", NULL);
473 from = X_CONFIG;
474 }
475#endif
476 if (s) {
477 g_winInfo.xkb.options = NULL_IF_EMPTY(s);
478 winMsg(from, "XKB: options: \"%s\"\n", s);
479 }
480
481#ifdef XWIN_XF86CONFIG
482 }
483#endif
484
485 return TRUE;
486}
487
488#ifdef XWIN_XF86CONFIG
489Bool
490winConfigMouse(DeviceIntPtr pDevice)
491{
492 MessageType mousefrom = X_CONFIG;
493
494 XF86ConfInputPtr mouse = NULL;
495 XF86ConfInputPtr input_list = NULL;
496
497 if (g_cmdline.mouse)
498 mousefrom = X_CMDLINE;
499
500 if (g_xf86configptr != NULL)
501 input_list = g_xf86configptr->conf_input_lst;
502
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,
507 g_cmdline.mouse))
508 continue;
509 mouse = input_list;
510 }
511 input_list = input_list->list.next;
512 }
513
514 if (mouse != NULL) {
515 if (mouse->inp_identifier)
516 winMsg(mousefrom, "Using pointer \"%s\" as primary pointer\n",
517 mouse->inp_identifier);
518
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;
523
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;
528 }
529 else {
530 winMsg(X_ERROR, "No primary pointer configured\n");
531 winMsg(X_DEFAULT, "Using compiletime defaults for pointer\n");
532 }
533
534 return TRUE;
535}
536
537Bool
538winConfigFiles()
539{
540 MessageType from;
541 XF86ConfFilesPtr filesptr = NULL;
542
543 /* set some shortcuts */
544 if (g_xf86configptr != NULL) {
545 filesptr = g_xf86configptr->conf_files;
546 }
547
548 /* Fontpath */
549 from = X_DEFAULT;
550
551 if (g_cmdline.fontPath) {
552 from = X_CMDLINE;
553 defaultFontPath = g_cmdline.fontPath;
554 }
555 else if (filesptr != NULL && filesptr->file_fontpath) {
556 from = X_CONFIG;
557 defaultFontPath = strdup(filesptr->file_fontpath);
558 }
559 winMsg(from, "FontPath set to \"%s\"\n", defaultFontPath);
560
561 return TRUE;
562}
563#else
564Bool
565winConfigFiles(void)
566{
567 /* Fontpath */
568 if (g_cmdline.fontPath) {
569 defaultFontPath = g_cmdline.fontPath;
570 winMsg(X_CMDLINE, "FontPath set to \"%s\"\n", defaultFontPath);
571 }
572
573 return TRUE;
574}
575#endif
576
577Bool
578winConfigOptions(void)
579{
580 return TRUE;
581}
582
583Bool
584winConfigScreens(void)
585{
586 return TRUE;
587}
588
589#ifdef XWIN_XF86CONFIG
590char *
591winSetStrOption(pointer optlist, const char *name, char *deflt)
592{
593 OptionInfoRec o;
594
595 o.name = name;
596 o.type = OPTV_STRING;
597 if (ParseOptionValue(-1, optlist, &o))
598 deflt = o.value.str;
599 if (deflt)
600 return strdup(deflt);
601 else
602 return NULL;
603}
604
605int
606winSetBoolOption(pointer optlist, const char *name, int deflt)
607{
608 OptionInfoRec o;
609
610 o.name = name;
611 o.type = OPTV_BOOLEAN;
612 if (ParseOptionValue(-1, optlist, &o))
613 deflt = o.value.bool;
614 return deflt;
615}
616
617int
618winSetIntOption(pointer optlist, const char *name, int deflt)
619{
620 OptionInfoRec o;
621
622 o.name = name;
623 o.type = OPTV_INTEGER;
624 if (ParseOptionValue(-1, optlist, &o))
625 deflt = o.value.num;
626 return deflt;
627}
628
629double
630winSetRealOption(pointer optlist, const char *name, double deflt)
631{
632 OptionInfoRec o;
633
634 o.name = name;
635 o.type = OPTV_REAL;
636 if (ParseOptionValue(-1, optlist, &o))
637 deflt = o.value.realnum;
638 return deflt;
639}
640
641double
642winSetPercentOption(pointer optlist, const char *name, double deflt)
643{
644 OptionInfoRec o;
645
646 o.name = name;
647 o.type = OPTV_PERCENT;
648 if (ParseOptionValue(-1, optlist, &o))
649 deflt = o.value.realnum;
650 return deflt;
651}
652#endif
653
654/*
655 * Compare two strings for equality. This is caseinsensitive and
656 * The characters '_', ' ' (space) and '\t' (tab) are treated as
657 * not existing.
658 */
659
660int
661winNameCompare(const char *s1, const char *s2)
662{
663 char c1, c2;
664
665 if (!s1 || *s1 == 0) {
666 if (!s2 || *s2 == 0)
667 return 0;
668 else
669 return 1;
670 }
671
672 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
673 s1++;
674 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
675 s2++;
676
677 c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
678 c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
679
680 while (c1 == c2) {
681 if (c1 == 0)
682 return 0;
683 s1++;
684 s2++;
685
686 while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
687 s1++;
688 while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
689 s2++;
690
691 c1 = (isupper((int) *s1) ? tolower((int) *s1) : *s1);
692 c2 = (isupper((int) *s2) ? tolower((int) *s2) : *s2);
693 }
694 return c1 - c2;
695}
696
697#ifdef XWIN_XF86CONFIG
698/*
699 * Find the named option in the list.
700 * @return the pointer to the option record, or NULL if not found.
701 */
702
703XF86OptionPtr
704winFindOption(XF86OptionPtr list, const char *name)
705{
706 while (list) {
707 if (winNameCompare(list->opt_name, name) == 0)
708 return list;
709 list = list->list.next;
710 }
711 return NULL;
712}
713
714/*
715 * Find the Value of an named option.
716 * @return The option value or NULL if not found.
717 */
718
719char *
720winFindOptionValue(XF86OptionPtr list, const char *name)
721{
722 list = winFindOption(list, name);
723 if (list) {
724 if (list->opt_val)
725 return list->opt_val;
726 else
727 return "";
728 }
729 return NULL;
730}
731
732/*
733 * Parse the option.
734 */
735
736static Bool
737ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p)
738{
739 char *s, *end;
740
741 if ((s = winFindOptionValue(options, p->name)) != NULL) {
742 switch (p->type) {
743 case OPTV_INTEGER:
744 if (*s == '\0') {
745 winDrvMsg(scrnIndex, X_WARNING,
746 "Option \"%s\" requires an integer value\n", p->name);
747 p->found = FALSE;
748 }
749 else {
750 p->value.num = strtoul(s, &end, 0);
751 if (*end == '\0') {
752 p->found = TRUE;
753 }
754 else {
755 winDrvMsg(scrnIndex, X_WARNING,
756 "Option \"%s\" requires an integer value\n",
757 p->name);
758 p->found = FALSE;
759 }
760 }
761 break;
762 case OPTV_STRING:
763 if (*s == '\0') {
764 winDrvMsg(scrnIndex, X_WARNING,
765 "Option \"%s\" requires a string value\n", p->name);
766 p->found = FALSE;
767 }
768 else {
769 p->value.str = s;
770 p->found = TRUE;
771 }
772 break;
773 case OPTV_ANYSTR:
774 p->value.str = s;
775 p->found = TRUE;
776 break;
777 case OPTV_REAL:
778 if (*s == '\0') {
779 winDrvMsg(scrnIndex, X_WARNING,
780 "Option \"%s\" requires a floating point value\n",
781 p->name);
782 p->found = FALSE;
783 }
784 else {
785 p->value.realnum = strtod(s, &end);
786 if (*end == '\0') {
787 p->found = TRUE;
788 }
789 else {
790 winDrvMsg(scrnIndex, X_WARNING,
791 "Option \"%s\" requires a floating point value\n",
792 p->name);
793 p->found = FALSE;
794 }
795 }
796 break;
797 case OPTV_BOOLEAN:
798 if (GetBoolValue(p, s)) {
799 p->found = TRUE;
800 }
801 else {
802 winDrvMsg(scrnIndex, X_WARNING,
803 "Option \"%s\" requires a boolean value\n", p->name);
804 p->found = FALSE;
805 }
806 break;
807 case OPTV_PERCENT:
808 if (*s == '\0') {
809 winDrvMsg(scrnIndex, X_WARNING,
810 "Option \"%s\" requires a percent value\n", p->name);
811 p->found = FALSE;
812 }
813 else {
814 double percent = strtod(s, &end);
815
816 if (end != s && winNameCompare(end, "%")) {
817 p->found = TRUE;
818 p->value.realnum = percent;
819 }
820 else {
821 winDrvMsg(scrnIndex, X_WARNING,
822 "Option \"%s\" requires a frequency value\n",
823 p->name);
824 p->found = FALSE;
825 }
826 }
827 case OPTV_FREQ:
828 if (*s == '\0') {
829 winDrvMsg(scrnIndex, X_WARNING,
830 "Option \"%s\" requires a frequency value\n",
831 p->name);
832 p->found = FALSE;
833 }
834 else {
835 double freq = strtod(s, &end);
836 int units = 0;
837
838 if (end != s) {
839 p->found = TRUE;
840 if (!winNameCompare(end, "Hz"))
841 units = 1;
842 else if (!winNameCompare(end, "kHz") ||
843 !winNameCompare(end, "k"))
844 units = 1000;
845 else if (!winNameCompare(end, "MHz") ||
846 !winNameCompare(end, "M"))
847 units = 1000000;
848 else {
849 winDrvMsg(scrnIndex, X_WARNING,
850 "Option \"%s\" requires a frequency value\n",
851 p->name);
852 p->found = FALSE;
853 }
854 if (p->found)
855 freq *= (double) units;
856 }
857 else {
858 winDrvMsg(scrnIndex, X_WARNING,
859 "Option \"%s\" requires a frequency value\n",
860 p->name);
861 p->found = FALSE;
862 }
863 if (p->found) {
864 p->value.freq.freq = freq;
865 p->value.freq.units = units;
866 }
867 }
868 break;
869 case OPTV_NONE:
870 /* Should never get here */
871 p->found = FALSE;
872 break;
873 }
874 if (p->found) {
875 winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name);
876 if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
877 winErrorFVerb(2, " \"%s\"", s);
878 }
879 winErrorFVerb(2, "\n");
880 }
881 }
882 else if (p->type == OPTV_BOOLEAN) {
883 /* Look for matches with options with or without a "No" prefix. */
884 char *n, *newn;
885 OptionInfoRec opt;
886
887 n = winNormalizeName(p->name);
888 if (!n) {
889 p->found = FALSE;
890 return FALSE;
891 }
892 if (strncmp(n, "no", 2) == 0) {
893 newn = n + 2;
894 }
895 else {
896 free(n);
897 n = malloc(strlen(p->name) + 2 + 1);
898 if (!n) {
899 p->found = FALSE;
900 return FALSE;
901 }
902 strcpy(n, "No");
903 strcat(n, p->name);
904 newn = n;
905 }
906 if ((s = winFindOptionValue(options, newn)) != NULL) {
907 if (GetBoolValue(&opt, s)) {
908 p->value.bool = !opt.value.bool;
909 p->found = TRUE;
910 }
911 else {
912 winDrvMsg(scrnIndex, X_WARNING,
913 "Option \"%s\" requires a boolean value\n", newn);
914 p->found = FALSE;
915 }
916 }
917 else {
918 p->found = FALSE;
919 }
920 if (p->found) {
921 winDrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
922 if (*s != 0) {
923 winErrorFVerb(2, " \"%s\"", s);
924 }
925 winErrorFVerb(2, "\n");
926 }
927 free(n);
928 }
929 else {
930 p->found = FALSE;
931 }
932 return p->found;
933}
934
935static Bool
936configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
937 char *default_layout)
938{
939#if 0
940#pragma warn UNIMPLEMENTED
941#endif
942 return TRUE;
943}
944
945static Bool
946configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen)
947{
948#if 0
949#pragma warn UNIMPLEMENTED
950#endif
951 return TRUE;
952}
953
954static Bool
955GetBoolValue(OptionInfoPtr p, const char *s)
956{
957 if (*s == 0) {
958 p->value.bool = TRUE;
959 }
960 else {
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;
977 }
978 return TRUE;
979}
980#endif
981
982char *
983winNormalizeName(const char *s)
984{
985 char *ret, *q;
986 const char *p;
987
988 if (s == NULL)
989 return NULL;
990
991 ret = malloc(strlen(s) + 1);
992 for (p = s, q = ret; *p != 0; p++) {
993 switch (*p) {
994 case '_':
995 case ' ':
996 case '\t':
997 continue;
998 default:
999 if (isupper((int) *p))
1000 *q++ = tolower((int) *p);
1001 else
1002 *q++ = *p;
1003 }
1004 }
1005 *q = '\0';
1006 return ret;
1007}