2 * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
29 * Author: David Dawes <dawes@xfree86.org>
31 * This file includes public option handling functions.
34 #ifdef HAVE_XORG_CONFIG_H
35 #include <xorg-config.h>
44 #include "xf86Xinput.h"
45 #include "xf86Optrec.h"
46 #include "xf86Parser.h"
47 #include "optionstr.h"
49 static Bool
ParseOptionValue(int scrnIndex
, XF86OptionPtr options
,
50 OptionInfoPtr p
, Bool markUsed
);
53 * xf86CollectOptions collects the options from each of the config file
54 * sections used by the screen and puts the combined list in pScrn->options.
55 * This function requires that the following have been initialised:
58 * pScrn->Entities[i]->device
62 * The extraOpts parameter may optionally contain a list of additional options
65 * The order of precedence for options is:
67 * extraOpts, display, confScreen, monitor, device
71 xf86CollectOptions(ScrnInfoPtr pScrn
, XF86OptionPtr extraOpts
)
74 XF86OptionPtr extras
= (XF86OptionPtr
) extraOpts
;
79 pScrn
->options
= NULL
;
81 for (i
= pScrn
->numEntities
- 1; i
>= 0; i
--) {
82 device
= xf86GetDevFromEntity(pScrn
->entityList
[i
],
83 pScrn
->entityInstanceList
[i
]);
84 if (device
&& device
->options
) {
85 tmp
= xf86optionListDup(device
->options
);
87 xf86optionListMerge(pScrn
->options
, tmp
);
92 if (pScrn
->monitor
->options
) {
93 tmp
= xf86optionListDup(pScrn
->monitor
->options
);
95 pScrn
->options
= xf86optionListMerge(pScrn
->options
, tmp
);
99 if (pScrn
->confScreen
->options
) {
100 tmp
= xf86optionListDup(pScrn
->confScreen
->options
);
102 pScrn
->options
= xf86optionListMerge(pScrn
->options
, tmp
);
104 pScrn
->options
= tmp
;
106 if (pScrn
->display
->options
) {
107 tmp
= xf86optionListDup(pScrn
->display
->options
);
109 pScrn
->options
= xf86optionListMerge(pScrn
->options
, tmp
);
111 pScrn
->options
= tmp
;
114 tmp
= xf86optionListDup(extras
);
116 pScrn
->options
= xf86optionListMerge(pScrn
->options
, tmp
);
118 pScrn
->options
= tmp
;
123 * xf86CollectInputOptions collects extra options for an InputDevice (other
124 * than those added by the config backend).
125 * The options are merged into the existing ones and thus take precedence
130 xf86CollectInputOptions(InputInfoPtr pInfo
, const char **defaultOpts
)
133 XF86OptionPtr tmp
= xf86optionListCreate(defaultOpts
, -1, 0);
136 pInfo
->options
= xf86optionListMerge(tmp
, pInfo
->options
);
138 pInfo
->options
= tmp
;
143 * Duplicate the option list passed in. The returned pointer will be a newly
144 * allocated option list and must be freed by the caller.
147 xf86OptionListDuplicate(XF86OptionPtr options
)
149 XF86OptionPtr o
= NULL
;
152 o
= xf86AddNewOption(o
, xf86OptionName(options
),
153 xf86OptionValue(options
));
154 options
= xf86nextOption(options
);
160 /* Created for new XInput stuff -- essentially extensions to the parser */
163 LookupIntOption(XF86OptionPtr optlist
, const char *name
, int deflt
,
169 o
.type
= OPTV_INTEGER
;
170 if (ParseOptionValue(-1, optlist
, &o
, markUsed
))
176 LookupRealOption(XF86OptionPtr optlist
, const char *name
, double deflt
,
183 if (ParseOptionValue(-1, optlist
, &o
, markUsed
))
184 deflt
= o
.value
.realnum
;
189 LookupStrOption(XF86OptionPtr optlist
, const char *name
, const char *deflt
,
195 o
.type
= OPTV_STRING
;
196 if (ParseOptionValue(-1, optlist
, &o
, markUsed
))
199 return strdup(deflt
);
205 LookupBoolOption(XF86OptionPtr optlist
, const char *name
, int deflt
,
211 o
.type
= OPTV_BOOLEAN
;
212 if (ParseOptionValue(-1, optlist
, &o
, markUsed
))
213 deflt
= o
.value
.bool;
218 LookupPercentOption(XF86OptionPtr optlist
, const char *name
, double deflt
,
224 o
.type
= OPTV_PERCENT
;
225 if (ParseOptionValue(-1, optlist
, &o
, markUsed
))
226 deflt
= o
.value
.realnum
;
230 /* These xf86Set* functions are intended for use by non-screen specific code */
233 xf86SetIntOption(XF86OptionPtr optlist
, const char *name
, int deflt
)
235 return LookupIntOption(optlist
, name
, deflt
, TRUE
);
239 xf86SetRealOption(XF86OptionPtr optlist
, const char *name
, double deflt
)
241 return LookupRealOption(optlist
, name
, deflt
, TRUE
);
245 xf86SetStrOption(XF86OptionPtr optlist
, const char *name
, const char *deflt
)
247 return LookupStrOption(optlist
, name
, deflt
, TRUE
);
251 xf86SetBoolOption(XF86OptionPtr optlist
, const char *name
, int deflt
)
253 return LookupBoolOption(optlist
, name
, deflt
, TRUE
);
257 xf86SetPercentOption(XF86OptionPtr optlist
, const char *name
, double deflt
)
259 return LookupPercentOption(optlist
, name
, deflt
, TRUE
);
263 * These are like the Set*Option functions, but they don't mark the options
267 xf86CheckIntOption(XF86OptionPtr optlist
, const char *name
, int deflt
)
269 return LookupIntOption(optlist
, name
, deflt
, FALSE
);
273 xf86CheckRealOption(XF86OptionPtr optlist
, const char *name
, double deflt
)
275 return LookupRealOption(optlist
, name
, deflt
, FALSE
);
279 xf86CheckStrOption(XF86OptionPtr optlist
, const char *name
, const char *deflt
)
281 return LookupStrOption(optlist
, name
, deflt
, FALSE
);
285 xf86CheckBoolOption(XF86OptionPtr optlist
, const char *name
, int deflt
)
287 return LookupBoolOption(optlist
, name
, deflt
, FALSE
);
291 xf86CheckPercentOption(XF86OptionPtr optlist
, const char *name
, double deflt
)
293 return LookupPercentOption(optlist
, name
, deflt
, FALSE
);
297 * xf86AddNewOption() has the required property of replacing the option value
298 * if the option is already present.
301 xf86ReplaceIntOption(XF86OptionPtr optlist
, const char *name
, const int val
)
305 snprintf(tmp
, sizeof(tmp
), "%i", val
);
306 return xf86AddNewOption(optlist
, name
, tmp
);
310 xf86ReplaceRealOption(XF86OptionPtr optlist
, const char *name
, const double val
)
314 snprintf(tmp
, sizeof(tmp
), "%f", val
);
315 return xf86AddNewOption(optlist
, name
, tmp
);
319 xf86ReplaceBoolOption(XF86OptionPtr optlist
, const char *name
, const Bool val
)
321 return xf86AddNewOption(optlist
, name
, val
? "True" : "False");
325 xf86ReplacePercentOption(XF86OptionPtr optlist
, const char *name
,
330 snprintf(tmp
, sizeof(tmp
), "%lf%%", val
);
331 return xf86AddNewOption(optlist
, name
, tmp
);
335 xf86ReplaceStrOption(XF86OptionPtr optlist
, const char *name
, const char *val
)
337 return xf86AddNewOption(optlist
, name
, val
);
341 xf86AddNewOption(XF86OptionPtr head
, const char *name
, const char *val
)
343 /* XXX These should actually be allocated in the parser library. */
344 char *tmp
= val
? strdup(val
) : NULL
;
345 char *tmp_name
= strdup(name
);
347 return xf86addNewOption(head
, tmp_name
, tmp
);
351 xf86NewOption(char *name
, char *value
)
353 return xf86newOption(name
, value
);
357 xf86NextOption(XF86OptionPtr list
)
359 return xf86nextOption(list
);
363 xf86OptionListCreate(const char **options
, int count
, int used
)
365 return xf86optionListCreate(options
, count
, used
);
369 xf86OptionListMerge(XF86OptionPtr head
, XF86OptionPtr tail
)
371 return xf86optionListMerge(head
, tail
);
375 xf86OptionListFree(XF86OptionPtr opt
)
377 xf86optionListFree(opt
);
381 xf86OptionName(XF86OptionPtr opt
)
383 return xf86optionName(opt
);
387 xf86OptionValue(XF86OptionPtr opt
)
389 return xf86optionValue(opt
);
393 xf86OptionListReport(XF86OptionPtr parm
)
395 XF86OptionPtr opts
= parm
;
398 if (xf86optionValue(opts
))
399 xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n",
400 xf86optionName(opts
), xf86optionValue(opts
));
402 xf86ErrorFVerb(5, "\tOption \"%s\"\n", xf86optionName(opts
));
403 opts
= xf86nextOption(opts
);
407 /* End of XInput-caused section */
410 xf86FindOption(XF86OptionPtr options
, const char *name
)
412 return xf86findOption(options
, name
);
416 xf86FindOptionValue(XF86OptionPtr options
, const char *name
)
418 return xf86findOptionValue(options
, name
);
422 xf86MarkOptionUsed(XF86OptionPtr option
)
425 option
->opt_used
= TRUE
;
429 xf86MarkOptionUsedByName(XF86OptionPtr options
, const char *name
)
433 opt
= xf86findOption(options
, name
);
435 opt
->opt_used
= TRUE
;
439 xf86CheckIfOptionUsed(XF86OptionPtr option
)
442 return option
->opt_used
;
448 xf86CheckIfOptionUsedByName(XF86OptionPtr options
, const char *name
)
452 opt
= xf86findOption(options
, name
);
454 return opt
->opt_used
;
460 xf86ShowUnusedOptions(int scrnIndex
, XF86OptionPtr opt
)
463 if (opt
->opt_name
&& !opt
->opt_used
) {
464 xf86DrvMsg(scrnIndex
, X_WARNING
, "Option \"%s\" is not used\n",
467 opt
= opt
->list
.next
;
472 GetBoolValue(OptionInfoPtr p
, const char *s
)
474 return xf86getBoolValue(&p
->value
.bool, s
);
478 ParseOptionValue(int scrnIndex
, XF86OptionPtr options
, OptionInfoPtr p
,
482 Bool wasUsed
= FALSE
;
484 if ((s
= xf86findOptionValue(options
, p
->name
)) != NULL
) {
486 wasUsed
= xf86CheckIfOptionUsedByName(options
, p
->name
);
487 xf86MarkOptionUsedByName(options
, p
->name
);
493 xf86DrvMsg(scrnIndex
, X_WARNING
,
494 "Option \"%s\" requires an integer value\n",
500 p
->value
.num
= strtoul(s
, &end
, 0);
506 xf86DrvMsg(scrnIndex
, X_WARNING
,
507 "Option \"%s\" requires an integer value\n",
517 xf86DrvMsg(scrnIndex
, X_WARNING
,
518 "Option \"%s\" requires a string value\n",
535 xf86DrvMsg(scrnIndex
, X_WARNING
,
536 "Option \"%s\" requires a floating point "
542 p
->value
.realnum
= strtod(s
, &end
);
548 xf86DrvMsg(scrnIndex
, X_WARNING
,
549 "Option \"%s\" requires a floating point "
557 if (GetBoolValue(p
, s
)) {
562 xf86DrvMsg(scrnIndex
, X_WARNING
,
563 "Option \"%s\" requires a boolean value\n",
573 /* awkward match, but %% doesn't increase the match counter,
574 * hence 100 looks the same as 100% to the caller of sccanf
576 if (sscanf(s
, "%lf%c", &p
->value
.realnum
, &tmp
) != 2 || tmp
!= '%') {
578 xf86DrvMsg(scrnIndex
, X_WARNING
,
579 "Option \"%s\" requires a percent value\n",
592 xf86DrvMsg(scrnIndex
, X_WARNING
,
593 "Option \"%s\" requires a frequency value\n",
599 double freq
= strtod(s
, &end
);
604 if (!xf86NameCmp(end
, "Hz"))
606 else if (!xf86NameCmp(end
, "kHz") || !xf86NameCmp(end
, "k"))
608 else if (!xf86NameCmp(end
, "MHz") || !xf86NameCmp(end
, "M"))
612 xf86DrvMsg(scrnIndex
, X_WARNING
,
613 "Option \"%s\" requires a frequency value\n",
619 freq
*= (double) units
;
623 xf86DrvMsg(scrnIndex
, X_WARNING
,
624 "Option \"%s\" requires a frequency value\n",
630 p
->value
.freq
.freq
= freq
;
631 p
->value
.freq
.units
= units
;
636 /* Should never get here */
640 if (p
->found
&& markUsed
) {
645 xf86DrvMsgVerb(scrnIndex
, X_CONFIG
, verb
, "Option \"%s\"", p
->name
);
646 if (!(p
->type
== OPTV_BOOLEAN
&& *s
== 0)) {
647 xf86ErrorFVerb(verb
, " \"%s\"", s
);
649 xf86ErrorFVerb(verb
, "\n");
652 else if (p
->type
== OPTV_BOOLEAN
) {
653 /* Look for matches with options with or without a "No" prefix. */
657 n
= xf86NormalizeName(p
->name
);
662 if (strncmp(n
, "no", 2) == 0) {
667 if (asprintf(&n
, "No%s", p
->name
) == -1) {
673 if ((s
= xf86findOptionValue(options
, newn
)) != NULL
) {
675 xf86MarkOptionUsedByName(options
, newn
);
676 if (GetBoolValue(&opt
, s
)) {
677 p
->value
.bool = !opt
.value
.bool;
681 xf86DrvMsg(scrnIndex
, X_WARNING
,
682 "Option \"%s\" requires a boolean value\n", newn
);
689 if (p
->found
&& markUsed
) {
690 xf86DrvMsgVerb(scrnIndex
, X_CONFIG
, 2, "Option \"%s\"", newn
);
692 xf86ErrorFVerb(2, " \"%s\"", s
);
694 xf86ErrorFVerb(2, "\n");
705 xf86ProcessOptions(int scrnIndex
, XF86OptionPtr options
, OptionInfoPtr optinfo
)
709 for (p
= optinfo
; p
->name
!= NULL
; p
++) {
710 ParseOptionValue(scrnIndex
, options
, p
, TRUE
);
715 xf86TokenToOptinfo(const OptionInfoRec
* table
, int token
)
717 const OptionInfoRec
*p
, *match
= NULL
, *set
= NULL
;
720 ErrorF("xf86TokenToOptinfo: table is NULL\n");
724 for (p
= table
; p
->token
>= 0; p
++) {
725 if (p
->token
== token
) {
733 return (OptionInfoPtr
) set
;
735 return (OptionInfoPtr
) match
;
741 xf86TokenToOptName(const OptionInfoRec
* table
, int token
)
743 const OptionInfoRec
*p
;
745 p
= xf86TokenToOptinfo(table
, token
);
746 return p
? p
->name
: NULL
;
750 xf86IsOptionSet(const OptionInfoRec
* table
, int token
)
754 p
= xf86TokenToOptinfo(table
, token
);
755 return p
&& p
->found
;
759 xf86GetOptValString(const OptionInfoRec
* table
, int token
)
763 p
= xf86TokenToOptinfo(table
, token
);
771 xf86GetOptValInteger(const OptionInfoRec
* table
, int token
, int *value
)
775 p
= xf86TokenToOptinfo(table
, token
);
777 *value
= p
->value
.num
;
785 xf86GetOptValULong(const OptionInfoRec
* table
, int token
, unsigned long *value
)
789 p
= xf86TokenToOptinfo(table
, token
);
791 *value
= p
->value
.num
;
799 xf86GetOptValReal(const OptionInfoRec
* table
, int token
, double *value
)
803 p
= xf86TokenToOptinfo(table
, token
);
805 *value
= p
->value
.realnum
;
813 xf86GetOptValFreq(const OptionInfoRec
* table
, int token
,
814 OptFreqUnits expectedUnits
, double *value
)
818 p
= xf86TokenToOptinfo(table
, token
);
820 if (p
->value
.freq
.units
> 0) {
821 /* Units give, so the scaling is known. */
822 switch (expectedUnits
) {
824 *value
= p
->value
.freq
.freq
;
827 *value
= p
->value
.freq
.freq
/ 1000.0;
830 *value
= p
->value
.freq
.freq
/ 1000000.0;
835 /* No units given, so try to guess the scaling. */
836 switch (expectedUnits
) {
838 *value
= p
->value
.freq
.freq
;
841 if (p
->value
.freq
.freq
> 1000.0)
842 *value
= p
->value
.freq
.freq
/ 1000.0;
844 *value
= p
->value
.freq
.freq
;
847 if (p
->value
.freq
.freq
> 1000000.0)
848 *value
= p
->value
.freq
.freq
/ 1000000.0;
849 else if (p
->value
.freq
.freq
> 1000.0)
850 *value
= p
->value
.freq
.freq
/ 1000.0;
852 *value
= p
->value
.freq
.freq
;
862 xf86GetOptValBool(const OptionInfoRec
* table
, int token
, Bool
*value
)
866 p
= xf86TokenToOptinfo(table
, token
);
868 *value
= p
->value
.bool;
876 xf86ReturnOptValBool(const OptionInfoRec
* table
, int token
, Bool def
)
880 p
= xf86TokenToOptinfo(table
, token
);
882 return p
->value
.bool;
889 xf86NameCmp(const char *s1
, const char *s2
)
891 return xf86nameCompare(s1
, s2
);
895 xf86NormalizeName(const char *s
)
903 ret
= malloc(strlen(s
) + 1);
904 for (p
= s
, q
= ret
; *p
!= 0; p
++) {