1706f2543Smrg/*
2706f2543Smrg * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
3706f2543Smrg *
4706f2543Smrg * All Rights Reserved.
5706f2543Smrg *
6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining
7706f2543Smrg * a copy of this software and associated documentation files (the
8706f2543Smrg * "Software"), to deal in the Software without restriction, including
9706f2543Smrg * without limitation on the rights to use, copy, modify, merge,
10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
11706f2543Smrg * and to permit persons to whom the Software is furnished to do so,
12706f2543Smrg * subject to the following conditions:
13706f2543Smrg *
14706f2543Smrg * The above copyright notice and this permission notice (including the
15706f2543Smrg * next paragraph) shall be included in all copies or substantial
16706f2543Smrg * portions of the Software.
17706f2543Smrg *
18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21706f2543Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25706f2543Smrg * SOFTWARE.
26706f2543Smrg */
27706f2543Smrg
28706f2543Smrg/*
29706f2543Smrg * Authors:
30706f2543Smrg *   Rickard E. (Rik) Faith <faith@redhat.com>
31706f2543Smrg *
32706f2543Smrg */
33706f2543Smrg
34706f2543Smrg/** \file
35706f2543Smrg * Provides interface for reading DMX configuration files and for
36706f2543Smrg * combining that information with command-line configuration parameters. */
37706f2543Smrg
38706f2543Smrg
39706f2543Smrg#ifdef HAVE_DMX_CONFIG_H
40706f2543Smrg#include <dmx-config.h>
41706f2543Smrg#endif
42706f2543Smrg
43706f2543Smrg#include "dmx.h"
44706f2543Smrg#include "dmxinput.h"
45706f2543Smrg#include "dmxconfig.h"
46706f2543Smrg#include "dmxparse.h"
47706f2543Smrg#include "dmxlog.h"
48706f2543Smrg#include "dmxcb.h"
49706f2543Smrg#include "dmxstat.h"
50706f2543Smrg#include "parser.h"
51706f2543Smrg
52706f2543Smrgextern int  yyparse(void);
53706f2543Smrgextern FILE *yyin;
54706f2543Smrg
55706f2543Smrgstatic char *dmxXkbRules;
56706f2543Smrgstatic char *dmxXkbModel;
57706f2543Smrgstatic char *dmxXkbLayout;
58706f2543Smrgstatic char *dmxXkbVariant;
59706f2543Smrgstatic char *dmxXkbOptions;
60706f2543Smrg
61706f2543Smrg/** Stores lists of configuration information. */
62706f2543Smrgtypedef struct DMXConfigListStruct {
63706f2543Smrg    const char                 *name;
64706f2543Smrg    struct DMXConfigListStruct *next;
65706f2543Smrg} DMXConfigList, *DMXConfigListPtr;
66706f2543Smrg
67706f2543Smrg/** This stucture stores the parsed configuration information. */
68706f2543Smrgtypedef struct DMXConfigCmdStruct {
69706f2543Smrg    const char    *filename;
70706f2543Smrg    const char    *config;
71706f2543Smrg    DMXConfigList *displays;
72706f2543Smrg    DMXConfigList *inputs;
73706f2543Smrg    DMXConfigList *xinputs;
74706f2543Smrg} DMXConfigCmd, *DMXConfigCmdPtr;
75706f2543Smrg
76706f2543SmrgDMXConfigEntryPtr    dmxConfigEntry;
77706f2543Smrgstatic DMXConfigCmd  dmxConfigCmd;
78706f2543Smrg
79706f2543Smrgstatic int dmxDisplaysFromCommandLine;
80706f2543Smrg
81706f2543Smrg/** Make a note that \a display is the name of an X11 display that
82706f2543Smrg * should be initialized as a backend (output) display.  Called from
83706f2543Smrg * #ddxProcessArgument. */
84706f2543Smrgvoid dmxConfigStoreDisplay(const char *display)
85706f2543Smrg{
86706f2543Smrg    DMXConfigListPtr entry = malloc(sizeof(*entry));
87706f2543Smrg    entry->name = strdup(display);
88706f2543Smrg    entry->next = NULL;
89706f2543Smrg    if (!dmxConfigCmd.displays) dmxConfigCmd.displays = entry;
90706f2543Smrg    else {
91706f2543Smrg        DMXConfigList *pt;
92706f2543Smrg        for (pt = dmxConfigCmd.displays; pt->next; pt = pt->next);
93706f2543Smrg        if (!pt)
94706f2543Smrg            dmxLog(dmxFatal, "dmxConfigStoreDisplay: end of list non-NULL\n");
95706f2543Smrg        pt->next = entry;
96706f2543Smrg    }
97706f2543Smrg    ++dmxDisplaysFromCommandLine;
98706f2543Smrg}
99706f2543Smrg
100706f2543Smrg/** Make a note that \a input is the name of an X11 display that should
101706f2543Smrg * be used for input (either a backend or a console input device). */
102706f2543Smrgvoid dmxConfigStoreInput(const char *input)
103706f2543Smrg{
104706f2543Smrg    DMXConfigListPtr entry = malloc(sizeof(*entry));
105706f2543Smrg    entry->name = strdup(input);
106706f2543Smrg    entry->next = NULL;
107706f2543Smrg    if (!dmxConfigCmd.inputs) dmxConfigCmd.inputs = entry;
108706f2543Smrg    else {
109706f2543Smrg        DMXConfigList *pt;
110706f2543Smrg        for (pt = dmxConfigCmd.inputs; pt->next; pt = pt->next);
111706f2543Smrg        if (!pt)
112706f2543Smrg            dmxLog(dmxFatal, "dmxConfigStoreInput: end of list non-NULL\n");
113706f2543Smrg        pt->next = entry;
114706f2543Smrg    }
115706f2543Smrg}
116706f2543Smrg
117706f2543Smrg/** Make a note that \a input is the name of an X11 display that should
118706f2543Smrg * be used for input from XInput extension devices. */
119706f2543Smrgvoid dmxConfigStoreXInput(const char *input)
120706f2543Smrg{
121706f2543Smrg    DMXConfigListPtr entry = malloc(sizeof(*entry));
122706f2543Smrg    entry->name = strdup(input);
123706f2543Smrg    entry->next = NULL;
124706f2543Smrg    if (!dmxConfigCmd.xinputs) dmxConfigCmd.xinputs = entry;
125706f2543Smrg    else {
126706f2543Smrg        DMXConfigList *pt;
127706f2543Smrg        for (pt = dmxConfigCmd.xinputs; pt->next; pt = pt->next);
128706f2543Smrg        if (!pt)
129706f2543Smrg            dmxLog(dmxFatal, "dmxConfigStoreXInput: end of list non-NULL\n");
130706f2543Smrg        pt->next = entry;
131706f2543Smrg    }
132706f2543Smrg}
133706f2543Smrg
134706f2543Smrg/** Make a note that \a file is the configuration file. */
135706f2543Smrgvoid dmxConfigStoreFile(const char *file)
136706f2543Smrg{
137706f2543Smrg    if (dmxConfigCmd.filename)
138706f2543Smrg        dmxLog(dmxFatal, "Only one -configfile allowed\n");
139706f2543Smrg    dmxConfigCmd.filename = strdup(file);
140706f2543Smrg}
141706f2543Smrg
142706f2543Smrg/** Make a note that \a config should be used as the configuration for
143706f2543Smrg * current instantiation of the DMX server. */
144706f2543Smrgvoid dmxConfigStoreConfig(const char *config)
145706f2543Smrg{
146706f2543Smrg    if (dmxConfigCmd.config) dmxLog(dmxFatal, "Only one -config allowed\n");
147706f2543Smrg    dmxConfigCmd.config = strdup(config);
148706f2543Smrg}
149706f2543Smrg
150706f2543Smrgstatic int dmxConfigReadFile(const char *filename, int debug)
151706f2543Smrg{
152706f2543Smrg    FILE *str;
153706f2543Smrg
154706f2543Smrg    if (!(str = fopen(filename, "r"))) return -1;
155706f2543Smrg    dmxLog(dmxInfo, "Reading configuration file \"%s\"\n", filename);
156706f2543Smrg    yyin    = str;
157706f2543Smrg    yydebug = debug;
158706f2543Smrg    yyparse();
159706f2543Smrg    fclose(str);
160706f2543Smrg    return 0;
161706f2543Smrg}
162706f2543Smrg
163706f2543Smrgstatic const char *dmxConfigMatch(const char *target, DMXConfigEntryPtr entry)
164706f2543Smrg{
165706f2543Smrg    DMXConfigVirtualPtr v     = entry->virtual;
166706f2543Smrg    const char          *name = NULL;
167706f2543Smrg
168706f2543Smrg    if (v && v->name) name = v->name;
169706f2543Smrg
170706f2543Smrg    if (v && !dmxConfigCmd.config) return v->name ? v->name : "<noname>";
171706f2543Smrg    if (!name)                     return NULL;
172706f2543Smrg    if (!strcmp(name, target))     return name;
173706f2543Smrg    return NULL;
174706f2543Smrg}
175706f2543Smrg
176706f2543Smrgstatic DMXScreenInfo *dmxConfigAddDisplay(const char *name,
177706f2543Smrg                                          int scrnWidth,   int scrnHeight,
178706f2543Smrg                                          int scrnX,       int scrnY,
179706f2543Smrg                                          int scrnXSign,   int scrnYSign,
180706f2543Smrg                                          int rootWidth,   int rootHeight,
181706f2543Smrg                                          int rootX,       int rootY,
182706f2543Smrg                                          int rootXSign,   int rootYSign)
183706f2543Smrg{
184706f2543Smrg    DMXScreenInfo *dmxScreen;
185706f2543Smrg
186706f2543Smrg    if (!(dmxScreens = realloc(dmxScreens,
187706f2543Smrg                               (dmxNumScreens+1) * sizeof(*dmxScreens))))
188706f2543Smrg        dmxLog(dmxFatal,
189706f2543Smrg               "dmxConfigAddDisplay: realloc failed for screen %d (%s)\n",
190706f2543Smrg               dmxNumScreens, name);
191706f2543Smrg
192706f2543Smrg    dmxScreen = &dmxScreens[dmxNumScreens];
193706f2543Smrg    memset(dmxScreen, 0, sizeof(*dmxScreen));
194706f2543Smrg    dmxScreen->name       = name;
195706f2543Smrg    dmxScreen->index      = dmxNumScreens;
196706f2543Smrg    dmxScreen->scrnWidth  = scrnWidth;
197706f2543Smrg    dmxScreen->scrnHeight = scrnHeight;
198706f2543Smrg    dmxScreen->scrnX      = scrnX;
199706f2543Smrg    dmxScreen->scrnY      = scrnY;
200706f2543Smrg    dmxScreen->scrnXSign  = scrnXSign;
201706f2543Smrg    dmxScreen->scrnYSign  = scrnYSign;
202706f2543Smrg    dmxScreen->rootWidth  = rootWidth;
203706f2543Smrg    dmxScreen->rootHeight = rootHeight;
204706f2543Smrg    dmxScreen->rootX      = rootX;
205706f2543Smrg    dmxScreen->rootY      = rootY;
206706f2543Smrg    dmxScreen->stat       = dmxStatAlloc();
207706f2543Smrg    ++dmxNumScreens;
208706f2543Smrg    return dmxScreen;
209706f2543Smrg}
210706f2543Smrg
211706f2543SmrgDMXInputInfo *dmxConfigAddInput(const char *name, int core)
212706f2543Smrg{
213706f2543Smrg    DMXInputInfo *dmxInput;
214706f2543Smrg
215706f2543Smrg    if (!(dmxInputs = realloc(dmxInputs,
216706f2543Smrg                              (dmxNumInputs+1) * sizeof(*dmxInputs))))
217706f2543Smrg        dmxLog(dmxFatal,
218706f2543Smrg               "dmxConfigAddInput: realloc failed for input %d (%s)\n",
219706f2543Smrg               dmxNumInputs, name);
220706f2543Smrg
221706f2543Smrg    dmxInput = &dmxInputs[dmxNumInputs];
222706f2543Smrg
223706f2543Smrg    memset(dmxInput, 0, sizeof(*dmxInput));
224706f2543Smrg    dmxInput->name     = name;
225706f2543Smrg    dmxInput->inputIdx = dmxNumInputs;
226706f2543Smrg    dmxInput->scrnIdx  = -1;
227706f2543Smrg    dmxInput->core     = core;
228706f2543Smrg    ++dmxNumInputs;
229706f2543Smrg    return dmxInput;
230706f2543Smrg}
231706f2543Smrg
232706f2543Smrgstatic void dmxConfigCopyFromDisplay(DMXConfigDisplayPtr d)
233706f2543Smrg{
234706f2543Smrg    DMXScreenInfo *dmxScreen;
235706f2543Smrg
236706f2543Smrg    dmxScreen         = dmxConfigAddDisplay(d->name,
237706f2543Smrg                                            d->scrnWidth, d->scrnHeight,
238706f2543Smrg                                            d->scrnX,     d->scrnY,
239706f2543Smrg                                            d->scrnXSign, d->scrnYSign,
240706f2543Smrg                                            d->rootWidth, d->rootHeight,
241706f2543Smrg                                            d->rootX,     d->rootY,
242706f2543Smrg                                            d->rootXSign, d->rootXSign);
243706f2543Smrg    dmxScreen->where  = PosAbsolute;
244706f2543Smrg    dmxScreen->whereX = d->rootXOrigin;
245706f2543Smrg    dmxScreen->whereY = d->rootYOrigin;
246706f2543Smrg}
247706f2543Smrg
248706f2543Smrgstatic void dmxConfigCopyFromWall(DMXConfigWallPtr w)
249706f2543Smrg{
250706f2543Smrg    DMXConfigStringPtr pt;
251706f2543Smrg    DMXScreenInfo      *dmxScreen;
252706f2543Smrg    int                edge = dmxNumScreens;
253706f2543Smrg    int                last = dmxNumScreens;
254706f2543Smrg
255706f2543Smrg    if (!w->xwall && !w->ywall) { /* Try to make it square */
256706f2543Smrg        int count;
257706f2543Smrg        for (pt = w->nameList, count = 0; pt; pt = pt->next) ++count;
258706f2543Smrg        w->xwall = sqrt(count) + .5;
259706f2543Smrg    }
260706f2543Smrg
261706f2543Smrg    for (pt = w->nameList; pt; pt = pt->next) {
262706f2543Smrg        dmxScreen = dmxConfigAddDisplay(pt->string, w->width, w->height,
263706f2543Smrg                                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
264706f2543Smrg        if (pt == w->nameList) { /* Upper left */
265706f2543Smrg            dmxScreen->where  = PosAbsolute;
266706f2543Smrg            dmxScreen->whereX = 0;
267706f2543Smrg            dmxScreen->whereY = 0;
268706f2543Smrg        } else if (w->xwall) {  /* Tile left to right, then top to bottom */
269706f2543Smrg            if (!((dmxNumScreens-1) % w->xwall)) {
270706f2543Smrg                dmxScreen->where          = PosBelow;
271706f2543Smrg                dmxScreen->whereRefScreen = edge;
272706f2543Smrg                edge                      = dmxNumScreens-1;
273706f2543Smrg            } else {
274706f2543Smrg                dmxScreen->where          = PosRightOf;
275706f2543Smrg                dmxScreen->whereRefScreen = last;
276706f2543Smrg            }
277706f2543Smrg        } else {                /* Tile top to bottom, then left to right */
278706f2543Smrg            if (!((dmxNumScreens-1) % w->ywall)) {
279706f2543Smrg                dmxScreen->where          = PosRightOf;
280706f2543Smrg                dmxScreen->whereRefScreen = edge;
281706f2543Smrg                edge                      = dmxNumScreens-1;
282706f2543Smrg            } else {
283706f2543Smrg                dmxScreen->where          = PosBelow;
284706f2543Smrg                dmxScreen->whereRefScreen = last;
285706f2543Smrg            }
286706f2543Smrg
287706f2543Smrg        }
288706f2543Smrg        last = dmxNumScreens-1;
289706f2543Smrg        if (dmxScreen->where == PosAbsolute)
290706f2543Smrg            dmxLog(dmxInfo, "Added %s at %d %d\n",
291706f2543Smrg                   pt->string, dmxScreen->whereX, dmxScreen->whereY);
292706f2543Smrg        else
293706f2543Smrg            dmxLog(dmxInfo, "Added %s %s %s\n",
294706f2543Smrg                   pt->string,
295706f2543Smrg                   dmxScreen->where == PosBelow ? "below" : "right of",
296706f2543Smrg                   dmxScreens[dmxScreen->whereRefScreen].name);
297706f2543Smrg    }
298706f2543Smrg}
299706f2543Smrg
300706f2543Smrgstatic void dmxConfigCopyFromOption(DMXConfigOptionPtr o)
301706f2543Smrg{
302706f2543Smrg    DMXConfigStringPtr pt;
303706f2543Smrg    int                argc   = 0;
304706f2543Smrg    char               **argv = NULL;
305706f2543Smrg
306706f2543Smrg    if (serverGeneration != 1) return; /* FIXME: only do once, for now */
307706f2543Smrg    if (!o || !o->string) return;
308706f2543Smrg    for (pt = o->option; pt; pt = pt->next) {
309706f2543Smrg        if (pt->string) {
310706f2543Smrg            ++argc;
311706f2543Smrg            argv = realloc(argv, (argc+1) * sizeof(*argv));
312706f2543Smrg            argv[argc] = (char *)pt->string;
313706f2543Smrg        }
314706f2543Smrg    }
315706f2543Smrg    argv[0] = NULL;
316706f2543Smrg    ProcessCommandLine(argc+1, argv);
317706f2543Smrg    free(argv);
318706f2543Smrg}
319706f2543Smrg
320706f2543Smrgstatic void dmxConfigCopyFromParam(DMXConfigParamPtr p)
321706f2543Smrg{
322706f2543Smrg    const char **argv;
323706f2543Smrg    int        argc;
324706f2543Smrg
325706f2543Smrg    if ((argv = dmxConfigLookupParam(p, "xkbrules", &argc)) && argc == 2) {
326706f2543Smrg        dmxConfigSetXkbRules(argv[1]);
327706f2543Smrg    } else if ((argv = dmxConfigLookupParam(p, "xkbmodel", &argc))
328706f2543Smrg               && argc == 2) {
329706f2543Smrg        dmxConfigSetXkbModel(argv[1]);
330706f2543Smrg    } else if ((argv = dmxConfigLookupParam(p, "xkblayout", &argc))
331706f2543Smrg               && argc == 2) {
332706f2543Smrg        dmxConfigSetXkbLayout(argv[1]);
333706f2543Smrg    } else if ((argv = dmxConfigLookupParam(p, "xkbvariant", &argc))
334706f2543Smrg               && argc == 2) {
335706f2543Smrg        dmxConfigSetXkbVariant(argv[1]);
336706f2543Smrg    } else if ((argv = dmxConfigLookupParam(p, "xkboptions", &argc))
337706f2543Smrg               && argc == 2) {
338706f2543Smrg        dmxConfigSetXkbOptions(argv[1]);
339706f2543Smrg    }
340706f2543Smrg}
341706f2543Smrg
342706f2543Smrgstatic void dmxConfigCopyData(DMXConfigVirtualPtr v)
343706f2543Smrg{
344706f2543Smrg    DMXConfigSubPtr sub;
345706f2543Smrg
346706f2543Smrg    if (v->dim) dmxSetWidthHeight(v->dim->x, v->dim->y);
347706f2543Smrg    else        dmxSetWidthHeight(0, 0);
348706f2543Smrg    for (sub = v->subentry; sub; sub = sub->next) {
349706f2543Smrg        switch (sub->type) {
350706f2543Smrg        case dmxConfigDisplay: dmxConfigCopyFromDisplay(sub->display); break;
351706f2543Smrg        case dmxConfigWall:    dmxConfigCopyFromWall(sub->wall);       break;
352706f2543Smrg        case dmxConfigOption:  dmxConfigCopyFromOption(sub->option);   break;
353706f2543Smrg        case dmxConfigParam:   dmxConfigCopyFromParam(sub->param);     break;
354706f2543Smrg        default:
355706f2543Smrg            dmxLog(dmxFatal,
356706f2543Smrg                   "dmxConfigCopyData: not a display, wall, or value\n");
357706f2543Smrg        }
358706f2543Smrg    }
359706f2543Smrg}
360706f2543Smrg
361706f2543Smrgstatic void dmxConfigFromCommandLine(void)
362706f2543Smrg{
363706f2543Smrg    DMXConfigListPtr pt;
364706f2543Smrg
365706f2543Smrg    dmxLog(dmxInfo, "Using configuration from command line\n");
366706f2543Smrg    for (pt = dmxConfigCmd.displays; pt; pt = pt->next) {
367706f2543Smrg        DMXScreenInfo *dmxScreen = dmxConfigAddDisplay(pt->name,
368706f2543Smrg                                                       0, 0, 0, 0, 0, 0,
369706f2543Smrg                                                       0, 0, 0, 0, 0, 0);
370706f2543Smrg        if (dmxNumScreens == 1) {
371706f2543Smrg            dmxScreen->where  = PosAbsolute;
372706f2543Smrg            dmxScreen->whereX = 0;
373706f2543Smrg            dmxScreen->whereY = 0;
374706f2543Smrg            dmxLog(dmxInfo, "Added %s at %d %d\n",
375706f2543Smrg                   dmxScreen->name, dmxScreen->whereX, dmxScreen->whereY);
376706f2543Smrg        } else {
377706f2543Smrg            dmxScreen->where          = PosRightOf;
378706f2543Smrg            dmxScreen->whereRefScreen = dmxNumScreens - 2;
379706f2543Smrg            if (dmxScreen->whereRefScreen < 0) dmxScreen->whereRefScreen = 0;
380706f2543Smrg            dmxLog(dmxInfo, "Added %s %s %s\n",
381706f2543Smrg                   dmxScreen->name,
382706f2543Smrg                   dmxScreen->where == PosBelow ? "below" : "right of",
383706f2543Smrg                   dmxScreens[dmxScreen->whereRefScreen].name);
384706f2543Smrg        }
385706f2543Smrg    }
386706f2543Smrg}
387706f2543Smrg
388706f2543Smrgstatic void dmxConfigFromConfigFile(void)
389706f2543Smrg{
390706f2543Smrg    DMXConfigEntryPtr pt;
391706f2543Smrg    const char        *name;
392706f2543Smrg
393706f2543Smrg    for (pt = dmxConfigEntry; pt; pt = pt->next) {
394706f2543Smrg                                /* FIXME -- if an input is specified, use it */
395706f2543Smrg        if (pt->type != dmxConfigVirtual) continue;
396706f2543Smrg        if ((name = dmxConfigMatch(dmxConfigCmd.config, pt))) {
397706f2543Smrg            dmxLog(dmxInfo, "Using configuration \"%s\"\n", name);
398706f2543Smrg            dmxConfigCopyData(pt->virtual);
399706f2543Smrg            return;
400706f2543Smrg        }
401706f2543Smrg    }
402706f2543Smrg    dmxLog(dmxFatal, "Could not find configuration \"%s\" in \"%s\"\n",
403706f2543Smrg           dmxConfigCmd.config, dmxConfigCmd.filename);
404706f2543Smrg}
405706f2543Smrg
406706f2543Smrgstatic void dmxConfigConfigInputs(void)
407706f2543Smrg{
408706f2543Smrg    DMXConfigListPtr pt;
409706f2543Smrg
410706f2543Smrg    if (dmxNumInputs) return;
411706f2543Smrg
412706f2543Smrg    if (dmxConfigCmd.inputs) {   /* Use command line */
413706f2543Smrg        for (pt = dmxConfigCmd.inputs; pt; pt = pt->next)
414706f2543Smrg            dmxConfigAddInput(pt->name, TRUE);
415706f2543Smrg    } else if (dmxNumScreens) { /* Use first display */
416706f2543Smrg        dmxConfigAddInput(dmxScreens[0].name, TRUE);
417706f2543Smrg    } else {                     /* Use dummy */
418706f2543Smrg        dmxConfigAddInput("dummy", TRUE);
419706f2543Smrg    }
420706f2543Smrg
421706f2543Smrg    if (dmxConfigCmd.xinputs) {  /* Non-core devices from command line */
422706f2543Smrg        for (pt = dmxConfigCmd.xinputs; pt; pt = pt->next)
423706f2543Smrg            dmxConfigAddInput(pt->name, FALSE);
424706f2543Smrg    }
425706f2543Smrg}
426706f2543Smrg
427706f2543Smrg/** Set up the appropriate global variables so that the DMX server will
428706f2543Smrg * be initialized using the configuration specified in the config file
429706f2543Smrg * and on the command line. */
430706f2543Smrgvoid dmxConfigConfigure(void)
431706f2543Smrg{
432706f2543Smrg    if (dmxConfigEntry) {
433706f2543Smrg        dmxConfigFreeEntry(dmxConfigEntry);
434706f2543Smrg        dmxConfigEntry = NULL;
435706f2543Smrg    }
436706f2543Smrg    if (dmxConfigCmd.filename) {
437706f2543Smrg        if (dmxConfigCmd.displays)
438706f2543Smrg            dmxLog(dmxWarning,
439706f2543Smrg                   "Using configuration file \"%s\" instead of command line\n",
440706f2543Smrg                   dmxConfigCmd.filename);
441706f2543Smrg        dmxConfigReadFile(dmxConfigCmd.filename, 0);
442706f2543Smrg        dmxConfigFromConfigFile();
443706f2543Smrg    } else {
444706f2543Smrg        if (dmxConfigCmd.config)
445706f2543Smrg            dmxLog(dmxWarning,
446706f2543Smrg                   "Configuration name (%s) without configuration file\n",
447706f2543Smrg                   dmxConfigCmd.config);
448706f2543Smrg        dmxConfigFromCommandLine();
449706f2543Smrg    }
450706f2543Smrg    dmxConfigConfigInputs();
451706f2543Smrg}
452706f2543Smrg
453706f2543Smrg/** This function determines the number of displays we WILL have and
454706f2543Smrg * sets MAXSCREENS to that value.  This is difficult since the number
455706f2543Smrg * depends on the command line (which is easy to count) or on the config
456706f2543Smrg * file, which has to be parsed. */
457706f2543Smrgvoid dmxConfigSetMaxScreens(void)
458706f2543Smrg{
459706f2543Smrg    static int processing = 0;
460706f2543Smrg
461706f2543Smrg    if (processing) return;     /* Prevent reentry via ProcessCommandLine */
462706f2543Smrg    processing = 1;
463706f2543Smrg    if (dmxConfigCmd.filename) {
464706f2543Smrg        if (!dmxNumScreens)
465706f2543Smrg            dmxConfigConfigure();
466706f2543Smrg#ifndef MAXSCREENS
467706f2543Smrg        SetMaxScreens(dmxNumScreens);
468706f2543Smrg#endif
469706f2543Smrg    } else
470706f2543Smrg#ifndef MAXSCREENS
471706f2543Smrg        SetMaxScreens(dmxDisplaysFromCommandLine);
472706f2543Smrg#endif
473706f2543Smrg    processing = 0;
474706f2543Smrg}
475706f2543Smrg
476706f2543Smrg/** This macro is used to generate the following access methods:
477706f2543Smrg * - dmxConfig{Set,Get}rules
478706f2543Smrg * - dmxConfig{Set,Get}model
479706f2543Smrg * - dmxConfig{Set,Get}layout
480706f2543Smrg * - dmxConfig{Set,Get}variant
481706f2543Smrg * - dmxConfig{Set,Get}options
482706f2543Smrg * These methods are used to read and write information about the keyboard. */
483706f2543Smrg
484706f2543Smrg#define GEN(param,glob,def)                                                   \
485706f2543Smrg void dmxConfigSet##glob(const char *param) {                                 \
486706f2543Smrg     if (dmx##glob) free((void *)dmx##glob);                                  \
487706f2543Smrg     dmx##glob = strdup(param);                                               \
488706f2543Smrg }                                                                            \
489706f2543Smrg char *dmxConfigGet##glob(void) {                                             \
490706f2543Smrg     return (char *)(dmx##glob ? dmx##glob : def);                            \
491706f2543Smrg }
492706f2543Smrg
493706f2543SmrgGEN(rules,   XkbRules,   XKB_DFLT_RULES)
494706f2543SmrgGEN(model,   XkbModel,   XKB_DFLT_MODEL)
495706f2543SmrgGEN(layout,  XkbLayout,  XKB_DFLT_LAYOUT)
496706f2543SmrgGEN(variant, XkbVariant, XKB_DFLT_VARIANT)
497706f2543SmrgGEN(options, XkbOptions, XKB_DFLT_OPTIONS)
498