135c4bbdfSmrg/*
235c4bbdfSmrg *
305b261ecSmrg * Copyright (c) 1997  Metro Link Incorporated
435c4bbdfSmrg *
505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
635c4bbdfSmrg * copy of this software and associated documentation files (the "Software"),
705b261ecSmrg * to deal in the Software without restriction, including without limitation
805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1005b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1135c4bbdfSmrg *
1205b261ecSmrg * The above copyright notice and this permission notice shall be included in
1305b261ecSmrg * all copies or substantial portions of the Software.
1435c4bbdfSmrg *
1505b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1605b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1705b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1805b261ecSmrg * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1905b261ecSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2005b261ecSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2105b261ecSmrg * SOFTWARE.
2235c4bbdfSmrg *
2305b261ecSmrg * Except as contained in this notice, the name of the Metro Link shall not be
2405b261ecSmrg * used in advertising or otherwise to promote the sale, use or other dealings
2505b261ecSmrg * in this Software without prior written authorization from Metro Link.
2635c4bbdfSmrg *
2705b261ecSmrg */
2805b261ecSmrg/*
2905b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3005b261ecSmrg *
3105b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
3205b261ecSmrg * copy of this software and associated documentation files (the "Software"),
3305b261ecSmrg * to deal in the Software without restriction, including without limitation
3405b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
3505b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
3605b261ecSmrg * Software is furnished to do so, subject to the following conditions:
3705b261ecSmrg *
3805b261ecSmrg * The above copyright notice and this permission notice shall be included in
3905b261ecSmrg * all copies or substantial portions of the Software.
4005b261ecSmrg *
4105b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4205b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4305b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
4405b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
4505b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4605b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4705b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
4805b261ecSmrg *
4905b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
5005b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
5105b261ecSmrg * the sale, use or other dealings in this Software without prior written
5205b261ecSmrg * authorization from the copyright holder(s) and author(s).
5305b261ecSmrg */
5405b261ecSmrg
5505b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
5605b261ecSmrg#include <xorg-config.h>
5705b261ecSmrg#endif
5805b261ecSmrg
5905b261ecSmrg#include "xf86Parser.h"
6005b261ecSmrg#include "xf86tokens.h"
6105b261ecSmrg#include "Configint.h"
6205b261ecSmrg#include <string.h>
6335c4bbdfSmrg#include "optionstr.h"
646747b715Smrg
656747b715Smrg/* Needed for auto server layout */
6635c4bbdfSmrgextern int xf86CheckBoolOption(void *optlist, const char *name, int deflt);
6735c4bbdfSmrg
6835c4bbdfSmrg
691b5d61b8Smrgstatic const xf86ConfigSymTabRec LayoutTab[] = {
7035c4bbdfSmrg    {ENDSECTION, "endsection"},
7135c4bbdfSmrg    {SCREEN, "screen"},
7235c4bbdfSmrg    {IDENTIFIER, "identifier"},
7335c4bbdfSmrg    {MATCHSEAT, "matchseat"},
7435c4bbdfSmrg    {INACTIVE, "inactive"},
7535c4bbdfSmrg    {INPUTDEVICE, "inputdevice"},
7635c4bbdfSmrg    {OPTION, "option"},
7735c4bbdfSmrg    {-1, ""},
7805b261ecSmrg};
7905b261ecSmrg
801b5d61b8Smrgstatic const xf86ConfigSymTabRec AdjTab[] = {
8135c4bbdfSmrg    {RIGHTOF, "rightof"},
8235c4bbdfSmrg    {LEFTOF, "leftof"},
8335c4bbdfSmrg    {ABOVE, "above"},
8435c4bbdfSmrg    {BELOW, "below"},
8535c4bbdfSmrg    {RELATIVE, "relative"},
8635c4bbdfSmrg    {ABSOLUTE, "absolute"},
8735c4bbdfSmrg    {-1, ""},
8805b261ecSmrg};
8905b261ecSmrg
9005b261ecSmrg#define CLEANUP xf86freeLayoutList
9105b261ecSmrg
9205b261ecSmrgXF86ConfLayoutPtr
9335c4bbdfSmrgxf86parseLayoutSection(void)
9405b261ecSmrg{
9535c4bbdfSmrg    int has_ident = FALSE;
9635c4bbdfSmrg    int token;
9735c4bbdfSmrg
9835c4bbdfSmrg    parsePrologue(XF86ConfLayoutPtr, XF86ConfLayoutRec)
9935c4bbdfSmrg
10035c4bbdfSmrg        while ((token = xf86getToken(LayoutTab)) != ENDSECTION) {
10135c4bbdfSmrg        switch (token) {
10235c4bbdfSmrg        case COMMENT:
10335c4bbdfSmrg            ptr->lay_comment = xf86addComment(ptr->lay_comment, xf86_lex_val.str);
10458cf2af7Smrg            free(xf86_lex_val.str);
10558cf2af7Smrg            xf86_lex_val.str = NULL;
10635c4bbdfSmrg            break;
10735c4bbdfSmrg        case IDENTIFIER:
10835c4bbdfSmrg            if (xf86getSubToken(&(ptr->lay_comment)) != STRING)
10935c4bbdfSmrg                Error(QUOTE_MSG, "Identifier");
11035c4bbdfSmrg            if (has_ident == TRUE)
11135c4bbdfSmrg                Error(MULTIPLE_MSG, "Identifier");
11235c4bbdfSmrg            ptr->lay_identifier = xf86_lex_val.str;
11335c4bbdfSmrg            has_ident = TRUE;
11435c4bbdfSmrg            break;
11535c4bbdfSmrg        case MATCHSEAT:
11635c4bbdfSmrg            if (xf86getSubToken(&(ptr->lay_comment)) != STRING)
11735c4bbdfSmrg                Error(QUOTE_MSG, "MatchSeat");
11835c4bbdfSmrg            ptr->match_seat = xf86_lex_val.str;
11935c4bbdfSmrg            break;
12035c4bbdfSmrg        case INACTIVE:
12135c4bbdfSmrg        {
12235c4bbdfSmrg            XF86ConfInactivePtr iptr;
12335c4bbdfSmrg
12435c4bbdfSmrg            iptr = calloc(1, sizeof(XF86ConfInactiveRec));
12535c4bbdfSmrg            iptr->list.next = NULL;
12635c4bbdfSmrg            if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
12735c4bbdfSmrg                free(iptr);
12835c4bbdfSmrg                Error(INACTIVE_MSG);
12935c4bbdfSmrg            }
13035c4bbdfSmrg            iptr->inactive_device_str = xf86_lex_val.str;
13135c4bbdfSmrg            ptr->lay_inactive_lst = (XF86ConfInactivePtr)
13235c4bbdfSmrg                xf86addListItem((glp) ptr->lay_inactive_lst, (glp) iptr);
13335c4bbdfSmrg        }
13435c4bbdfSmrg            break;
13535c4bbdfSmrg        case SCREEN:
13635c4bbdfSmrg        {
13735c4bbdfSmrg            XF86ConfAdjacencyPtr aptr;
13835c4bbdfSmrg            int absKeyword = 0;
13935c4bbdfSmrg
14035c4bbdfSmrg            aptr = calloc(1, sizeof(XF86ConfAdjacencyRec));
14135c4bbdfSmrg            aptr->list.next = NULL;
14235c4bbdfSmrg            aptr->adj_scrnum = -1;
14335c4bbdfSmrg            aptr->adj_where = CONF_ADJ_OBSOLETE;
14435c4bbdfSmrg            aptr->adj_x = 0;
14535c4bbdfSmrg            aptr->adj_y = 0;
14635c4bbdfSmrg            aptr->adj_refscreen = NULL;
14735c4bbdfSmrg            if ((token = xf86getSubToken(&(ptr->lay_comment))) == NUMBER)
14835c4bbdfSmrg                aptr->adj_scrnum = xf86_lex_val.num;
14935c4bbdfSmrg            else
15035c4bbdfSmrg                xf86unGetToken(token);
15135c4bbdfSmrg            token = xf86getSubToken(&(ptr->lay_comment));
15235c4bbdfSmrg            if (token != STRING) {
15335c4bbdfSmrg                free(aptr);
15435c4bbdfSmrg                Error(SCREEN_MSG);
15535c4bbdfSmrg            }
15635c4bbdfSmrg            aptr->adj_screen_str = xf86_lex_val.str;
15735c4bbdfSmrg
15835c4bbdfSmrg            token = xf86getSubTokenWithTab(&(ptr->lay_comment), AdjTab);
15935c4bbdfSmrg            switch (token) {
16035c4bbdfSmrg            case RIGHTOF:
16135c4bbdfSmrg                aptr->adj_where = CONF_ADJ_RIGHTOF;
16235c4bbdfSmrg                break;
16335c4bbdfSmrg            case LEFTOF:
16435c4bbdfSmrg                aptr->adj_where = CONF_ADJ_LEFTOF;
16535c4bbdfSmrg                break;
16635c4bbdfSmrg            case ABOVE:
16735c4bbdfSmrg                aptr->adj_where = CONF_ADJ_ABOVE;
16835c4bbdfSmrg                break;
16935c4bbdfSmrg            case BELOW:
17035c4bbdfSmrg                aptr->adj_where = CONF_ADJ_BELOW;
17135c4bbdfSmrg                break;
17235c4bbdfSmrg            case RELATIVE:
17335c4bbdfSmrg                aptr->adj_where = CONF_ADJ_RELATIVE;
17435c4bbdfSmrg                break;
17535c4bbdfSmrg            case ABSOLUTE:
17635c4bbdfSmrg                aptr->adj_where = CONF_ADJ_ABSOLUTE;
17735c4bbdfSmrg                absKeyword = 1;
17835c4bbdfSmrg                break;
17935c4bbdfSmrg            case EOF_TOKEN:
18035c4bbdfSmrg                free(aptr);
18135c4bbdfSmrg                Error(UNEXPECTED_EOF_MSG);
18235c4bbdfSmrg                break;
18335c4bbdfSmrg            default:
18435c4bbdfSmrg                xf86unGetToken(token);
18535c4bbdfSmrg                token = xf86getSubToken(&(ptr->lay_comment));
18635c4bbdfSmrg                if (token == STRING)
18735c4bbdfSmrg                    aptr->adj_where = CONF_ADJ_OBSOLETE;
18835c4bbdfSmrg                else
18935c4bbdfSmrg                    aptr->adj_where = CONF_ADJ_ABSOLUTE;
19035c4bbdfSmrg            }
19135c4bbdfSmrg            switch (aptr->adj_where) {
19235c4bbdfSmrg            case CONF_ADJ_ABSOLUTE:
19335c4bbdfSmrg                if (absKeyword)
19435c4bbdfSmrg                    token = xf86getSubToken(&(ptr->lay_comment));
19535c4bbdfSmrg                if (token == NUMBER) {
19635c4bbdfSmrg                    aptr->adj_x = xf86_lex_val.num;
19735c4bbdfSmrg                    token = xf86getSubToken(&(ptr->lay_comment));
19835c4bbdfSmrg                    if (token != NUMBER) {
19935c4bbdfSmrg                        free(aptr);
20035c4bbdfSmrg                        Error(INVALID_SCR_MSG);
20135c4bbdfSmrg                    }
20235c4bbdfSmrg                    aptr->adj_y = xf86_lex_val.num;
20335c4bbdfSmrg                }
20435c4bbdfSmrg                else {
20535c4bbdfSmrg                    if (absKeyword) {
20635c4bbdfSmrg                        free(aptr);
20735c4bbdfSmrg                        Error(INVALID_SCR_MSG);
20835c4bbdfSmrg                    }
20935c4bbdfSmrg                    else
21035c4bbdfSmrg                        xf86unGetToken(token);
21135c4bbdfSmrg                }
21235c4bbdfSmrg                break;
21335c4bbdfSmrg            case CONF_ADJ_RIGHTOF:
21435c4bbdfSmrg            case CONF_ADJ_LEFTOF:
21535c4bbdfSmrg            case CONF_ADJ_ABOVE:
21635c4bbdfSmrg            case CONF_ADJ_BELOW:
21735c4bbdfSmrg            case CONF_ADJ_RELATIVE:
21835c4bbdfSmrg                token = xf86getSubToken(&(ptr->lay_comment));
21935c4bbdfSmrg                if (token != STRING) {
22035c4bbdfSmrg                    free(aptr);
22135c4bbdfSmrg                    Error(INVALID_SCR_MSG);
22235c4bbdfSmrg                }
22335c4bbdfSmrg                aptr->adj_refscreen = xf86_lex_val.str;
22435c4bbdfSmrg                if (aptr->adj_where == CONF_ADJ_RELATIVE) {
22535c4bbdfSmrg                    token = xf86getSubToken(&(ptr->lay_comment));
22635c4bbdfSmrg                    if (token != NUMBER) {
22735c4bbdfSmrg                        free(aptr);
22835c4bbdfSmrg                        Error(INVALID_SCR_MSG);
22935c4bbdfSmrg                    }
23035c4bbdfSmrg                    aptr->adj_x = xf86_lex_val.num;
23135c4bbdfSmrg                    token = xf86getSubToken(&(ptr->lay_comment));
23235c4bbdfSmrg                    if (token != NUMBER) {
23335c4bbdfSmrg                        free(aptr);
23435c4bbdfSmrg                        Error(INVALID_SCR_MSG);
23535c4bbdfSmrg                    }
23635c4bbdfSmrg                    aptr->adj_y = xf86_lex_val.num;
23735c4bbdfSmrg                }
23835c4bbdfSmrg                break;
23935c4bbdfSmrg            case CONF_ADJ_OBSOLETE:
24035c4bbdfSmrg                /* top */
24135c4bbdfSmrg                aptr->adj_top_str = xf86_lex_val.str;
24235c4bbdfSmrg
24335c4bbdfSmrg                /* bottom */
24435c4bbdfSmrg                if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
24535c4bbdfSmrg                    free(aptr);
24635c4bbdfSmrg                    Error(SCREEN_MSG);
24735c4bbdfSmrg                }
24835c4bbdfSmrg                aptr->adj_bottom_str = xf86_lex_val.str;
24935c4bbdfSmrg
25035c4bbdfSmrg                /* left */
25135c4bbdfSmrg                if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
25235c4bbdfSmrg                    free(aptr);
25335c4bbdfSmrg                    Error(SCREEN_MSG);
25435c4bbdfSmrg                }
25535c4bbdfSmrg                aptr->adj_left_str = xf86_lex_val.str;
25635c4bbdfSmrg
25735c4bbdfSmrg                /* right */
25835c4bbdfSmrg                if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
25935c4bbdfSmrg                    free(aptr);
26035c4bbdfSmrg                    Error(SCREEN_MSG);
26135c4bbdfSmrg                }
26235c4bbdfSmrg                aptr->adj_right_str = xf86_lex_val.str;
26335c4bbdfSmrg
26435c4bbdfSmrg            }
26535c4bbdfSmrg            ptr->lay_adjacency_lst = (XF86ConfAdjacencyPtr)
26635c4bbdfSmrg                xf86addListItem((glp) ptr->lay_adjacency_lst, (glp) aptr);
26735c4bbdfSmrg        }
26835c4bbdfSmrg            break;
26935c4bbdfSmrg        case INPUTDEVICE:
27035c4bbdfSmrg        {
27135c4bbdfSmrg            XF86ConfInputrefPtr iptr;
27235c4bbdfSmrg
27335c4bbdfSmrg            iptr = calloc(1, sizeof(XF86ConfInputrefRec));
27435c4bbdfSmrg            iptr->list.next = NULL;
27535c4bbdfSmrg            iptr->iref_option_lst = NULL;
27635c4bbdfSmrg            if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
27735c4bbdfSmrg                free(iptr);
27835c4bbdfSmrg                Error(INPUTDEV_MSG);
27935c4bbdfSmrg            }
28035c4bbdfSmrg            iptr->iref_inputdev_str = xf86_lex_val.str;
28135c4bbdfSmrg            while ((token = xf86getSubToken(&(ptr->lay_comment))) == STRING) {
28235c4bbdfSmrg                iptr->iref_option_lst =
28335c4bbdfSmrg                    xf86addNewOption(iptr->iref_option_lst, xf86_lex_val.str, NULL);
28435c4bbdfSmrg            }
28535c4bbdfSmrg            xf86unGetToken(token);
28635c4bbdfSmrg            ptr->lay_input_lst = (XF86ConfInputrefPtr)
28735c4bbdfSmrg                xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
28835c4bbdfSmrg        }
28935c4bbdfSmrg            break;
29035c4bbdfSmrg        case OPTION:
29135c4bbdfSmrg            ptr->lay_option_lst = xf86parseOption(ptr->lay_option_lst);
29235c4bbdfSmrg            break;
29335c4bbdfSmrg        case EOF_TOKEN:
29435c4bbdfSmrg            Error(UNEXPECTED_EOF_MSG);
29535c4bbdfSmrg            break;
29635c4bbdfSmrg        default:
29735c4bbdfSmrg            Error(INVALID_KEYWORD_MSG, xf86tokenString());
29835c4bbdfSmrg            break;
29935c4bbdfSmrg        }
30035c4bbdfSmrg    }
30135c4bbdfSmrg
30235c4bbdfSmrg    if (!has_ident)
30335c4bbdfSmrg        Error(NO_IDENT_MSG);
30405b261ecSmrg
30505b261ecSmrg#ifdef DEBUG
30635c4bbdfSmrg    printf("Layout section parsed\n");
30705b261ecSmrg#endif
30805b261ecSmrg
30935c4bbdfSmrg    return ptr;
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrg#undef CLEANUP
31305b261ecSmrg
31405b261ecSmrgvoid
31535c4bbdfSmrgxf86printLayoutSection(FILE * cf, XF86ConfLayoutPtr ptr)
31605b261ecSmrg{
31735c4bbdfSmrg    XF86ConfAdjacencyPtr aptr;
31835c4bbdfSmrg    XF86ConfInactivePtr iptr;
31935c4bbdfSmrg    XF86ConfInputrefPtr inptr;
32035c4bbdfSmrg    XF86OptionPtr optr;
32135c4bbdfSmrg
32235c4bbdfSmrg    while (ptr) {
32335c4bbdfSmrg        fprintf(cf, "Section \"ServerLayout\"\n");
32435c4bbdfSmrg        if (ptr->lay_comment)
32535c4bbdfSmrg            fprintf(cf, "%s", ptr->lay_comment);
32635c4bbdfSmrg        if (ptr->lay_identifier)
32735c4bbdfSmrg            fprintf(cf, "\tIdentifier     \"%s\"\n", ptr->lay_identifier);
32835c4bbdfSmrg
32935c4bbdfSmrg        for (aptr = ptr->lay_adjacency_lst; aptr; aptr = aptr->list.next) {
33035c4bbdfSmrg            fprintf(cf, "\tScreen     ");
33135c4bbdfSmrg            if (aptr->adj_scrnum >= 0)
33235c4bbdfSmrg                fprintf(cf, "%2d", aptr->adj_scrnum);
33335c4bbdfSmrg            else
33435c4bbdfSmrg                fprintf(cf, "  ");
33535c4bbdfSmrg            fprintf(cf, "  \"%s\"", aptr->adj_screen_str);
33635c4bbdfSmrg            switch (aptr->adj_where) {
33735c4bbdfSmrg            case CONF_ADJ_OBSOLETE:
33835c4bbdfSmrg                fprintf(cf, " \"%s\"", aptr->adj_top_str);
33935c4bbdfSmrg                fprintf(cf, " \"%s\"", aptr->adj_bottom_str);
34035c4bbdfSmrg                fprintf(cf, " \"%s\"", aptr->adj_right_str);
34135c4bbdfSmrg                fprintf(cf, " \"%s\"\n", aptr->adj_left_str);
34235c4bbdfSmrg                break;
34335c4bbdfSmrg            case CONF_ADJ_ABSOLUTE:
34435c4bbdfSmrg                if (aptr->adj_x != -1)
34535c4bbdfSmrg                    fprintf(cf, " %d %d\n", aptr->adj_x, aptr->adj_y);
34635c4bbdfSmrg                else
34735c4bbdfSmrg                    fprintf(cf, "\n");
34835c4bbdfSmrg                break;
34935c4bbdfSmrg            case CONF_ADJ_RIGHTOF:
35035c4bbdfSmrg                fprintf(cf, " RightOf \"%s\"\n", aptr->adj_refscreen);
35135c4bbdfSmrg                break;
35235c4bbdfSmrg            case CONF_ADJ_LEFTOF:
35335c4bbdfSmrg                fprintf(cf, " LeftOf \"%s\"\n", aptr->adj_refscreen);
35435c4bbdfSmrg                break;
35535c4bbdfSmrg            case CONF_ADJ_ABOVE:
35635c4bbdfSmrg                fprintf(cf, " Above \"%s\"\n", aptr->adj_refscreen);
35735c4bbdfSmrg                break;
35835c4bbdfSmrg            case CONF_ADJ_BELOW:
35935c4bbdfSmrg                fprintf(cf, " Below \"%s\"\n", aptr->adj_refscreen);
36035c4bbdfSmrg                break;
36135c4bbdfSmrg            case CONF_ADJ_RELATIVE:
36235c4bbdfSmrg                fprintf(cf, " Relative \"%s\" %d %d\n", aptr->adj_refscreen,
36335c4bbdfSmrg                        aptr->adj_x, aptr->adj_y);
36435c4bbdfSmrg                break;
36535c4bbdfSmrg            }
36635c4bbdfSmrg        }
36735c4bbdfSmrg        for (iptr = ptr->lay_inactive_lst; iptr; iptr = iptr->list.next)
36835c4bbdfSmrg            fprintf(cf, "\tInactive       \"%s\"\n", iptr->inactive_device_str);
36935c4bbdfSmrg        for (inptr = ptr->lay_input_lst; inptr; inptr = inptr->list.next) {
37035c4bbdfSmrg            fprintf(cf, "\tInputDevice    \"%s\"", inptr->iref_inputdev_str);
37135c4bbdfSmrg            for (optr = inptr->iref_option_lst; optr; optr = optr->list.next) {
37235c4bbdfSmrg                fprintf(cf, " \"%s\"", optr->opt_name);
37335c4bbdfSmrg            }
37435c4bbdfSmrg            fprintf(cf, "\n");
37535c4bbdfSmrg        }
37635c4bbdfSmrg        xf86printOptionList(cf, ptr->lay_option_lst, 1);
37735c4bbdfSmrg        fprintf(cf, "EndSection\n\n");
37835c4bbdfSmrg        ptr = ptr->list.next;
37935c4bbdfSmrg    }
38005b261ecSmrg}
38105b261ecSmrg
38205b261ecSmrgstatic void
38335c4bbdfSmrgxf86freeAdjacencyList(XF86ConfAdjacencyPtr ptr)
38405b261ecSmrg{
38535c4bbdfSmrg    XF86ConfAdjacencyPtr prev;
38635c4bbdfSmrg
38735c4bbdfSmrg    while (ptr) {
38835c4bbdfSmrg        TestFree(ptr->adj_screen_str);
38935c4bbdfSmrg        TestFree(ptr->adj_top_str);
39035c4bbdfSmrg        TestFree(ptr->adj_bottom_str);
39135c4bbdfSmrg        TestFree(ptr->adj_left_str);
39235c4bbdfSmrg        TestFree(ptr->adj_right_str);
39335c4bbdfSmrg
39435c4bbdfSmrg        prev = ptr;
39535c4bbdfSmrg        ptr = ptr->list.next;
39635c4bbdfSmrg        free(prev);
39735c4bbdfSmrg    }
39805b261ecSmrg
39905b261ecSmrg}
40005b261ecSmrg
40105b261ecSmrgstatic void
40235c4bbdfSmrgxf86freeInputrefList(XF86ConfInputrefPtr ptr)
40305b261ecSmrg{
40435c4bbdfSmrg    XF86ConfInputrefPtr prev;
40535c4bbdfSmrg
40635c4bbdfSmrg    while (ptr) {
40735c4bbdfSmrg        TestFree(ptr->iref_inputdev_str);
40835c4bbdfSmrg        xf86optionListFree(ptr->iref_option_lst);
40935c4bbdfSmrg        prev = ptr;
41035c4bbdfSmrg        ptr = ptr->list.next;
41135c4bbdfSmrg        free(prev);
41235c4bbdfSmrg    }
41305b261ecSmrg
41405b261ecSmrg}
41505b261ecSmrg
41605b261ecSmrgvoid
41735c4bbdfSmrgxf86freeLayoutList(XF86ConfLayoutPtr ptr)
41805b261ecSmrg{
41935c4bbdfSmrg    XF86ConfLayoutPtr prev;
42035c4bbdfSmrg
42135c4bbdfSmrg    while (ptr) {
42235c4bbdfSmrg        TestFree(ptr->lay_identifier);
42335c4bbdfSmrg        TestFree(ptr->lay_comment);
42435c4bbdfSmrg        xf86freeAdjacencyList(ptr->lay_adjacency_lst);
42535c4bbdfSmrg        xf86freeInputrefList(ptr->lay_input_lst);
42635c4bbdfSmrg        prev = ptr;
42735c4bbdfSmrg        ptr = ptr->list.next;
42835c4bbdfSmrg        free(prev);
42935c4bbdfSmrg    }
43005b261ecSmrg}
43105b261ecSmrg
4326747b715Smrgint
4336747b715Smrgxf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout)
4346747b715Smrg{
4356747b715Smrg    int count = 0;
4366747b715Smrg    XF86ConfInputPtr input = config->conf_input_lst;
4376747b715Smrg    XF86ConfInputrefPtr inptr;
4386747b715Smrg
4396747b715Smrg    /* add all AutoServerLayout devices to the server layout */
44035c4bbdfSmrg    while (input) {
44135c4bbdfSmrg        if (xf86CheckBoolOption
44235c4bbdfSmrg            (input->inp_option_lst, "AutoServerLayout", FALSE)) {
44335c4bbdfSmrg            XF86ConfInputrefPtr iref = layout->lay_input_lst;
44435c4bbdfSmrg
44535c4bbdfSmrg            /* avoid duplicates if referenced but lists AutoServerLayout too */
44635c4bbdfSmrg            while (iref) {
44735c4bbdfSmrg                if (strcmp(iref->iref_inputdev_str, input->inp_identifier) == 0)
44835c4bbdfSmrg                    break;
44935c4bbdfSmrg                iref = iref->list.next;
45035c4bbdfSmrg            }
45135c4bbdfSmrg
45235c4bbdfSmrg            if (!iref) {
45335c4bbdfSmrg                XF86ConfInputrefPtr iptr;
45435c4bbdfSmrg
45535c4bbdfSmrg                iptr = calloc(1, sizeof(XF86ConfInputrefRec));
45635c4bbdfSmrg                iptr->iref_inputdev_str = input->inp_identifier;
45735c4bbdfSmrg                layout->lay_input_lst = (XF86ConfInputrefPtr)
45835c4bbdfSmrg                    xf86addListItem((glp) layout->lay_input_lst, (glp) iptr);
45935c4bbdfSmrg                count++;
46035c4bbdfSmrg            }
46135c4bbdfSmrg        }
46235c4bbdfSmrg        input = input->list.next;
4636747b715Smrg    }
4646747b715Smrg
4656747b715Smrg    inptr = layout->lay_input_lst;
46635c4bbdfSmrg    while (inptr) {
46735c4bbdfSmrg        input = xf86findInput(inptr->iref_inputdev_str, config->conf_input_lst);
46835c4bbdfSmrg        if (!input) {
46935c4bbdfSmrg            xf86validationError(UNDEFINED_INPUT_MSG,
47035c4bbdfSmrg                                inptr->iref_inputdev_str,
47135c4bbdfSmrg                                layout->lay_identifier);
47235c4bbdfSmrg            return -1;
47335c4bbdfSmrg        }
47435c4bbdfSmrg        else
47535c4bbdfSmrg            inptr->iref_inputdev = input;
47635c4bbdfSmrg        inptr = inptr->list.next;
4776747b715Smrg    }
4786747b715Smrg
4796747b715Smrg    return count;
48005b261ecSmrg}
48105b261ecSmrg
48205b261ecSmrgint
48335c4bbdfSmrgxf86validateLayout(XF86ConfigPtr p)
48405b261ecSmrg{
48535c4bbdfSmrg    XF86ConfLayoutPtr layout = p->conf_layout_lst;
48635c4bbdfSmrg    XF86ConfAdjacencyPtr adj;
48735c4bbdfSmrg    XF86ConfInactivePtr iptr;
48835c4bbdfSmrg    XF86ConfScreenPtr screen;
48935c4bbdfSmrg    XF86ConfDevicePtr device;
49035c4bbdfSmrg
49135c4bbdfSmrg    while (layout) {
49235c4bbdfSmrg        adj = layout->lay_adjacency_lst;
49335c4bbdfSmrg        while (adj) {
49435c4bbdfSmrg            /* the first one can't be "" but all others can */
49535c4bbdfSmrg            screen = xf86findScreen(adj->adj_screen_str, p->conf_screen_lst);
49635c4bbdfSmrg            if (!screen) {
49735c4bbdfSmrg                xf86validationError(UNDEFINED_SCREEN_MSG,
49835c4bbdfSmrg                                    adj->adj_screen_str,
49935c4bbdfSmrg                                    layout->lay_identifier);
50035c4bbdfSmrg                return FALSE;
50135c4bbdfSmrg            }
50235c4bbdfSmrg            else
50335c4bbdfSmrg                adj->adj_screen = screen;
50435c4bbdfSmrg
50535c4bbdfSmrg            adj = adj->list.next;
50635c4bbdfSmrg        }
50735c4bbdfSmrg        iptr = layout->lay_inactive_lst;
50835c4bbdfSmrg        while (iptr) {
50935c4bbdfSmrg            device = xf86findDevice(iptr->inactive_device_str,
51035c4bbdfSmrg                                    p->conf_device_lst);
51135c4bbdfSmrg            if (!device) {
51235c4bbdfSmrg                xf86validationError(UNDEFINED_DEVICE_LAY_MSG,
51335c4bbdfSmrg                                    iptr->inactive_device_str,
51435c4bbdfSmrg                                    layout->lay_identifier);
51535c4bbdfSmrg                return FALSE;
51635c4bbdfSmrg            }
51735c4bbdfSmrg            else
51835c4bbdfSmrg                iptr->inactive_device = device;
51935c4bbdfSmrg            iptr = iptr->list.next;
52035c4bbdfSmrg        }
52135c4bbdfSmrg
52235c4bbdfSmrg        if (xf86layoutAddInputDevices(p, layout) == -1)
52335c4bbdfSmrg            return FALSE;
52435c4bbdfSmrg
52535c4bbdfSmrg        layout = layout->list.next;
52635c4bbdfSmrg    }
52735c4bbdfSmrg    return TRUE;
52805b261ecSmrg}
52905b261ecSmrg
53005b261ecSmrgXF86ConfLayoutPtr
53135c4bbdfSmrgxf86findLayout(const char *name, XF86ConfLayoutPtr list)
53205b261ecSmrg{
53335c4bbdfSmrg    while (list) {
53435c4bbdfSmrg        if (xf86nameCompare(list->lay_identifier, name) == 0)
53535c4bbdfSmrg            return list;
53635c4bbdfSmrg        list = list->list.next;
53735c4bbdfSmrg    }
53835c4bbdfSmrg    return NULL;
53905b261ecSmrg}
540