Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / parser / Layout.c
CommitLineData
a09e091a
JB
1/*
2 *
3 * Copyright (c) 1997 Metro Link Incorporated
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the Metro Link shall not be
24 * used in advertising or otherwise to promote the sale, use or other dealings
25 * in this Software without prior written authorization from Metro Link.
26 *
27 */
28/*
29 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47 * OTHER DEALINGS IN THE SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the copyright holder(s)
50 * and author(s) shall not be used in advertising or otherwise to promote
51 * the sale, use or other dealings in this Software without prior written
52 * authorization from the copyright holder(s) and author(s).
53 */
54
55#ifdef HAVE_XORG_CONFIG_H
56#include <xorg-config.h>
57#endif
58
59#include "xf86Parser.h"
60#include "xf86tokens.h"
61#include "Configint.h"
62#include <string.h>
63#include "optionstr.h"
64
65/* Needed for auto server layout */
66extern int xf86CheckBoolOption(void *optlist, const char *name, int deflt);
67
68extern LexRec val;
69
70static xf86ConfigSymTabRec LayoutTab[] = {
71 {ENDSECTION, "endsection"},
72 {SCREEN, "screen"},
73 {IDENTIFIER, "identifier"},
74 {INACTIVE, "inactive"},
75 {INPUTDEVICE, "inputdevice"},
76 {OPTION, "option"},
77 {-1, ""},
78};
79
80static xf86ConfigSymTabRec AdjTab[] = {
81 {RIGHTOF, "rightof"},
82 {LEFTOF, "leftof"},
83 {ABOVE, "above"},
84 {BELOW, "below"},
85 {RELATIVE, "relative"},
86 {ABSOLUTE, "absolute"},
87 {-1, ""},
88};
89
90#define CLEANUP xf86freeLayoutList
91
92XF86ConfLayoutPtr
93xf86parseLayoutSection(void)
94{
95 int has_ident = FALSE;
96 int token;
97
98 parsePrologue(XF86ConfLayoutPtr, XF86ConfLayoutRec)
99
100 while ((token = xf86getToken(LayoutTab)) != ENDSECTION) {
101 switch (token) {
102 case COMMENT:
103 ptr->lay_comment = xf86addComment(ptr->lay_comment, val.str);
104 break;
105 case IDENTIFIER:
106 if (xf86getSubToken(&(ptr->lay_comment)) != STRING)
107 Error(QUOTE_MSG, "Identifier");
108 if (has_ident == TRUE)
109 Error(MULTIPLE_MSG, "Identifier");
110 ptr->lay_identifier = val.str;
111 has_ident = TRUE;
112 break;
113 case INACTIVE:
114 {
115 XF86ConfInactivePtr iptr;
116
117 iptr = calloc(1, sizeof(XF86ConfInactiveRec));
118 iptr->list.next = NULL;
119 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
120 free(iptr);
121 Error(INACTIVE_MSG);
122 }
123 iptr->inactive_device_str = val.str;
124 ptr->lay_inactive_lst = (XF86ConfInactivePtr)
125 xf86addListItem((glp) ptr->lay_inactive_lst, (glp) iptr);
126 }
127 break;
128 case SCREEN:
129 {
130 XF86ConfAdjacencyPtr aptr;
131 int absKeyword = 0;
132
133 aptr = calloc(1, sizeof(XF86ConfAdjacencyRec));
134 aptr->list.next = NULL;
135 aptr->adj_scrnum = -1;
136 aptr->adj_where = CONF_ADJ_OBSOLETE;
137 aptr->adj_x = 0;
138 aptr->adj_y = 0;
139 aptr->adj_refscreen = NULL;
140 if ((token = xf86getSubToken(&(ptr->lay_comment))) == NUMBER)
141 aptr->adj_scrnum = val.num;
142 else
143 xf86unGetToken(token);
144 token = xf86getSubToken(&(ptr->lay_comment));
145 if (token != STRING) {
146 free(aptr);
147 Error(SCREEN_MSG);
148 }
149 aptr->adj_screen_str = val.str;
150
151 token = xf86getSubTokenWithTab(&(ptr->lay_comment), AdjTab);
152 switch (token) {
153 case RIGHTOF:
154 aptr->adj_where = CONF_ADJ_RIGHTOF;
155 break;
156 case LEFTOF:
157 aptr->adj_where = CONF_ADJ_LEFTOF;
158 break;
159 case ABOVE:
160 aptr->adj_where = CONF_ADJ_ABOVE;
161 break;
162 case BELOW:
163 aptr->adj_where = CONF_ADJ_BELOW;
164 break;
165 case RELATIVE:
166 aptr->adj_where = CONF_ADJ_RELATIVE;
167 break;
168 case ABSOLUTE:
169 aptr->adj_where = CONF_ADJ_ABSOLUTE;
170 absKeyword = 1;
171 break;
172 case EOF_TOKEN:
173 free(aptr);
174 Error(UNEXPECTED_EOF_MSG);
175 break;
176 default:
177 xf86unGetToken(token);
178 token = xf86getSubToken(&(ptr->lay_comment));
179 if (token == STRING)
180 aptr->adj_where = CONF_ADJ_OBSOLETE;
181 else
182 aptr->adj_where = CONF_ADJ_ABSOLUTE;
183 }
184 switch (aptr->adj_where) {
185 case CONF_ADJ_ABSOLUTE:
186 if (absKeyword)
187 token = xf86getSubToken(&(ptr->lay_comment));
188 if (token == NUMBER) {
189 aptr->adj_x = val.num;
190 token = xf86getSubToken(&(ptr->lay_comment));
191 if (token != NUMBER) {
192 free(aptr);
193 Error(INVALID_SCR_MSG);
194 }
195 aptr->adj_y = val.num;
196 }
197 else {
198 if (absKeyword) {
199 free(aptr);
200 Error(INVALID_SCR_MSG);
201 }
202 else
203 xf86unGetToken(token);
204 }
205 break;
206 case CONF_ADJ_RIGHTOF:
207 case CONF_ADJ_LEFTOF:
208 case CONF_ADJ_ABOVE:
209 case CONF_ADJ_BELOW:
210 case CONF_ADJ_RELATIVE:
211 token = xf86getSubToken(&(ptr->lay_comment));
212 if (token != STRING) {
213 free(aptr);
214 Error(INVALID_SCR_MSG);
215 }
216 aptr->adj_refscreen = val.str;
217 if (aptr->adj_where == CONF_ADJ_RELATIVE) {
218 token = xf86getSubToken(&(ptr->lay_comment));
219 if (token != NUMBER) {
220 free(aptr);
221 Error(INVALID_SCR_MSG);
222 }
223 aptr->adj_x = val.num;
224 token = xf86getSubToken(&(ptr->lay_comment));
225 if (token != NUMBER) {
226 free(aptr);
227 Error(INVALID_SCR_MSG);
228 }
229 aptr->adj_y = val.num;
230 }
231 break;
232 case CONF_ADJ_OBSOLETE:
233 /* top */
234 aptr->adj_top_str = val.str;
235
236 /* bottom */
237 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
238 free(aptr);
239 Error(SCREEN_MSG);
240 }
241 aptr->adj_bottom_str = val.str;
242
243 /* left */
244 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
245 free(aptr);
246 Error(SCREEN_MSG);
247 }
248 aptr->adj_left_str = val.str;
249
250 /* right */
251 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
252 free(aptr);
253 Error(SCREEN_MSG);
254 }
255 aptr->adj_right_str = val.str;
256
257 }
258 ptr->lay_adjacency_lst = (XF86ConfAdjacencyPtr)
259 xf86addListItem((glp) ptr->lay_adjacency_lst, (glp) aptr);
260 }
261 break;
262 case INPUTDEVICE:
263 {
264 XF86ConfInputrefPtr iptr;
265
266 iptr = calloc(1, sizeof(XF86ConfInputrefRec));
267 iptr->list.next = NULL;
268 iptr->iref_option_lst = NULL;
269 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
270 free(iptr);
271 Error(INPUTDEV_MSG);
272 }
273 iptr->iref_inputdev_str = val.str;
274 while ((token = xf86getSubToken(&(ptr->lay_comment))) == STRING) {
275 iptr->iref_option_lst =
276 xf86addNewOption(iptr->iref_option_lst, val.str, NULL);
277 }
278 xf86unGetToken(token);
279 ptr->lay_input_lst = (XF86ConfInputrefPtr)
280 xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
281 }
282 break;
283 case OPTION:
284 ptr->lay_option_lst = xf86parseOption(ptr->lay_option_lst);
285 break;
286 case EOF_TOKEN:
287 Error(UNEXPECTED_EOF_MSG);
288 break;
289 default:
290 Error(INVALID_KEYWORD_MSG, xf86tokenString());
291 break;
292 }
293 }
294
295 if (!has_ident)
296 Error(NO_IDENT_MSG);
297
298#ifdef DEBUG
299 printf("Layout section parsed\n");
300#endif
301
302 return ptr;
303}
304
305#undef CLEANUP
306
307void
308xf86printLayoutSection(FILE * cf, XF86ConfLayoutPtr ptr)
309{
310 XF86ConfAdjacencyPtr aptr;
311 XF86ConfInactivePtr iptr;
312 XF86ConfInputrefPtr inptr;
313 XF86OptionPtr optr;
314
315 while (ptr) {
316 fprintf(cf, "Section \"ServerLayout\"\n");
317 if (ptr->lay_comment)
318 fprintf(cf, "%s", ptr->lay_comment);
319 if (ptr->lay_identifier)
320 fprintf(cf, "\tIdentifier \"%s\"\n", ptr->lay_identifier);
321
322 for (aptr = ptr->lay_adjacency_lst; aptr; aptr = aptr->list.next) {
323 fprintf(cf, "\tScreen ");
324 if (aptr->adj_scrnum >= 0)
325 fprintf(cf, "%2d", aptr->adj_scrnum);
326 else
327 fprintf(cf, " ");
328 fprintf(cf, " \"%s\"", aptr->adj_screen_str);
329 switch (aptr->adj_where) {
330 case CONF_ADJ_OBSOLETE:
331 fprintf(cf, " \"%s\"", aptr->adj_top_str);
332 fprintf(cf, " \"%s\"", aptr->adj_bottom_str);
333 fprintf(cf, " \"%s\"", aptr->adj_right_str);
334 fprintf(cf, " \"%s\"\n", aptr->adj_left_str);
335 break;
336 case CONF_ADJ_ABSOLUTE:
337 if (aptr->adj_x != -1)
338 fprintf(cf, " %d %d\n", aptr->adj_x, aptr->adj_y);
339 else
340 fprintf(cf, "\n");
341 break;
342 case CONF_ADJ_RIGHTOF:
343 fprintf(cf, " RightOf \"%s\"\n", aptr->adj_refscreen);
344 break;
345 case CONF_ADJ_LEFTOF:
346 fprintf(cf, " LeftOf \"%s\"\n", aptr->adj_refscreen);
347 break;
348 case CONF_ADJ_ABOVE:
349 fprintf(cf, " Above \"%s\"\n", aptr->adj_refscreen);
350 break;
351 case CONF_ADJ_BELOW:
352 fprintf(cf, " Below \"%s\"\n", aptr->adj_refscreen);
353 break;
354 case CONF_ADJ_RELATIVE:
355 fprintf(cf, " Relative \"%s\" %d %d\n", aptr->adj_refscreen,
356 aptr->adj_x, aptr->adj_y);
357 break;
358 }
359 }
360 for (iptr = ptr->lay_inactive_lst; iptr; iptr = iptr->list.next)
361 fprintf(cf, "\tInactive \"%s\"\n", iptr->inactive_device_str);
362 for (inptr = ptr->lay_input_lst; inptr; inptr = inptr->list.next) {
363 fprintf(cf, "\tInputDevice \"%s\"", inptr->iref_inputdev_str);
364 for (optr = inptr->iref_option_lst; optr; optr = optr->list.next) {
365 fprintf(cf, " \"%s\"", optr->opt_name);
366 }
367 fprintf(cf, "\n");
368 }
369 xf86printOptionList(cf, ptr->lay_option_lst, 1);
370 fprintf(cf, "EndSection\n\n");
371 ptr = ptr->list.next;
372 }
373}
374
375static void
376xf86freeAdjacencyList(XF86ConfAdjacencyPtr ptr)
377{
378 XF86ConfAdjacencyPtr prev;
379
380 while (ptr) {
381 TestFree(ptr->adj_screen_str);
382 TestFree(ptr->adj_top_str);
383 TestFree(ptr->adj_bottom_str);
384 TestFree(ptr->adj_left_str);
385 TestFree(ptr->adj_right_str);
386
387 prev = ptr;
388 ptr = ptr->list.next;
389 free(prev);
390 }
391
392}
393
394static void
395xf86freeInputrefList(XF86ConfInputrefPtr ptr)
396{
397 XF86ConfInputrefPtr prev;
398
399 while (ptr) {
400 TestFree(ptr->iref_inputdev_str);
401 xf86optionListFree(ptr->iref_option_lst);
402 prev = ptr;
403 ptr = ptr->list.next;
404 free(prev);
405 }
406
407}
408
409void
410xf86freeLayoutList(XF86ConfLayoutPtr ptr)
411{
412 XF86ConfLayoutPtr prev;
413
414 while (ptr) {
415 TestFree(ptr->lay_identifier);
416 TestFree(ptr->lay_comment);
417 xf86freeAdjacencyList(ptr->lay_adjacency_lst);
418 xf86freeInputrefList(ptr->lay_input_lst);
419 prev = ptr;
420 ptr = ptr->list.next;
421 free(prev);
422 }
423}
424
425int
426xf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout)
427{
428 int count = 0;
429 XF86ConfInputPtr input = config->conf_input_lst;
430 XF86ConfInputrefPtr inptr;
431
432 /* add all AutoServerLayout devices to the server layout */
433 while (input) {
434 if (xf86CheckBoolOption
435 (input->inp_option_lst, "AutoServerLayout", FALSE)) {
436 XF86ConfInputrefPtr iref = layout->lay_input_lst;
437
438 /* avoid duplicates if referenced but lists AutoServerLayout too */
439 while (iref) {
440 if (strcmp(iref->iref_inputdev_str, input->inp_identifier) == 0)
441 break;
442 iref = iref->list.next;
443 }
444
445 if (!iref) {
446 XF86ConfInputrefPtr iptr;
447
448 iptr = calloc(1, sizeof(XF86ConfInputrefRec));
449 iptr->iref_inputdev_str = input->inp_identifier;
450 layout->lay_input_lst = (XF86ConfInputrefPtr)
451 xf86addListItem((glp) layout->lay_input_lst, (glp) iptr);
452 count++;
453 }
454 }
455 input = input->list.next;
456 }
457
458 inptr = layout->lay_input_lst;
459 while (inptr) {
460 input = xf86findInput(inptr->iref_inputdev_str, config->conf_input_lst);
461 if (!input) {
462 xf86validationError(UNDEFINED_INPUT_MSG,
463 inptr->iref_inputdev_str,
464 layout->lay_identifier);
465 return -1;
466 }
467 else
468 inptr->iref_inputdev = input;
469 inptr = inptr->list.next;
470 }
471
472 return count;
473}
474
475int
476xf86validateLayout(XF86ConfigPtr p)
477{
478 XF86ConfLayoutPtr layout = p->conf_layout_lst;
479 XF86ConfAdjacencyPtr adj;
480 XF86ConfInactivePtr iptr;
481 XF86ConfScreenPtr screen;
482 XF86ConfDevicePtr device;
483
484 while (layout) {
485 adj = layout->lay_adjacency_lst;
486 while (adj) {
487 /* the first one can't be "" but all others can */
488 screen = xf86findScreen(adj->adj_screen_str, p->conf_screen_lst);
489 if (!screen) {
490 xf86validationError(UNDEFINED_SCREEN_MSG,
491 adj->adj_screen_str,
492 layout->lay_identifier);
493 return FALSE;
494 }
495 else
496 adj->adj_screen = screen;
497
498 adj = adj->list.next;
499 }
500 iptr = layout->lay_inactive_lst;
501 while (iptr) {
502 device = xf86findDevice(iptr->inactive_device_str,
503 p->conf_device_lst);
504 if (!device) {
505 xf86validationError(UNDEFINED_DEVICE_LAY_MSG,
506 iptr->inactive_device_str,
507 layout->lay_identifier);
508 return FALSE;
509 }
510 else
511 iptr->inactive_device = device;
512 iptr = iptr->list.next;
513 }
514
515 if (xf86layoutAddInputDevices(p, layout) == -1)
516 return FALSE;
517
518 layout = layout->list.next;
519 }
520 return TRUE;
521}
522
523XF86ConfLayoutPtr
524xf86findLayout(const char *name, XF86ConfLayoutPtr list)
525{
526 while (list) {
527 if (xf86nameCompare(list->lay_identifier, name) == 0)
528 return list;
529 list = list->list.next;
530 }
531 return NULL;
532}