xref: /OK3568_Linux_fs/external/xserver/hw/dmx/config/dmxconfig.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * All Rights Reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun  * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun  * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun  * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun  * subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun  * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun  * portions of the Software.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun  * SOFTWARE.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Rickard E. (Rik) Faith <faith@redhat.com>
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /** \file
35*4882a593Smuzhiyun  * Provides interface for reading DMX configuration files and for
36*4882a593Smuzhiyun  * combining that information with command-line configuration parameters. */
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
39*4882a593Smuzhiyun #include <dmx-config.h>
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include "dmx.h"
43*4882a593Smuzhiyun #include "dmxinput.h"
44*4882a593Smuzhiyun #include "dmxconfig.h"
45*4882a593Smuzhiyun #include "dmxparse.h"
46*4882a593Smuzhiyun #include "dmxlog.h"
47*4882a593Smuzhiyun #include "dmxcb.h"
48*4882a593Smuzhiyun #include "dmxstat.h"
49*4882a593Smuzhiyun #include "parser.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun extern int yydebug;
52*4882a593Smuzhiyun extern FILE *yyin;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun static char *dmxXkbRules;
55*4882a593Smuzhiyun static char *dmxXkbModel;
56*4882a593Smuzhiyun static char *dmxXkbLayout;
57*4882a593Smuzhiyun static char *dmxXkbVariant;
58*4882a593Smuzhiyun static char *dmxXkbOptions;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /** Stores lists of configuration information. */
61*4882a593Smuzhiyun typedef struct DMXConfigListStruct {
62*4882a593Smuzhiyun     const char *name;
63*4882a593Smuzhiyun     struct DMXConfigListStruct *next;
64*4882a593Smuzhiyun } DMXConfigList, *DMXConfigListPtr;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /** This stucture stores the parsed configuration information. */
67*4882a593Smuzhiyun typedef struct DMXConfigCmdStruct {
68*4882a593Smuzhiyun     const char *filename;
69*4882a593Smuzhiyun     const char *config;
70*4882a593Smuzhiyun     DMXConfigList *displays;
71*4882a593Smuzhiyun     DMXConfigList *inputs;
72*4882a593Smuzhiyun     DMXConfigList *xinputs;
73*4882a593Smuzhiyun } DMXConfigCmd, *DMXConfigCmdPtr;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun extern DMXConfigEntryPtr dmxConfigEntry;
76*4882a593Smuzhiyun static DMXConfigCmd dmxConfigCmd;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun static int dmxDisplaysFromCommandLine;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /** Make a note that \a display is the name of an X11 display that
81*4882a593Smuzhiyun  * should be initialized as a backend (output) display.  Called from
82*4882a593Smuzhiyun  * #ddxProcessArgument. */
83*4882a593Smuzhiyun void
dmxConfigStoreDisplay(const char * display)84*4882a593Smuzhiyun dmxConfigStoreDisplay(const char *display)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun     DMXConfigListPtr entry = malloc(sizeof(*entry));
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun     entry->name = strdup(display);
89*4882a593Smuzhiyun     entry->next = NULL;
90*4882a593Smuzhiyun     if (!dmxConfigCmd.displays)
91*4882a593Smuzhiyun         dmxConfigCmd.displays = entry;
92*4882a593Smuzhiyun     else {
93*4882a593Smuzhiyun         DMXConfigList *pt;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun         for (pt = dmxConfigCmd.displays; pt->next; pt = pt->next);
96*4882a593Smuzhiyun         if (!pt)
97*4882a593Smuzhiyun             dmxLog(dmxFatal, "dmxConfigStoreDisplay: end of list non-NULL\n");
98*4882a593Smuzhiyun         pt->next = entry;
99*4882a593Smuzhiyun     }
100*4882a593Smuzhiyun     ++dmxDisplaysFromCommandLine;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /** Make a note that \a input is the name of an X11 display that should
104*4882a593Smuzhiyun  * be used for input (either a backend or a console input device). */
105*4882a593Smuzhiyun void
dmxConfigStoreInput(const char * input)106*4882a593Smuzhiyun dmxConfigStoreInput(const char *input)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun     DMXConfigListPtr entry = malloc(sizeof(*entry));
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     entry->name = strdup(input);
111*4882a593Smuzhiyun     entry->next = NULL;
112*4882a593Smuzhiyun     if (!dmxConfigCmd.inputs)
113*4882a593Smuzhiyun         dmxConfigCmd.inputs = entry;
114*4882a593Smuzhiyun     else {
115*4882a593Smuzhiyun         DMXConfigList *pt;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun         for (pt = dmxConfigCmd.inputs; pt->next; pt = pt->next);
118*4882a593Smuzhiyun         if (!pt)
119*4882a593Smuzhiyun             dmxLog(dmxFatal, "dmxConfigStoreInput: end of list non-NULL\n");
120*4882a593Smuzhiyun         pt->next = entry;
121*4882a593Smuzhiyun     }
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /** Make a note that \a input is the name of an X11 display that should
125*4882a593Smuzhiyun  * be used for input from XInput extension devices. */
126*4882a593Smuzhiyun void
dmxConfigStoreXInput(const char * input)127*4882a593Smuzhiyun dmxConfigStoreXInput(const char *input)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun     DMXConfigListPtr entry = malloc(sizeof(*entry));
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     entry->name = strdup(input);
132*4882a593Smuzhiyun     entry->next = NULL;
133*4882a593Smuzhiyun     if (!dmxConfigCmd.xinputs)
134*4882a593Smuzhiyun         dmxConfigCmd.xinputs = entry;
135*4882a593Smuzhiyun     else {
136*4882a593Smuzhiyun         DMXConfigList *pt;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun         for (pt = dmxConfigCmd.xinputs; pt->next; pt = pt->next);
139*4882a593Smuzhiyun         if (!pt)
140*4882a593Smuzhiyun             dmxLog(dmxFatal, "dmxConfigStoreXInput: end of list non-NULL\n");
141*4882a593Smuzhiyun         pt->next = entry;
142*4882a593Smuzhiyun     }
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /** Make a note that \a file is the configuration file. */
146*4882a593Smuzhiyun void
dmxConfigStoreFile(const char * file)147*4882a593Smuzhiyun dmxConfigStoreFile(const char *file)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun     if (dmxConfigCmd.filename)
150*4882a593Smuzhiyun         dmxLog(dmxFatal, "Only one -configfile allowed\n");
151*4882a593Smuzhiyun     dmxConfigCmd.filename = strdup(file);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /** Make a note that \a config should be used as the configuration for
155*4882a593Smuzhiyun  * current instantiation of the DMX server. */
156*4882a593Smuzhiyun void
dmxConfigStoreConfig(const char * config)157*4882a593Smuzhiyun dmxConfigStoreConfig(const char *config)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun     if (dmxConfigCmd.config)
160*4882a593Smuzhiyun         dmxLog(dmxFatal, "Only one -config allowed\n");
161*4882a593Smuzhiyun     dmxConfigCmd.config = strdup(config);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun static int
dmxConfigReadFile(const char * filename,int debug)165*4882a593Smuzhiyun dmxConfigReadFile(const char *filename, int debug)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     FILE *str;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     if (!(str = fopen(filename, "r")))
170*4882a593Smuzhiyun         return -1;
171*4882a593Smuzhiyun     dmxLog(dmxInfo, "Reading configuration file \"%s\"\n", filename);
172*4882a593Smuzhiyun     yyin = str;
173*4882a593Smuzhiyun     yydebug = debug;
174*4882a593Smuzhiyun     yyparse();
175*4882a593Smuzhiyun     fclose(str);
176*4882a593Smuzhiyun     return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static const char *
dmxConfigMatch(const char * target,DMXConfigEntryPtr entry)180*4882a593Smuzhiyun dmxConfigMatch(const char *target, DMXConfigEntryPtr entry)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun     DMXConfigVirtualPtr v = entry->virtual;
183*4882a593Smuzhiyun     const char *name = NULL;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     if (v && v->name)
186*4882a593Smuzhiyun         name = v->name;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     if (v && !dmxConfigCmd.config)
189*4882a593Smuzhiyun         return v->name ? v->name : "<noname>";
190*4882a593Smuzhiyun     if (!name)
191*4882a593Smuzhiyun         return NULL;
192*4882a593Smuzhiyun     if (!strcmp(name, target))
193*4882a593Smuzhiyun         return name;
194*4882a593Smuzhiyun     return NULL;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static DMXScreenInfo *
dmxConfigAddDisplay(const char * name,int scrnWidth,int scrnHeight,int scrnX,int scrnY,int scrnXSign,int scrnYSign,int rootWidth,int rootHeight,int rootX,int rootY,int rootXSign,int rootYSign)198*4882a593Smuzhiyun dmxConfigAddDisplay(const char *name,
199*4882a593Smuzhiyun                     int scrnWidth, int scrnHeight,
200*4882a593Smuzhiyun                     int scrnX, int scrnY,
201*4882a593Smuzhiyun                     int scrnXSign, int scrnYSign,
202*4882a593Smuzhiyun                     int rootWidth, int rootHeight,
203*4882a593Smuzhiyun                     int rootX, int rootY, int rootXSign, int rootYSign)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     if (!(dmxScreens = reallocarray(dmxScreens, dmxNumScreens + 1,
208*4882a593Smuzhiyun                                     sizeof(*dmxScreens))))
209*4882a593Smuzhiyun         dmxLog(dmxFatal,
210*4882a593Smuzhiyun                "dmxConfigAddDisplay: realloc failed for screen %d (%s)\n",
211*4882a593Smuzhiyun                dmxNumScreens, name);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun     dmxScreen = &dmxScreens[dmxNumScreens];
214*4882a593Smuzhiyun     memset(dmxScreen, 0, sizeof(*dmxScreen));
215*4882a593Smuzhiyun     dmxScreen->name = name;
216*4882a593Smuzhiyun     dmxScreen->index = dmxNumScreens;
217*4882a593Smuzhiyun     dmxScreen->scrnWidth = scrnWidth;
218*4882a593Smuzhiyun     dmxScreen->scrnHeight = scrnHeight;
219*4882a593Smuzhiyun     dmxScreen->scrnX = scrnX;
220*4882a593Smuzhiyun     dmxScreen->scrnY = scrnY;
221*4882a593Smuzhiyun     dmxScreen->scrnXSign = scrnXSign;
222*4882a593Smuzhiyun     dmxScreen->scrnYSign = scrnYSign;
223*4882a593Smuzhiyun     dmxScreen->rootWidth = rootWidth;
224*4882a593Smuzhiyun     dmxScreen->rootHeight = rootHeight;
225*4882a593Smuzhiyun     dmxScreen->rootX = rootX;
226*4882a593Smuzhiyun     dmxScreen->rootY = rootY;
227*4882a593Smuzhiyun     dmxScreen->stat = dmxStatAlloc();
228*4882a593Smuzhiyun     ++dmxNumScreens;
229*4882a593Smuzhiyun     return dmxScreen;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun DMXInputInfo *
dmxConfigAddInput(const char * name,int core)233*4882a593Smuzhiyun dmxConfigAddInput(const char *name, int core)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun     DMXInputInfo *dmxInput;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     if (!(dmxInputs = reallocarray(dmxInputs, dmxNumInputs + 1,
238*4882a593Smuzhiyun                                    sizeof(*dmxInputs))))
239*4882a593Smuzhiyun         dmxLog(dmxFatal,
240*4882a593Smuzhiyun                "dmxConfigAddInput: realloc failed for input %d (%s)\n",
241*4882a593Smuzhiyun                dmxNumInputs, name);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun     dmxInput = &dmxInputs[dmxNumInputs];
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun     memset(dmxInput, 0, sizeof(*dmxInput));
246*4882a593Smuzhiyun     dmxInput->name = name;
247*4882a593Smuzhiyun     dmxInput->inputIdx = dmxNumInputs;
248*4882a593Smuzhiyun     dmxInput->scrnIdx = -1;
249*4882a593Smuzhiyun     dmxInput->core = core;
250*4882a593Smuzhiyun     ++dmxNumInputs;
251*4882a593Smuzhiyun     return dmxInput;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun static void
dmxConfigCopyFromDisplay(DMXConfigDisplayPtr d)255*4882a593Smuzhiyun dmxConfigCopyFromDisplay(DMXConfigDisplayPtr d)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun     dmxScreen = dmxConfigAddDisplay(d->name,
260*4882a593Smuzhiyun                                     d->scrnWidth, d->scrnHeight,
261*4882a593Smuzhiyun                                     d->scrnX, d->scrnY,
262*4882a593Smuzhiyun                                     d->scrnXSign, d->scrnYSign,
263*4882a593Smuzhiyun                                     d->rootWidth, d->rootHeight,
264*4882a593Smuzhiyun                                     d->rootX, d->rootY,
265*4882a593Smuzhiyun                                     d->rootXSign, d->rootXSign);
266*4882a593Smuzhiyun     dmxScreen->where = PosAbsolute;
267*4882a593Smuzhiyun     dmxScreen->whereX = d->rootXOrigin;
268*4882a593Smuzhiyun     dmxScreen->whereY = d->rootYOrigin;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun static void
dmxConfigCopyFromWall(DMXConfigWallPtr w)272*4882a593Smuzhiyun dmxConfigCopyFromWall(DMXConfigWallPtr w)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun     DMXConfigStringPtr pt;
275*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen;
276*4882a593Smuzhiyun     int edge = dmxNumScreens;
277*4882a593Smuzhiyun     int last = dmxNumScreens;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     if (!w->xwall && !w->ywall) {       /* Try to make it square */
280*4882a593Smuzhiyun         int count;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun         for (pt = w->nameList, count = 0; pt; pt = pt->next)
283*4882a593Smuzhiyun             ++count;
284*4882a593Smuzhiyun         w->xwall = sqrt(count) + .5;
285*4882a593Smuzhiyun     }
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     for (pt = w->nameList; pt; pt = pt->next) {
288*4882a593Smuzhiyun         dmxScreen = dmxConfigAddDisplay(pt->string, w->width, w->height,
289*4882a593Smuzhiyun                                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
290*4882a593Smuzhiyun         if (pt == w->nameList) {        /* Upper left */
291*4882a593Smuzhiyun             dmxScreen->where = PosAbsolute;
292*4882a593Smuzhiyun             dmxScreen->whereX = 0;
293*4882a593Smuzhiyun             dmxScreen->whereY = 0;
294*4882a593Smuzhiyun         }
295*4882a593Smuzhiyun         else if (w->xwall) {    /* Tile left to right, then top to bottom */
296*4882a593Smuzhiyun             if (!((dmxNumScreens - 1) % w->xwall)) {
297*4882a593Smuzhiyun                 dmxScreen->where = PosBelow;
298*4882a593Smuzhiyun                 dmxScreen->whereRefScreen = edge;
299*4882a593Smuzhiyun                 edge = dmxNumScreens - 1;
300*4882a593Smuzhiyun             }
301*4882a593Smuzhiyun             else {
302*4882a593Smuzhiyun                 dmxScreen->where = PosRightOf;
303*4882a593Smuzhiyun                 dmxScreen->whereRefScreen = last;
304*4882a593Smuzhiyun             }
305*4882a593Smuzhiyun         }
306*4882a593Smuzhiyun         else {                  /* Tile top to bottom, then left to right */
307*4882a593Smuzhiyun             if (!((dmxNumScreens - 1) % w->ywall)) {
308*4882a593Smuzhiyun                 dmxScreen->where = PosRightOf;
309*4882a593Smuzhiyun                 dmxScreen->whereRefScreen = edge;
310*4882a593Smuzhiyun                 edge = dmxNumScreens - 1;
311*4882a593Smuzhiyun             }
312*4882a593Smuzhiyun             else {
313*4882a593Smuzhiyun                 dmxScreen->where = PosBelow;
314*4882a593Smuzhiyun                 dmxScreen->whereRefScreen = last;
315*4882a593Smuzhiyun             }
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun         }
318*4882a593Smuzhiyun         last = dmxNumScreens - 1;
319*4882a593Smuzhiyun         if (dmxScreen->where == PosAbsolute)
320*4882a593Smuzhiyun             dmxLog(dmxInfo, "Added %s at %d %d\n",
321*4882a593Smuzhiyun                    pt->string, dmxScreen->whereX, dmxScreen->whereY);
322*4882a593Smuzhiyun         else
323*4882a593Smuzhiyun             dmxLog(dmxInfo, "Added %s %s %s\n",
324*4882a593Smuzhiyun                    pt->string,
325*4882a593Smuzhiyun                    dmxScreen->where == PosBelow ? "below" : "right of",
326*4882a593Smuzhiyun                    dmxScreens[dmxScreen->whereRefScreen].name);
327*4882a593Smuzhiyun     }
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun static void
dmxConfigCopyFromOption(DMXConfigOptionPtr o)331*4882a593Smuzhiyun dmxConfigCopyFromOption(DMXConfigOptionPtr o)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun     DMXConfigStringPtr pt;
334*4882a593Smuzhiyun     int argc = 0;
335*4882a593Smuzhiyun     char **argv = NULL;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun     if (serverGeneration != 1)
338*4882a593Smuzhiyun         return;                 /* FIXME: only do once, for now */
339*4882a593Smuzhiyun     if (!o || !o->string)
340*4882a593Smuzhiyun         return;
341*4882a593Smuzhiyun     for (pt = o->option; pt; pt = pt->next) {
342*4882a593Smuzhiyun         if (pt->string) {
343*4882a593Smuzhiyun             ++argc;
344*4882a593Smuzhiyun             argv = reallocarray(argv, argc + 1, sizeof(*argv));
345*4882a593Smuzhiyun             argv[argc] = (char *) pt->string;
346*4882a593Smuzhiyun         }
347*4882a593Smuzhiyun     }
348*4882a593Smuzhiyun     argv[0] = NULL;
349*4882a593Smuzhiyun     ProcessCommandLine(argc + 1, argv);
350*4882a593Smuzhiyun     free(argv);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun static void
dmxConfigCopyFromParam(DMXConfigParamPtr p)354*4882a593Smuzhiyun dmxConfigCopyFromParam(DMXConfigParamPtr p)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun     const char **argv;
357*4882a593Smuzhiyun     int argc;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun     if ((argv = dmxConfigLookupParam(p, "xkbrules", &argc)) && argc == 2) {
360*4882a593Smuzhiyun         dmxConfigSetXkbRules(argv[1]);
361*4882a593Smuzhiyun     }
362*4882a593Smuzhiyun     else if ((argv = dmxConfigLookupParam(p, "xkbmodel", &argc))
363*4882a593Smuzhiyun              && argc == 2) {
364*4882a593Smuzhiyun         dmxConfigSetXkbModel(argv[1]);
365*4882a593Smuzhiyun     }
366*4882a593Smuzhiyun     else if ((argv = dmxConfigLookupParam(p, "xkblayout", &argc))
367*4882a593Smuzhiyun              && argc == 2) {
368*4882a593Smuzhiyun         dmxConfigSetXkbLayout(argv[1]);
369*4882a593Smuzhiyun     }
370*4882a593Smuzhiyun     else if ((argv = dmxConfigLookupParam(p, "xkbvariant", &argc))
371*4882a593Smuzhiyun              && argc == 2) {
372*4882a593Smuzhiyun         dmxConfigSetXkbVariant(argv[1]);
373*4882a593Smuzhiyun     }
374*4882a593Smuzhiyun     else if ((argv = dmxConfigLookupParam(p, "xkboptions", &argc))
375*4882a593Smuzhiyun              && argc == 2) {
376*4882a593Smuzhiyun         dmxConfigSetXkbOptions(argv[1]);
377*4882a593Smuzhiyun     }
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun static void
dmxConfigCopyData(DMXConfigVirtualPtr v)381*4882a593Smuzhiyun dmxConfigCopyData(DMXConfigVirtualPtr v)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun     DMXConfigSubPtr sub;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun     if (v->dim)
386*4882a593Smuzhiyun         dmxSetWidthHeight(v->dim->x, v->dim->y);
387*4882a593Smuzhiyun     else
388*4882a593Smuzhiyun         dmxSetWidthHeight(0, 0);
389*4882a593Smuzhiyun     for (sub = v->subentry; sub; sub = sub->next) {
390*4882a593Smuzhiyun         switch (sub->type) {
391*4882a593Smuzhiyun         case dmxConfigDisplay:
392*4882a593Smuzhiyun             dmxConfigCopyFromDisplay(sub->display);
393*4882a593Smuzhiyun             break;
394*4882a593Smuzhiyun         case dmxConfigWall:
395*4882a593Smuzhiyun             dmxConfigCopyFromWall(sub->wall);
396*4882a593Smuzhiyun             break;
397*4882a593Smuzhiyun         case dmxConfigOption:
398*4882a593Smuzhiyun             dmxConfigCopyFromOption(sub->option);
399*4882a593Smuzhiyun             break;
400*4882a593Smuzhiyun         case dmxConfigParam:
401*4882a593Smuzhiyun             dmxConfigCopyFromParam(sub->param);
402*4882a593Smuzhiyun             break;
403*4882a593Smuzhiyun         default:
404*4882a593Smuzhiyun             dmxLog(dmxFatal,
405*4882a593Smuzhiyun                    "dmxConfigCopyData: not a display, wall, or value\n");
406*4882a593Smuzhiyun         }
407*4882a593Smuzhiyun     }
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun static void
dmxConfigFromCommandLine(void)411*4882a593Smuzhiyun dmxConfigFromCommandLine(void)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun     DMXConfigListPtr pt;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun     dmxLog(dmxInfo, "Using configuration from command line\n");
416*4882a593Smuzhiyun     for (pt = dmxConfigCmd.displays; pt; pt = pt->next) {
417*4882a593Smuzhiyun         DMXScreenInfo *dmxScreen = dmxConfigAddDisplay(pt->name,
418*4882a593Smuzhiyun                                                        0, 0, 0, 0, 0, 0,
419*4882a593Smuzhiyun                                                        0, 0, 0, 0, 0, 0);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun         if (dmxNumScreens == 1) {
422*4882a593Smuzhiyun             dmxScreen->where = PosAbsolute;
423*4882a593Smuzhiyun             dmxScreen->whereX = 0;
424*4882a593Smuzhiyun             dmxScreen->whereY = 0;
425*4882a593Smuzhiyun             dmxLog(dmxInfo, "Added %s at %d %d\n",
426*4882a593Smuzhiyun                    dmxScreen->name, dmxScreen->whereX, dmxScreen->whereY);
427*4882a593Smuzhiyun         }
428*4882a593Smuzhiyun         else {
429*4882a593Smuzhiyun             dmxScreen->where = PosRightOf;
430*4882a593Smuzhiyun             dmxScreen->whereRefScreen = dmxNumScreens - 2;
431*4882a593Smuzhiyun             if (dmxScreen->whereRefScreen < 0)
432*4882a593Smuzhiyun                 dmxScreen->whereRefScreen = 0;
433*4882a593Smuzhiyun             dmxLog(dmxInfo, "Added %s %s %s\n",
434*4882a593Smuzhiyun                    dmxScreen->name,
435*4882a593Smuzhiyun                    dmxScreen->where == PosBelow ? "below" : "right of",
436*4882a593Smuzhiyun                    dmxScreens[dmxScreen->whereRefScreen].name);
437*4882a593Smuzhiyun         }
438*4882a593Smuzhiyun     }
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun static void
dmxConfigFromConfigFile(void)442*4882a593Smuzhiyun dmxConfigFromConfigFile(void)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun     DMXConfigEntryPtr pt;
445*4882a593Smuzhiyun     const char *name;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun     for (pt = dmxConfigEntry; pt; pt = pt->next) {
448*4882a593Smuzhiyun         /* FIXME -- if an input is specified, use it */
449*4882a593Smuzhiyun         if (pt->type != dmxConfigVirtual)
450*4882a593Smuzhiyun             continue;
451*4882a593Smuzhiyun         if ((name = dmxConfigMatch(dmxConfigCmd.config, pt))) {
452*4882a593Smuzhiyun             dmxLog(dmxInfo, "Using configuration \"%s\"\n", name);
453*4882a593Smuzhiyun             dmxConfigCopyData(pt->virtual);
454*4882a593Smuzhiyun             return;
455*4882a593Smuzhiyun         }
456*4882a593Smuzhiyun     }
457*4882a593Smuzhiyun     dmxLog(dmxFatal, "Could not find configuration \"%s\" in \"%s\"\n",
458*4882a593Smuzhiyun            dmxConfigCmd.config, dmxConfigCmd.filename);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun static void
dmxConfigConfigInputs(void)462*4882a593Smuzhiyun dmxConfigConfigInputs(void)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun     DMXConfigListPtr pt;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun     if (dmxNumInputs)
467*4882a593Smuzhiyun         return;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun     if (dmxConfigCmd.inputs) {  /* Use command line */
470*4882a593Smuzhiyun         for (pt = dmxConfigCmd.inputs; pt; pt = pt->next)
471*4882a593Smuzhiyun             dmxConfigAddInput(pt->name, TRUE);
472*4882a593Smuzhiyun     }
473*4882a593Smuzhiyun     else if (dmxNumScreens) {   /* Use first display */
474*4882a593Smuzhiyun         dmxConfigAddInput(dmxScreens[0].name, TRUE);
475*4882a593Smuzhiyun     }
476*4882a593Smuzhiyun     else {                      /* Use dummy */
477*4882a593Smuzhiyun         dmxConfigAddInput("dummy", TRUE);
478*4882a593Smuzhiyun     }
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun     if (dmxConfigCmd.xinputs) { /* Non-core devices from command line */
481*4882a593Smuzhiyun         for (pt = dmxConfigCmd.xinputs; pt; pt = pt->next)
482*4882a593Smuzhiyun             dmxConfigAddInput(pt->name, FALSE);
483*4882a593Smuzhiyun     }
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun /** Set up the appropriate global variables so that the DMX server will
487*4882a593Smuzhiyun  * be initialized using the configuration specified in the config file
488*4882a593Smuzhiyun  * and on the command line. */
489*4882a593Smuzhiyun void
dmxConfigConfigure(void)490*4882a593Smuzhiyun dmxConfigConfigure(void)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun     if (dmxConfigEntry) {
493*4882a593Smuzhiyun         dmxConfigFreeEntry(dmxConfigEntry);
494*4882a593Smuzhiyun         dmxConfigEntry = NULL;
495*4882a593Smuzhiyun     }
496*4882a593Smuzhiyun     if (dmxConfigCmd.filename) {
497*4882a593Smuzhiyun         if (dmxConfigCmd.displays)
498*4882a593Smuzhiyun             dmxLog(dmxWarning,
499*4882a593Smuzhiyun                    "Using configuration file \"%s\" instead of command line\n",
500*4882a593Smuzhiyun                    dmxConfigCmd.filename);
501*4882a593Smuzhiyun         dmxConfigReadFile(dmxConfigCmd.filename, 0);
502*4882a593Smuzhiyun         dmxConfigFromConfigFile();
503*4882a593Smuzhiyun     }
504*4882a593Smuzhiyun     else {
505*4882a593Smuzhiyun         if (dmxConfigCmd.config)
506*4882a593Smuzhiyun             dmxLog(dmxWarning,
507*4882a593Smuzhiyun                    "Configuration name (%s) without configuration file\n",
508*4882a593Smuzhiyun                    dmxConfigCmd.config);
509*4882a593Smuzhiyun         dmxConfigFromCommandLine();
510*4882a593Smuzhiyun     }
511*4882a593Smuzhiyun     dmxConfigConfigInputs();
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun /** This function determines the number of displays we WILL have and
515*4882a593Smuzhiyun  * sets MAXSCREENS to that value.  This is difficult since the number
516*4882a593Smuzhiyun  * depends on the command line (which is easy to count) or on the config
517*4882a593Smuzhiyun  * file, which has to be parsed. */
518*4882a593Smuzhiyun void
dmxConfigSetMaxScreens(void)519*4882a593Smuzhiyun dmxConfigSetMaxScreens(void)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun     static int processing = 0;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun     if (processing)
524*4882a593Smuzhiyun         return;                 /* Prevent reentry via ProcessCommandLine */
525*4882a593Smuzhiyun     processing = 1;
526*4882a593Smuzhiyun     if (dmxConfigCmd.filename) {
527*4882a593Smuzhiyun         if (!dmxNumScreens)
528*4882a593Smuzhiyun             dmxConfigConfigure();
529*4882a593Smuzhiyun #ifndef MAXSCREENS
530*4882a593Smuzhiyun         SetMaxScreens(dmxNumScreens);
531*4882a593Smuzhiyun #endif
532*4882a593Smuzhiyun     }
533*4882a593Smuzhiyun     else
534*4882a593Smuzhiyun #ifndef MAXSCREENS
535*4882a593Smuzhiyun         SetMaxScreens(dmxDisplaysFromCommandLine);
536*4882a593Smuzhiyun #endif
537*4882a593Smuzhiyun     processing = 0;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun /** This macro is used to generate the following access methods:
541*4882a593Smuzhiyun  * - dmxConfig{Set,Get}rules
542*4882a593Smuzhiyun  * - dmxConfig{Set,Get}model
543*4882a593Smuzhiyun  * - dmxConfig{Set,Get}layout
544*4882a593Smuzhiyun  * - dmxConfig{Set,Get}variant
545*4882a593Smuzhiyun  * - dmxConfig{Set,Get}options
546*4882a593Smuzhiyun  * These methods are used to read and write information about the keyboard. */
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun #define GEN(param,glob,def)                                                   \
549*4882a593Smuzhiyun  void dmxConfigSet##glob(const char *param) {                                 \
550*4882a593Smuzhiyun      if (dmx##glob) free((void *)dmx##glob);                                  \
551*4882a593Smuzhiyun      dmx##glob = strdup(param);                                               \
552*4882a593Smuzhiyun  }                                                                            \
553*4882a593Smuzhiyun  char *dmxConfigGet##glob(void) {                                             \
554*4882a593Smuzhiyun      return (char *)(dmx##glob ? dmx##glob : def);                            \
555*4882a593Smuzhiyun  }
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun GEN(rules, XkbRules, XKB_DFLT_RULES)
558*4882a593Smuzhiyun     GEN(model, XkbModel, XKB_DFLT_MODEL)
559*4882a593Smuzhiyun     GEN(layout, XkbLayout, XKB_DFLT_LAYOUT)
560*4882a593Smuzhiyun     GEN(variant, XkbVariant, XKB_DFLT_VARIANT)
561*4882a593Smuzhiyun     GEN(options, XkbOptions, XKB_DFLT_OPTIONS)
562