105b261ecSmrg/*
205b261ecSmrg * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
305b261ecSmrg *
405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
505b261ecSmrg * copy of this software and associated documentation files (the "Software"),
605b261ecSmrg * to deal in the Software without restriction, including without limitation
705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
905b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1005b261ecSmrg *
1105b261ecSmrg * The above copyright notice and this permission notice shall be included in
1205b261ecSmrg * all copies or substantial portions of the Software.
1305b261ecSmrg *
1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1705b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg *
2205b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
2305b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
2405b261ecSmrg * the sale, use or other dealings in this Software without prior written
2505b261ecSmrg * authorization from the copyright holder(s) and author(s).
2605b261ecSmrg */
2705b261ecSmrg
2805b261ecSmrg/*
2905b261ecSmrg * Author: David Dawes <dawes@xfree86.org>
3005b261ecSmrg *
3105b261ecSmrg * This file includes public option handling functions.
3205b261ecSmrg */
3305b261ecSmrg
3405b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
3505b261ecSmrg#include <xorg-config.h>
3605b261ecSmrg#endif
3705b261ecSmrg
3805b261ecSmrg#include <stdlib.h>
3905b261ecSmrg#include <ctype.h>
4005b261ecSmrg#include <X11/X.h>
4105b261ecSmrg#include "os.h"
4205b261ecSmrg#include "xf86.h"
4335c4bbdfSmrg#include "xf86Opt.h"
4405b261ecSmrg#include "xf86Xinput.h"
4505b261ecSmrg#include "xf86Optrec.h"
466747b715Smrg#include "xf86Parser.h"
471b5d61b8Smrg#include "xf86platformBus.h" /* For OutputClass functions */
4835c4bbdfSmrg#include "optionstr.h"
4905b261ecSmrg
5035c4bbdfSmrgstatic Bool ParseOptionValue(int scrnIndex, XF86OptionPtr options,
5135c4bbdfSmrg                             OptionInfoPtr p, Bool markUsed);
5205b261ecSmrg
5305b261ecSmrg/*
5405b261ecSmrg * xf86CollectOptions collects the options from each of the config file
5505b261ecSmrg * sections used by the screen and puts the combined list in pScrn->options.
5605b261ecSmrg * This function requires that the following have been initialised:
5705b261ecSmrg *
5805b261ecSmrg *	pScrn->confScreen
5905b261ecSmrg *	pScrn->Entities[i]->device
6005b261ecSmrg *	pScrn->display
6105b261ecSmrg *	pScrn->monitor
6205b261ecSmrg *
6305b261ecSmrg * The extraOpts parameter may optionally contain a list of additional options
6405b261ecSmrg * to include.
6505b261ecSmrg *
6605b261ecSmrg * The order of precedence for options is:
6705b261ecSmrg *
681b5d61b8Smrg *   extraOpts, display, confScreen, monitor, device, outputClassOptions
6905b261ecSmrg */
7005b261ecSmrg
716747b715Smrgvoid
7235c4bbdfSmrgxf86CollectOptions(ScrnInfoPtr pScrn, XF86OptionPtr extraOpts)
7305b261ecSmrg{
7405b261ecSmrg    XF86OptionPtr tmp;
7535c4bbdfSmrg    XF86OptionPtr extras = (XF86OptionPtr) extraOpts;
7605b261ecSmrg    GDevPtr device;
7735c4bbdfSmrg
7805b261ecSmrg    int i;
7905b261ecSmrg
8005b261ecSmrg    pScrn->options = NULL;
8105b261ecSmrg
8235c4bbdfSmrg    for (i = pScrn->numEntities - 1; i >= 0; i--) {
831b5d61b8Smrg        xf86MergeOutputClassOptions(pScrn->entityList[i], &pScrn->options);
841b5d61b8Smrg
8535c4bbdfSmrg        device = xf86GetDevFromEntity(pScrn->entityList[i],
8635c4bbdfSmrg                                      pScrn->entityInstanceList[i]);
8735c4bbdfSmrg        if (device && device->options) {
8835c4bbdfSmrg            tmp = xf86optionListDup(device->options);
8935c4bbdfSmrg            if (pScrn->options)
901b5d61b8Smrg                pScrn->options = xf86optionListMerge(pScrn->options, tmp);
9135c4bbdfSmrg            else
9235c4bbdfSmrg                pScrn->options = tmp;
9335c4bbdfSmrg        }
9405b261ecSmrg    }
9505b261ecSmrg    if (pScrn->monitor->options) {
9635c4bbdfSmrg        tmp = xf86optionListDup(pScrn->monitor->options);
9735c4bbdfSmrg        if (pScrn->options)
9835c4bbdfSmrg            pScrn->options = xf86optionListMerge(pScrn->options, tmp);
9935c4bbdfSmrg        else
10035c4bbdfSmrg            pScrn->options = tmp;
10105b261ecSmrg    }
10205b261ecSmrg    if (pScrn->confScreen->options) {
10335c4bbdfSmrg        tmp = xf86optionListDup(pScrn->confScreen->options);
10435c4bbdfSmrg        if (pScrn->options)
10535c4bbdfSmrg            pScrn->options = xf86optionListMerge(pScrn->options, tmp);
10635c4bbdfSmrg        else
10735c4bbdfSmrg            pScrn->options = tmp;
10805b261ecSmrg    }
10905b261ecSmrg    if (pScrn->display->options) {
11035c4bbdfSmrg        tmp = xf86optionListDup(pScrn->display->options);
11135c4bbdfSmrg        if (pScrn->options)
11235c4bbdfSmrg            pScrn->options = xf86optionListMerge(pScrn->options, tmp);
11335c4bbdfSmrg        else
11435c4bbdfSmrg            pScrn->options = tmp;
11505b261ecSmrg    }
11605b261ecSmrg    if (extras) {
11735c4bbdfSmrg        tmp = xf86optionListDup(extras);
11835c4bbdfSmrg        if (pScrn->options)
11935c4bbdfSmrg            pScrn->options = xf86optionListMerge(pScrn->options, tmp);
12035c4bbdfSmrg        else
12135c4bbdfSmrg            pScrn->options = tmp;
12205b261ecSmrg    }
12305b261ecSmrg}
12405b261ecSmrg
12505b261ecSmrg/*
1269ace9065Smrg * xf86CollectInputOptions collects extra options for an InputDevice (other
1279ace9065Smrg * than those added by the config backend).
1289ace9065Smrg * The options are merged into the existing ones and thus take precedence
1299ace9065Smrg * over the others.
13005b261ecSmrg */
13105b261ecSmrg
1326747b715Smrgvoid
1339ace9065Smrgxf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts)
13405b261ecSmrg{
13505b261ecSmrg    if (defaultOpts) {
13635c4bbdfSmrg        XF86OptionPtr tmp = xf86optionListCreate(defaultOpts, -1, 0);
13735c4bbdfSmrg
13835c4bbdfSmrg        if (pInfo->options)
13935c4bbdfSmrg            pInfo->options = xf86optionListMerge(tmp, pInfo->options);
14035c4bbdfSmrg        else
14135c4bbdfSmrg            pInfo->options = tmp;
14205b261ecSmrg    }
1439ace9065Smrg}
1446747b715Smrg
1459ace9065Smrg/**
1469ace9065Smrg * Duplicate the option list passed in. The returned pointer will be a newly
1479ace9065Smrg * allocated option list and must be freed by the caller.
1489ace9065Smrg */
14935c4bbdfSmrgXF86OptionPtr
15035c4bbdfSmrgxf86OptionListDuplicate(XF86OptionPtr options)
1519ace9065Smrg{
15235c4bbdfSmrg    XF86OptionPtr o = NULL;
1539ace9065Smrg
15435c4bbdfSmrg    while (options) {
15535c4bbdfSmrg        o = xf86AddNewOption(o, xf86OptionName(options),
15635c4bbdfSmrg                             xf86OptionValue(options));
1579ace9065Smrg        options = xf86nextOption(options);
1586747b715Smrg    }
1599ace9065Smrg
1609ace9065Smrg    return o;
16105b261ecSmrg}
16205b261ecSmrg
16305b261ecSmrg/* Created for new XInput stuff -- essentially extensions to the parser	*/
16405b261ecSmrg
16505b261ecSmrgstatic int
16635c4bbdfSmrgLookupIntOption(XF86OptionPtr optlist, const char *name, int deflt,
16735c4bbdfSmrg                Bool markUsed)
16805b261ecSmrg{
16905b261ecSmrg    OptionInfoRec o;
17005b261ecSmrg
17105b261ecSmrg    o.name = name;
17205b261ecSmrg    o.type = OPTV_INTEGER;
17305b261ecSmrg    if (ParseOptionValue(-1, optlist, &o, markUsed))
17435c4bbdfSmrg        deflt = o.value.num;
17505b261ecSmrg    return deflt;
17605b261ecSmrg}
17705b261ecSmrg
17805b261ecSmrgstatic double
17935c4bbdfSmrgLookupRealOption(XF86OptionPtr optlist, const char *name, double deflt,
18035c4bbdfSmrg                 Bool markUsed)
18105b261ecSmrg{
18205b261ecSmrg    OptionInfoRec o;
18305b261ecSmrg
18405b261ecSmrg    o.name = name;
18505b261ecSmrg    o.type = OPTV_REAL;
18605b261ecSmrg    if (ParseOptionValue(-1, optlist, &o, markUsed))
18735c4bbdfSmrg        deflt = o.value.realnum;
18805b261ecSmrg    return deflt;
18905b261ecSmrg}
19005b261ecSmrg
19105b261ecSmrgstatic char *
19235c4bbdfSmrgLookupStrOption(XF86OptionPtr optlist, const char *name, const char *deflt,
19335c4bbdfSmrg                Bool markUsed)
19405b261ecSmrg{
19505b261ecSmrg    OptionInfoRec o;
19605b261ecSmrg
19705b261ecSmrg    o.name = name;
19805b261ecSmrg    o.type = OPTV_STRING;
19905b261ecSmrg    if (ParseOptionValue(-1, optlist, &o, markUsed))
20005b261ecSmrg        deflt = o.value.str;
20105b261ecSmrg    if (deflt)
20235c4bbdfSmrg        return strdup(deflt);
20305b261ecSmrg    else
20435c4bbdfSmrg        return NULL;
20505b261ecSmrg}
20605b261ecSmrg
20705b261ecSmrgstatic int
20835c4bbdfSmrgLookupBoolOption(XF86OptionPtr optlist, const char *name, int deflt,
20935c4bbdfSmrg                 Bool markUsed)
21005b261ecSmrg{
21105b261ecSmrg    OptionInfoRec o;
21205b261ecSmrg
21305b261ecSmrg    o.name = name;
21405b261ecSmrg    o.type = OPTV_BOOLEAN;
21505b261ecSmrg    if (ParseOptionValue(-1, optlist, &o, markUsed))
216ed6184dfSmrg        deflt = o.value.boolean;
21705b261ecSmrg    return deflt;
21805b261ecSmrg}
21905b261ecSmrg
2209ace9065Smrgstatic double
22135c4bbdfSmrgLookupPercentOption(XF86OptionPtr optlist, const char *name, double deflt,
22235c4bbdfSmrg                    Bool markUsed)
2236747b715Smrg{
2246747b715Smrg    OptionInfoRec o;
2256747b715Smrg
2266747b715Smrg    o.name = name;
2276747b715Smrg    o.type = OPTV_PERCENT;
2286747b715Smrg    if (ParseOptionValue(-1, optlist, &o, markUsed))
22935c4bbdfSmrg        deflt = o.value.realnum;
2306747b715Smrg    return deflt;
2316747b715Smrg}
2326747b715Smrg
23305b261ecSmrg/* These xf86Set* functions are intended for use by non-screen specific code */
23405b261ecSmrg
2356747b715Smrgint
23635c4bbdfSmrgxf86SetIntOption(XF86OptionPtr optlist, const char *name, int deflt)
23705b261ecSmrg{
23805b261ecSmrg    return LookupIntOption(optlist, name, deflt, TRUE);
23905b261ecSmrg}
24005b261ecSmrg
2416747b715Smrgdouble
24235c4bbdfSmrgxf86SetRealOption(XF86OptionPtr optlist, const char *name, double deflt)
24305b261ecSmrg{
24405b261ecSmrg    return LookupRealOption(optlist, name, deflt, TRUE);
24505b261ecSmrg}
24605b261ecSmrg
2476747b715Smrgchar *
24835c4bbdfSmrgxf86SetStrOption(XF86OptionPtr optlist, const char *name, const char *deflt)
24905b261ecSmrg{
25005b261ecSmrg    return LookupStrOption(optlist, name, deflt, TRUE);
25105b261ecSmrg}
25205b261ecSmrg
2536747b715Smrgint
25435c4bbdfSmrgxf86SetBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
25505b261ecSmrg{
25605b261ecSmrg    return LookupBoolOption(optlist, name, deflt, TRUE);
25705b261ecSmrg}
25805b261ecSmrg
2596747b715Smrgdouble
26035c4bbdfSmrgxf86SetPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
2616747b715Smrg{
2626747b715Smrg    return LookupPercentOption(optlist, name, deflt, TRUE);
2636747b715Smrg}
2646747b715Smrg
26505b261ecSmrg/*
26605b261ecSmrg * These are like the Set*Option functions, but they don't mark the options
26705b261ecSmrg * as used.
26805b261ecSmrg */
2696747b715Smrgint
27035c4bbdfSmrgxf86CheckIntOption(XF86OptionPtr optlist, const char *name, int deflt)
27105b261ecSmrg{
27205b261ecSmrg    return LookupIntOption(optlist, name, deflt, FALSE);
27305b261ecSmrg}
27405b261ecSmrg
2756747b715Smrgdouble
27635c4bbdfSmrgxf86CheckRealOption(XF86OptionPtr optlist, const char *name, double deflt)
27705b261ecSmrg{
27805b261ecSmrg    return LookupRealOption(optlist, name, deflt, FALSE);
27905b261ecSmrg}
28005b261ecSmrg
2816747b715Smrgchar *
28235c4bbdfSmrgxf86CheckStrOption(XF86OptionPtr optlist, const char *name, const char *deflt)
28305b261ecSmrg{
28405b261ecSmrg    return LookupStrOption(optlist, name, deflt, FALSE);
28505b261ecSmrg}
28605b261ecSmrg
2876747b715Smrgint
28835c4bbdfSmrgxf86CheckBoolOption(XF86OptionPtr optlist, const char *name, int deflt)
28905b261ecSmrg{
29005b261ecSmrg    return LookupBoolOption(optlist, name, deflt, FALSE);
29105b261ecSmrg}
29205b261ecSmrg
2936747b715Smrgdouble
29435c4bbdfSmrgxf86CheckPercentOption(XF86OptionPtr optlist, const char *name, double deflt)
2956747b715Smrg{
2966747b715Smrg    return LookupPercentOption(optlist, name, deflt, FALSE);
2976747b715Smrg}
29835c4bbdfSmrg
29905b261ecSmrg/*
30035c4bbdfSmrg * xf86AddNewOption() has the required property of replacing the option value
30105b261ecSmrg * if the option is already present.
30205b261ecSmrg */
30335c4bbdfSmrgXF86OptionPtr
30435c4bbdfSmrgxf86ReplaceIntOption(XF86OptionPtr optlist, const char *name, const int val)
30505b261ecSmrg{
30605b261ecSmrg    char tmp[16];
30735c4bbdfSmrg
30835c4bbdfSmrg    snprintf(tmp, sizeof(tmp), "%i", val);
30935c4bbdfSmrg    return xf86AddNewOption(optlist, name, tmp);
31005b261ecSmrg}
31105b261ecSmrg
31235c4bbdfSmrgXF86OptionPtr
31335c4bbdfSmrgxf86ReplaceRealOption(XF86OptionPtr optlist, const char *name, const double val)
31405b261ecSmrg{
31505b261ecSmrg    char tmp[32];
31635c4bbdfSmrg
31735c4bbdfSmrg    snprintf(tmp, sizeof(tmp), "%f", val);
31835c4bbdfSmrg    return xf86AddNewOption(optlist, name, tmp);
31905b261ecSmrg}
32005b261ecSmrg
32135c4bbdfSmrgXF86OptionPtr
32235c4bbdfSmrgxf86ReplaceBoolOption(XF86OptionPtr optlist, const char *name, const Bool val)
32305b261ecSmrg{
32435c4bbdfSmrg    return xf86AddNewOption(optlist, name, val ? "True" : "False");
32505b261ecSmrg}
32605b261ecSmrg
32735c4bbdfSmrgXF86OptionPtr
32835c4bbdfSmrgxf86ReplacePercentOption(XF86OptionPtr optlist, const char *name,
32935c4bbdfSmrg                         const double val)
3306747b715Smrg{
3316747b715Smrg    char tmp[16];
33235c4bbdfSmrg
33335c4bbdfSmrg    snprintf(tmp, sizeof(tmp), "%lf%%", val);
33435c4bbdfSmrg    return xf86AddNewOption(optlist, name, tmp);
3356747b715Smrg}
3366747b715Smrg
33735c4bbdfSmrgXF86OptionPtr
33835c4bbdfSmrgxf86ReplaceStrOption(XF86OptionPtr optlist, const char *name, const char *val)
33905b261ecSmrg{
34035c4bbdfSmrg    return xf86AddNewOption(optlist, name, val);
34105b261ecSmrg}
34205b261ecSmrg
34335c4bbdfSmrgXF86OptionPtr
34435c4bbdfSmrgxf86AddNewOption(XF86OptionPtr head, const char *name, const char *val)
34505b261ecSmrg{
34605b261ecSmrg    /* XXX These should actually be allocated in the parser library. */
347475c125cSmrg    char *tmp = val ? strdup(val) : NULL;
34805b261ecSmrg    char *tmp_name = strdup(name);
34905b261ecSmrg
35005b261ecSmrg    return xf86addNewOption(head, tmp_name, tmp);
35105b261ecSmrg}
35205b261ecSmrg
35335c4bbdfSmrgXF86OptionPtr
35405b261ecSmrgxf86NewOption(char *name, char *value)
35505b261ecSmrg{
35605b261ecSmrg    return xf86newOption(name, value);
35705b261ecSmrg}
35805b261ecSmrg
35935c4bbdfSmrgXF86OptionPtr
36035c4bbdfSmrgxf86NextOption(XF86OptionPtr list)
36105b261ecSmrg{
36205b261ecSmrg    return xf86nextOption(list);
36305b261ecSmrg}
36405b261ecSmrg
36535c4bbdfSmrgXF86OptionPtr
36605b261ecSmrgxf86OptionListCreate(const char **options, int count, int used)
36705b261ecSmrg{
36835c4bbdfSmrg    return xf86optionListCreate(options, count, used);
36905b261ecSmrg}
37005b261ecSmrg
37135c4bbdfSmrgXF86OptionPtr
37235c4bbdfSmrgxf86OptionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
37305b261ecSmrg{
37435c4bbdfSmrg    return xf86optionListMerge(head, tail);
37505b261ecSmrg}
37605b261ecSmrg
3776747b715Smrgvoid
37835c4bbdfSmrgxf86OptionListFree(XF86OptionPtr opt)
37905b261ecSmrg{
38035c4bbdfSmrg    xf86optionListFree(opt);
38105b261ecSmrg}
38205b261ecSmrg
3836747b715Smrgchar *
38435c4bbdfSmrgxf86OptionName(XF86OptionPtr opt)
38505b261ecSmrg{
38635c4bbdfSmrg    return xf86optionName(opt);
38705b261ecSmrg}
38805b261ecSmrg
3896747b715Smrgchar *
39035c4bbdfSmrgxf86OptionValue(XF86OptionPtr opt)
39105b261ecSmrg{
39235c4bbdfSmrg    return xf86optionValue(opt);
39305b261ecSmrg}
39405b261ecSmrg
3956747b715Smrgvoid
39635c4bbdfSmrgxf86OptionListReport(XF86OptionPtr parm)
39705b261ecSmrg{
39805b261ecSmrg    XF86OptionPtr opts = parm;
39905b261ecSmrg
40035c4bbdfSmrg    while (opts) {
40135c4bbdfSmrg        if (xf86optionValue(opts))
40235c4bbdfSmrg            xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n",
40335c4bbdfSmrg                           xf86optionName(opts), xf86optionValue(opts));
40435c4bbdfSmrg        else
40535c4bbdfSmrg            xf86ErrorFVerb(5, "\tOption \"%s\"\n", xf86optionName(opts));
40635c4bbdfSmrg        opts = xf86nextOption(opts);
40705b261ecSmrg    }
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrg/* End of XInput-caused section	*/
41105b261ecSmrg
41235c4bbdfSmrgXF86OptionPtr
41335c4bbdfSmrgxf86FindOption(XF86OptionPtr options, const char *name)
41405b261ecSmrg{
41505b261ecSmrg    return xf86findOption(options, name);
41605b261ecSmrg}
41705b261ecSmrg
41835c4bbdfSmrgconst char *
41935c4bbdfSmrgxf86FindOptionValue(XF86OptionPtr options, const char *name)
42005b261ecSmrg{
42105b261ecSmrg    return xf86findOptionValue(options, name);
42205b261ecSmrg}
42305b261ecSmrg
4246747b715Smrgvoid
42535c4bbdfSmrgxf86MarkOptionUsed(XF86OptionPtr option)
42605b261ecSmrg{
42705b261ecSmrg    if (option != NULL)
42835c4bbdfSmrg        option->opt_used = TRUE;
42905b261ecSmrg}
43005b261ecSmrg
4316747b715Smrgvoid
43235c4bbdfSmrgxf86MarkOptionUsedByName(XF86OptionPtr options, const char *name)
43305b261ecSmrg{
43405b261ecSmrg    XF86OptionPtr opt;
43505b261ecSmrg
43605b261ecSmrg    opt = xf86findOption(options, name);
43705b261ecSmrg    if (opt != NULL)
43835c4bbdfSmrg        opt->opt_used = TRUE;
43905b261ecSmrg}
44005b261ecSmrg
4416747b715SmrgBool
44235c4bbdfSmrgxf86CheckIfOptionUsed(XF86OptionPtr option)
44305b261ecSmrg{
44405b261ecSmrg    if (option != NULL)
44535c4bbdfSmrg        return option->opt_used;
44605b261ecSmrg    else
44735c4bbdfSmrg        return FALSE;
44805b261ecSmrg}
44905b261ecSmrg
4506747b715SmrgBool
45135c4bbdfSmrgxf86CheckIfOptionUsedByName(XF86OptionPtr options, const char *name)
45205b261ecSmrg{
45305b261ecSmrg    XF86OptionPtr opt;
45405b261ecSmrg
45505b261ecSmrg    opt = xf86findOption(options, name);
45605b261ecSmrg    if (opt != NULL)
45735c4bbdfSmrg        return opt->opt_used;
45805b261ecSmrg    else
45935c4bbdfSmrg        return FALSE;
46005b261ecSmrg}
46105b261ecSmrg
4626747b715Smrgvoid
46335c4bbdfSmrgxf86ShowUnusedOptions(int scrnIndex, XF86OptionPtr opt)
46405b261ecSmrg{
46505b261ecSmrg    while (opt) {
46635c4bbdfSmrg        if (opt->opt_name && !opt->opt_used) {
46735c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n",
46835c4bbdfSmrg                       opt->opt_name);
46935c4bbdfSmrg        }
47035c4bbdfSmrg        opt = opt->list.next;
47105b261ecSmrg    }
47205b261ecSmrg}
47305b261ecSmrg
47405b261ecSmrgstatic Bool
47505b261ecSmrgGetBoolValue(OptionInfoPtr p, const char *s)
47605b261ecSmrg{
477ed6184dfSmrg    return xf86getBoolValue(&p->value.boolean, s);
47805b261ecSmrg}
47905b261ecSmrg
48005b261ecSmrgstatic Bool
48135c4bbdfSmrgParseOptionValue(int scrnIndex, XF86OptionPtr options, OptionInfoPtr p,
48235c4bbdfSmrg                 Bool markUsed)
48305b261ecSmrg{
48435c4bbdfSmrg    const char *s;
48535c4bbdfSmrg    char *end;
48605b261ecSmrg    Bool wasUsed = FALSE;
48705b261ecSmrg
48805b261ecSmrg    if ((s = xf86findOptionValue(options, p->name)) != NULL) {
48935c4bbdfSmrg        if (markUsed) {
49035c4bbdfSmrg            wasUsed = xf86CheckIfOptionUsedByName(options, p->name);
49135c4bbdfSmrg            xf86MarkOptionUsedByName(options, p->name);
49235c4bbdfSmrg        }
49335c4bbdfSmrg        switch (p->type) {
49435c4bbdfSmrg        case OPTV_INTEGER:
49535c4bbdfSmrg            if (*s == '\0') {
49635c4bbdfSmrg                if (markUsed) {
49735c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
49835c4bbdfSmrg                               "Option \"%s\" requires an integer value\n",
49935c4bbdfSmrg                               p->name);
50035c4bbdfSmrg                }
50135c4bbdfSmrg                p->found = FALSE;
50235c4bbdfSmrg            }
50335c4bbdfSmrg            else {
50435c4bbdfSmrg                p->value.num = strtoul(s, &end, 0);
50535c4bbdfSmrg                if (*end == '\0') {
50635c4bbdfSmrg                    p->found = TRUE;
50735c4bbdfSmrg                }
50835c4bbdfSmrg                else {
50935c4bbdfSmrg                    if (markUsed) {
51035c4bbdfSmrg                        xf86DrvMsg(scrnIndex, X_WARNING,
51135c4bbdfSmrg                                   "Option \"%s\" requires an integer value\n",
51235c4bbdfSmrg                                   p->name);
51335c4bbdfSmrg                    }
51435c4bbdfSmrg                    p->found = FALSE;
51535c4bbdfSmrg                }
51635c4bbdfSmrg            }
51735c4bbdfSmrg            break;
51835c4bbdfSmrg        case OPTV_STRING:
51935c4bbdfSmrg            if (*s == '\0') {
52035c4bbdfSmrg                if (markUsed) {
52135c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
52235c4bbdfSmrg                               "Option \"%s\" requires a string value\n",
52335c4bbdfSmrg                               p->name);
52435c4bbdfSmrg                }
52535c4bbdfSmrg                p->found = FALSE;
52635c4bbdfSmrg            }
52735c4bbdfSmrg            else {
52835c4bbdfSmrg                p->value.str = s;
52935c4bbdfSmrg                p->found = TRUE;
53035c4bbdfSmrg            }
53135c4bbdfSmrg            break;
53235c4bbdfSmrg        case OPTV_ANYSTR:
53335c4bbdfSmrg            p->value.str = s;
53435c4bbdfSmrg            p->found = TRUE;
53535c4bbdfSmrg            break;
53635c4bbdfSmrg        case OPTV_REAL:
53735c4bbdfSmrg            if (*s == '\0') {
53835c4bbdfSmrg                if (markUsed) {
53935c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
54035c4bbdfSmrg                               "Option \"%s\" requires a floating point "
54135c4bbdfSmrg                               "value\n", p->name);
54235c4bbdfSmrg                }
54335c4bbdfSmrg                p->found = FALSE;
54435c4bbdfSmrg            }
54535c4bbdfSmrg            else {
54635c4bbdfSmrg                p->value.realnum = strtod(s, &end);
54735c4bbdfSmrg                if (*end == '\0') {
54835c4bbdfSmrg                    p->found = TRUE;
54935c4bbdfSmrg                }
55035c4bbdfSmrg                else {
55135c4bbdfSmrg                    if (markUsed) {
55235c4bbdfSmrg                        xf86DrvMsg(scrnIndex, X_WARNING,
55335c4bbdfSmrg                                   "Option \"%s\" requires a floating point "
55435c4bbdfSmrg                                   "value\n", p->name);
55535c4bbdfSmrg                    }
55635c4bbdfSmrg                    p->found = FALSE;
55735c4bbdfSmrg                }
55835c4bbdfSmrg            }
55935c4bbdfSmrg            break;
56035c4bbdfSmrg        case OPTV_BOOLEAN:
56135c4bbdfSmrg            if (GetBoolValue(p, s)) {
56235c4bbdfSmrg                p->found = TRUE;
56335c4bbdfSmrg            }
56435c4bbdfSmrg            else {
56535c4bbdfSmrg                if (markUsed) {
56635c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
56735c4bbdfSmrg                               "Option \"%s\" requires a boolean value\n",
56835c4bbdfSmrg                               p->name);
56935c4bbdfSmrg                }
57035c4bbdfSmrg                p->found = FALSE;
57135c4bbdfSmrg            }
57235c4bbdfSmrg            break;
57335c4bbdfSmrg        case OPTV_PERCENT:
57435c4bbdfSmrg        {
57535c4bbdfSmrg            char tmp = 0;
57635c4bbdfSmrg
57735c4bbdfSmrg            /* awkward match, but %% doesn't increase the match counter,
57835c4bbdfSmrg             * hence 100 looks the same as 100% to the caller of sccanf
57935c4bbdfSmrg             */
58035c4bbdfSmrg            if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') {
58135c4bbdfSmrg                if (markUsed) {
58235c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
58335c4bbdfSmrg                               "Option \"%s\" requires a percent value\n",
58435c4bbdfSmrg                               p->name);
58535c4bbdfSmrg                }
58635c4bbdfSmrg                p->found = FALSE;
58735c4bbdfSmrg            }
58835c4bbdfSmrg            else {
58935c4bbdfSmrg                p->found = TRUE;
59035c4bbdfSmrg            }
59135c4bbdfSmrg        }
59235c4bbdfSmrg            break;
59335c4bbdfSmrg        case OPTV_FREQ:
59435c4bbdfSmrg            if (*s == '\0') {
59535c4bbdfSmrg                if (markUsed) {
59635c4bbdfSmrg                    xf86DrvMsg(scrnIndex, X_WARNING,
59735c4bbdfSmrg                               "Option \"%s\" requires a frequency value\n",
59835c4bbdfSmrg                               p->name);
59935c4bbdfSmrg                }
60035c4bbdfSmrg                p->found = FALSE;
60135c4bbdfSmrg            }
60235c4bbdfSmrg            else {
60335c4bbdfSmrg                double freq = strtod(s, &end);
60435c4bbdfSmrg                int units = 0;
60535c4bbdfSmrg
60635c4bbdfSmrg                if (end != s) {
60735c4bbdfSmrg                    p->found = TRUE;
60835c4bbdfSmrg                    if (!xf86NameCmp(end, "Hz"))
60935c4bbdfSmrg                        units = 1;
61035c4bbdfSmrg                    else if (!xf86NameCmp(end, "kHz") || !xf86NameCmp(end, "k"))
61135c4bbdfSmrg                        units = 1000;
61235c4bbdfSmrg                    else if (!xf86NameCmp(end, "MHz") || !xf86NameCmp(end, "M"))
61335c4bbdfSmrg                        units = 1000000;
61435c4bbdfSmrg                    else {
61535c4bbdfSmrg                        if (markUsed) {
61635c4bbdfSmrg                            xf86DrvMsg(scrnIndex, X_WARNING,
61735c4bbdfSmrg                                       "Option \"%s\" requires a frequency value\n",
61835c4bbdfSmrg                                       p->name);
61935c4bbdfSmrg                        }
62035c4bbdfSmrg                        p->found = FALSE;
62135c4bbdfSmrg                    }
62235c4bbdfSmrg                    if (p->found)
62335c4bbdfSmrg                        freq *= (double) units;
62435c4bbdfSmrg                }
62535c4bbdfSmrg                else {
62635c4bbdfSmrg                    if (markUsed) {
62735c4bbdfSmrg                        xf86DrvMsg(scrnIndex, X_WARNING,
62835c4bbdfSmrg                                   "Option \"%s\" requires a frequency value\n",
62935c4bbdfSmrg                                   p->name);
63035c4bbdfSmrg                    }
63135c4bbdfSmrg                    p->found = FALSE;
63235c4bbdfSmrg                }
63335c4bbdfSmrg                if (p->found) {
63435c4bbdfSmrg                    p->value.freq.freq = freq;
63535c4bbdfSmrg                    p->value.freq.units = units;
63635c4bbdfSmrg                }
63735c4bbdfSmrg            }
63835c4bbdfSmrg            break;
63935c4bbdfSmrg        case OPTV_NONE:
64035c4bbdfSmrg            /* Should never get here */
64135c4bbdfSmrg            p->found = FALSE;
64235c4bbdfSmrg            break;
64335c4bbdfSmrg        }
64435c4bbdfSmrg        if (p->found && markUsed) {
64535c4bbdfSmrg            int verb = 2;
64635c4bbdfSmrg
64735c4bbdfSmrg            if (wasUsed)
64835c4bbdfSmrg                verb = 4;
64935c4bbdfSmrg            xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name);
65035c4bbdfSmrg            if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
65135c4bbdfSmrg                xf86ErrorFVerb(verb, " \"%s\"", s);
65235c4bbdfSmrg            }
65335c4bbdfSmrg            xf86ErrorFVerb(verb, "\n");
65435c4bbdfSmrg        }
65535c4bbdfSmrg    }
65635c4bbdfSmrg    else if (p->type == OPTV_BOOLEAN) {
65735c4bbdfSmrg        /* Look for matches with options with or without a "No" prefix. */
65835c4bbdfSmrg        char *n, *newn;
65935c4bbdfSmrg        OptionInfoRec opt;
66035c4bbdfSmrg
66135c4bbdfSmrg        n = xf86NormalizeName(p->name);
66235c4bbdfSmrg        if (!n) {
66335c4bbdfSmrg            p->found = FALSE;
66435c4bbdfSmrg            return FALSE;
66535c4bbdfSmrg        }
66635c4bbdfSmrg        if (strncmp(n, "no", 2) == 0) {
66735c4bbdfSmrg            newn = n + 2;
66835c4bbdfSmrg        }
66935c4bbdfSmrg        else {
67035c4bbdfSmrg            free(n);
67135c4bbdfSmrg            if (asprintf(&n, "No%s", p->name) == -1) {
67235c4bbdfSmrg                p->found = FALSE;
67335c4bbdfSmrg                return FALSE;
67435c4bbdfSmrg            }
67535c4bbdfSmrg            newn = n;
67635c4bbdfSmrg        }
67735c4bbdfSmrg        if ((s = xf86findOptionValue(options, newn)) != NULL) {
67835c4bbdfSmrg            if (markUsed)
67935c4bbdfSmrg                xf86MarkOptionUsedByName(options, newn);
68035c4bbdfSmrg            if (GetBoolValue(&opt, s)) {
681ed6184dfSmrg                p->value.boolean = !opt.value.boolean;
68235c4bbdfSmrg                p->found = TRUE;
68335c4bbdfSmrg            }
68435c4bbdfSmrg            else {
68535c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_WARNING,
68635c4bbdfSmrg                           "Option \"%s\" requires a boolean value\n", newn);
68735c4bbdfSmrg                p->found = FALSE;
68835c4bbdfSmrg            }
68935c4bbdfSmrg        }
69035c4bbdfSmrg        else {
69135c4bbdfSmrg            p->found = FALSE;
69235c4bbdfSmrg        }
69335c4bbdfSmrg        if (p->found && markUsed) {
69435c4bbdfSmrg            xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
69535c4bbdfSmrg            if (*s != 0) {
69635c4bbdfSmrg                xf86ErrorFVerb(2, " \"%s\"", s);
69735c4bbdfSmrg            }
69835c4bbdfSmrg            xf86ErrorFVerb(2, "\n");
69935c4bbdfSmrg        }
70035c4bbdfSmrg        free(n);
70135c4bbdfSmrg    }
70235c4bbdfSmrg    else {
70335c4bbdfSmrg        p->found = FALSE;
70405b261ecSmrg    }
70505b261ecSmrg    return p->found;
70605b261ecSmrg}
70705b261ecSmrg
7086747b715Smrgvoid
70935c4bbdfSmrgxf86ProcessOptions(int scrnIndex, XF86OptionPtr options, OptionInfoPtr optinfo)
71005b261ecSmrg{
71105b261ecSmrg    OptionInfoPtr p;
71205b261ecSmrg
71305b261ecSmrg    for (p = optinfo; p->name != NULL; p++) {
71435c4bbdfSmrg        ParseOptionValue(scrnIndex, options, p, TRUE);
71505b261ecSmrg    }
71605b261ecSmrg}
71705b261ecSmrg
7186747b715SmrgOptionInfoPtr
71935c4bbdfSmrgxf86TokenToOptinfo(const OptionInfoRec * table, int token)
72005b261ecSmrg{
72105b261ecSmrg    const OptionInfoRec *p, *match = NULL, *set = NULL;
72205b261ecSmrg
72305b261ecSmrg    if (!table) {
72435c4bbdfSmrg        ErrorF("xf86TokenToOptinfo: table is NULL\n");
72535c4bbdfSmrg        return NULL;
72605b261ecSmrg    }
72705b261ecSmrg
72805b261ecSmrg    for (p = table; p->token >= 0; p++) {
72935c4bbdfSmrg        if (p->token == token) {
73035c4bbdfSmrg            match = p;
73135c4bbdfSmrg            if (p->found)
73235c4bbdfSmrg                set = p;
73335c4bbdfSmrg        }
73405b261ecSmrg    }
73505b261ecSmrg
73605b261ecSmrg    if (set)
73735c4bbdfSmrg        return (OptionInfoPtr) set;
73805b261ecSmrg    else if (match)
73935c4bbdfSmrg        return (OptionInfoPtr) match;
74005b261ecSmrg    else
74135c4bbdfSmrg        return NULL;
74205b261ecSmrg}
74305b261ecSmrg
7446747b715Smrgconst char *
74535c4bbdfSmrgxf86TokenToOptName(const OptionInfoRec * table, int token)
74605b261ecSmrg{
74705b261ecSmrg    const OptionInfoRec *p;
74805b261ecSmrg
74905b261ecSmrg    p = xf86TokenToOptinfo(table, token);
75035c4bbdfSmrg    return p ? p->name : NULL;
75105b261ecSmrg}
75205b261ecSmrg
7536747b715SmrgBool
75435c4bbdfSmrgxf86IsOptionSet(const OptionInfoRec * table, int token)
75505b261ecSmrg{
75605b261ecSmrg    OptionInfoPtr p;
75705b261ecSmrg
75805b261ecSmrg    p = xf86TokenToOptinfo(table, token);
7596747b715Smrg    return p && p->found;
76005b261ecSmrg}
76105b261ecSmrg
76235c4bbdfSmrgconst char *
76335c4bbdfSmrgxf86GetOptValString(const OptionInfoRec * table, int token)
76405b261ecSmrg{
76505b261ecSmrg    OptionInfoPtr p;
76605b261ecSmrg
76705b261ecSmrg    p = xf86TokenToOptinfo(table, token);
76805b261ecSmrg    if (p && p->found)
76935c4bbdfSmrg        return p->value.str;
77005b261ecSmrg    else
77135c4bbdfSmrg        return NULL;
77205b261ecSmrg}
77305b261ecSmrg
7746747b715SmrgBool
77535c4bbdfSmrgxf86GetOptValInteger(const OptionInfoRec * table, int token, int *value)
77605b261ecSmrg{
77705b261ecSmrg    OptionInfoPtr p;
77805b261ecSmrg
77905b261ecSmrg    p = xf86TokenToOptinfo(table, token);
78005b261ecSmrg    if (p && p->found) {
78135c4bbdfSmrg        *value = p->value.num;
78235c4bbdfSmrg        return TRUE;
78335c4bbdfSmrg    }
78435c4bbdfSmrg    else
78535c4bbdfSmrg        return FALSE;
78605b261ecSmrg}
78705b261ecSmrg
7886747b715SmrgBool
78935c4bbdfSmrgxf86GetOptValULong(const OptionInfoRec * table, int token, unsigned long *value)
79005b261ecSmrg{
79105b261ecSmrg    OptionInfoPtr p;
79205b261ecSmrg
79305b261ecSmrg    p = xf86TokenToOptinfo(table, token);
79405b261ecSmrg    if (p && p->found) {
79535c4bbdfSmrg        *value = p->value.num;
79635c4bbdfSmrg        return TRUE;
79735c4bbdfSmrg    }
79835c4bbdfSmrg    else
79935c4bbdfSmrg        return FALSE;
80005b261ecSmrg}
80105b261ecSmrg
8026747b715SmrgBool
80335c4bbdfSmrgxf86GetOptValReal(const OptionInfoRec * table, int token, double *value)
80405b261ecSmrg{
80505b261ecSmrg    OptionInfoPtr p;
80605b261ecSmrg
80705b261ecSmrg    p = xf86TokenToOptinfo(table, token);
80805b261ecSmrg    if (p && p->found) {
80935c4bbdfSmrg        *value = p->value.realnum;
81035c4bbdfSmrg        return TRUE;
81135c4bbdfSmrg    }
81235c4bbdfSmrg    else
81335c4bbdfSmrg        return FALSE;
81405b261ecSmrg}
81505b261ecSmrg
8166747b715SmrgBool
81735c4bbdfSmrgxf86GetOptValFreq(const OptionInfoRec * table, int token,
81835c4bbdfSmrg                  OptFreqUnits expectedUnits, double *value)
81905b261ecSmrg{
82005b261ecSmrg    OptionInfoPtr p;
82105b261ecSmrg
82205b261ecSmrg    p = xf86TokenToOptinfo(table, token);
82305b261ecSmrg    if (p && p->found) {
82435c4bbdfSmrg        if (p->value.freq.units > 0) {
82535c4bbdfSmrg            /* Units give, so the scaling is known. */
82635c4bbdfSmrg            switch (expectedUnits) {
82735c4bbdfSmrg            case OPTUNITS_HZ:
82835c4bbdfSmrg                *value = p->value.freq.freq;
82935c4bbdfSmrg                break;
83035c4bbdfSmrg            case OPTUNITS_KHZ:
83135c4bbdfSmrg                *value = p->value.freq.freq / 1000.0;
83235c4bbdfSmrg                break;
83335c4bbdfSmrg            case OPTUNITS_MHZ:
83435c4bbdfSmrg                *value = p->value.freq.freq / 1000000.0;
83535c4bbdfSmrg                break;
83635c4bbdfSmrg            }
83735c4bbdfSmrg        }
83835c4bbdfSmrg        else {
83935c4bbdfSmrg            /* No units given, so try to guess the scaling. */
84035c4bbdfSmrg            switch (expectedUnits) {
84135c4bbdfSmrg            case OPTUNITS_HZ:
84235c4bbdfSmrg                *value = p->value.freq.freq;
84335c4bbdfSmrg                break;
84435c4bbdfSmrg            case OPTUNITS_KHZ:
84535c4bbdfSmrg                if (p->value.freq.freq > 1000.0)
84635c4bbdfSmrg                    *value = p->value.freq.freq / 1000.0;
84735c4bbdfSmrg                else
84835c4bbdfSmrg                    *value = p->value.freq.freq;
84935c4bbdfSmrg                break;
85035c4bbdfSmrg            case OPTUNITS_MHZ:
85135c4bbdfSmrg                if (p->value.freq.freq > 1000000.0)
85235c4bbdfSmrg                    *value = p->value.freq.freq / 1000000.0;
85335c4bbdfSmrg                else if (p->value.freq.freq > 1000.0)
85435c4bbdfSmrg                    *value = p->value.freq.freq / 1000.0;
85535c4bbdfSmrg                else
85635c4bbdfSmrg                    *value = p->value.freq.freq;
85735c4bbdfSmrg            }
85835c4bbdfSmrg        }
85935c4bbdfSmrg        return TRUE;
86035c4bbdfSmrg    }
86135c4bbdfSmrg    else
86235c4bbdfSmrg        return FALSE;
86305b261ecSmrg}
86405b261ecSmrg
8656747b715SmrgBool
86635c4bbdfSmrgxf86GetOptValBool(const OptionInfoRec * table, int token, Bool *value)
86705b261ecSmrg{
86805b261ecSmrg    OptionInfoPtr p;
86905b261ecSmrg
87005b261ecSmrg    p = xf86TokenToOptinfo(table, token);
87105b261ecSmrg    if (p && p->found) {
872ed6184dfSmrg        *value = p->value.boolean;
87335c4bbdfSmrg        return TRUE;
87435c4bbdfSmrg    }
87535c4bbdfSmrg    else
87635c4bbdfSmrg        return FALSE;
87705b261ecSmrg}
87805b261ecSmrg
8796747b715SmrgBool
88035c4bbdfSmrgxf86ReturnOptValBool(const OptionInfoRec * table, int token, Bool def)
88105b261ecSmrg{
88205b261ecSmrg    OptionInfoPtr p;
88305b261ecSmrg
88405b261ecSmrg    p = xf86TokenToOptinfo(table, token);
88505b261ecSmrg    if (p && p->found) {
886ed6184dfSmrg        return p->value.boolean;
88735c4bbdfSmrg    }
88835c4bbdfSmrg    else
88935c4bbdfSmrg        return def;
89005b261ecSmrg}
89105b261ecSmrg
8926747b715Smrgint
89305b261ecSmrgxf86NameCmp(const char *s1, const char *s2)
89405b261ecSmrg{
89505b261ecSmrg    return xf86nameCompare(s1, s2);
89605b261ecSmrg}
89705b261ecSmrg
89805b261ecSmrgchar *
89905b261ecSmrgxf86NormalizeName(const char *s)
90005b261ecSmrg{
90105b261ecSmrg    char *ret, *q;
90205b261ecSmrg    const char *p;
90305b261ecSmrg
90405b261ecSmrg    if (s == NULL)
90535c4bbdfSmrg        return NULL;
90605b261ecSmrg
9076747b715Smrg    ret = malloc(strlen(s) + 1);
90805b261ecSmrg    for (p = s, q = ret; *p != 0; p++) {
90935c4bbdfSmrg        switch (*p) {
91035c4bbdfSmrg        case '_':
91135c4bbdfSmrg        case ' ':
91235c4bbdfSmrg        case '\t':
91335c4bbdfSmrg            continue;
91435c4bbdfSmrg        default:
91535c4bbdfSmrg            if (isupper(*p))
91635c4bbdfSmrg                *q++ = tolower(*p);
91735c4bbdfSmrg            else
91835c4bbdfSmrg                *q++ = *p;
91935c4bbdfSmrg        }
92005b261ecSmrg    }
92105b261ecSmrg    *q = '\0';
92205b261ecSmrg    return ret;
92305b261ecSmrg}
924