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