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 */
66 extern int xf86CheckBoolOption(void *optlist, const char *name, int deflt);
67
68
69 static const xf86ConfigSymTabRec LayoutTab[] = {
70 {ENDSECTION, "endsection"},
71 {SCREEN, "screen"},
72 {IDENTIFIER, "identifier"},
73 {MATCHSEAT, "matchseat"},
74 {INACTIVE, "inactive"},
75 {INPUTDEVICE, "inputdevice"},
76 {OPTION, "option"},
77 {-1, ""},
78 };
79
80 static const 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
92 XF86ConfLayoutPtr
xf86parseLayoutSection(void)93 xf86parseLayoutSection(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, xf86_lex_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 = xf86_lex_val.str;
111 has_ident = TRUE;
112 break;
113 case MATCHSEAT:
114 if (xf86getSubToken(&(ptr->lay_comment)) != STRING)
115 Error(QUOTE_MSG, "MatchSeat");
116 ptr->match_seat = xf86_lex_val.str;
117 break;
118 case INACTIVE:
119 {
120 XF86ConfInactivePtr iptr;
121
122 iptr = calloc(1, sizeof(XF86ConfInactiveRec));
123 iptr->list.next = NULL;
124 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
125 free(iptr);
126 Error(INACTIVE_MSG);
127 }
128 iptr->inactive_device_str = xf86_lex_val.str;
129 ptr->lay_inactive_lst = (XF86ConfInactivePtr)
130 xf86addListItem((glp) ptr->lay_inactive_lst, (glp) iptr);
131 }
132 break;
133 case SCREEN:
134 {
135 XF86ConfAdjacencyPtr aptr;
136 int absKeyword = 0;
137
138 aptr = calloc(1, sizeof(XF86ConfAdjacencyRec));
139 aptr->list.next = NULL;
140 aptr->adj_scrnum = -1;
141 aptr->adj_where = CONF_ADJ_OBSOLETE;
142 aptr->adj_x = 0;
143 aptr->adj_y = 0;
144 aptr->adj_refscreen = NULL;
145 if ((token = xf86getSubToken(&(ptr->lay_comment))) == NUMBER)
146 aptr->adj_scrnum = xf86_lex_val.num;
147 else
148 xf86unGetToken(token);
149 token = xf86getSubToken(&(ptr->lay_comment));
150 if (token != STRING) {
151 free(aptr);
152 Error(SCREEN_MSG);
153 }
154 aptr->adj_screen_str = xf86_lex_val.str;
155
156 token = xf86getSubTokenWithTab(&(ptr->lay_comment), AdjTab);
157 switch (token) {
158 case RIGHTOF:
159 aptr->adj_where = CONF_ADJ_RIGHTOF;
160 break;
161 case LEFTOF:
162 aptr->adj_where = CONF_ADJ_LEFTOF;
163 break;
164 case ABOVE:
165 aptr->adj_where = CONF_ADJ_ABOVE;
166 break;
167 case BELOW:
168 aptr->adj_where = CONF_ADJ_BELOW;
169 break;
170 case RELATIVE:
171 aptr->adj_where = CONF_ADJ_RELATIVE;
172 break;
173 case ABSOLUTE:
174 aptr->adj_where = CONF_ADJ_ABSOLUTE;
175 absKeyword = 1;
176 break;
177 case EOF_TOKEN:
178 free(aptr);
179 Error(UNEXPECTED_EOF_MSG);
180 break;
181 default:
182 xf86unGetToken(token);
183 token = xf86getSubToken(&(ptr->lay_comment));
184 if (token == STRING)
185 aptr->adj_where = CONF_ADJ_OBSOLETE;
186 else
187 aptr->adj_where = CONF_ADJ_ABSOLUTE;
188 }
189 switch (aptr->adj_where) {
190 case CONF_ADJ_ABSOLUTE:
191 if (absKeyword)
192 token = xf86getSubToken(&(ptr->lay_comment));
193 if (token == NUMBER) {
194 aptr->adj_x = xf86_lex_val.num;
195 token = xf86getSubToken(&(ptr->lay_comment));
196 if (token != NUMBER) {
197 free(aptr);
198 Error(INVALID_SCR_MSG);
199 }
200 aptr->adj_y = xf86_lex_val.num;
201 }
202 else {
203 if (absKeyword) {
204 free(aptr);
205 Error(INVALID_SCR_MSG);
206 }
207 else
208 xf86unGetToken(token);
209 }
210 break;
211 case CONF_ADJ_RIGHTOF:
212 case CONF_ADJ_LEFTOF:
213 case CONF_ADJ_ABOVE:
214 case CONF_ADJ_BELOW:
215 case CONF_ADJ_RELATIVE:
216 token = xf86getSubToken(&(ptr->lay_comment));
217 if (token != STRING) {
218 free(aptr);
219 Error(INVALID_SCR_MSG);
220 }
221 aptr->adj_refscreen = xf86_lex_val.str;
222 if (aptr->adj_where == CONF_ADJ_RELATIVE) {
223 token = xf86getSubToken(&(ptr->lay_comment));
224 if (token != NUMBER) {
225 free(aptr);
226 Error(INVALID_SCR_MSG);
227 }
228 aptr->adj_x = xf86_lex_val.num;
229 token = xf86getSubToken(&(ptr->lay_comment));
230 if (token != NUMBER) {
231 free(aptr);
232 Error(INVALID_SCR_MSG);
233 }
234 aptr->adj_y = xf86_lex_val.num;
235 }
236 break;
237 case CONF_ADJ_OBSOLETE:
238 /* top */
239 aptr->adj_top_str = xf86_lex_val.str;
240
241 /* bottom */
242 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
243 free(aptr);
244 Error(SCREEN_MSG);
245 }
246 aptr->adj_bottom_str = xf86_lex_val.str;
247
248 /* left */
249 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
250 free(aptr);
251 Error(SCREEN_MSG);
252 }
253 aptr->adj_left_str = xf86_lex_val.str;
254
255 /* right */
256 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
257 free(aptr);
258 Error(SCREEN_MSG);
259 }
260 aptr->adj_right_str = xf86_lex_val.str;
261
262 }
263 ptr->lay_adjacency_lst = (XF86ConfAdjacencyPtr)
264 xf86addListItem((glp) ptr->lay_adjacency_lst, (glp) aptr);
265 }
266 break;
267 case INPUTDEVICE:
268 {
269 XF86ConfInputrefPtr iptr;
270
271 iptr = calloc(1, sizeof(XF86ConfInputrefRec));
272 iptr->list.next = NULL;
273 iptr->iref_option_lst = NULL;
274 if (xf86getSubToken(&(ptr->lay_comment)) != STRING) {
275 free(iptr);
276 Error(INPUTDEV_MSG);
277 }
278 iptr->iref_inputdev_str = xf86_lex_val.str;
279 while ((token = xf86getSubToken(&(ptr->lay_comment))) == STRING) {
280 iptr->iref_option_lst =
281 xf86addNewOption(iptr->iref_option_lst, xf86_lex_val.str, NULL);
282 }
283 xf86unGetToken(token);
284 ptr->lay_input_lst = (XF86ConfInputrefPtr)
285 xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
286 }
287 break;
288 case OPTION:
289 ptr->lay_option_lst = xf86parseOption(ptr->lay_option_lst);
290 break;
291 case EOF_TOKEN:
292 Error(UNEXPECTED_EOF_MSG);
293 break;
294 default:
295 Error(INVALID_KEYWORD_MSG, xf86tokenString());
296 break;
297 }
298 }
299
300 if (!has_ident)
301 Error(NO_IDENT_MSG);
302
303 #ifdef DEBUG
304 printf("Layout section parsed\n");
305 #endif
306
307 return ptr;
308 }
309
310 #undef CLEANUP
311
312 void
xf86printLayoutSection(FILE * cf,XF86ConfLayoutPtr ptr)313 xf86printLayoutSection(FILE * cf, XF86ConfLayoutPtr ptr)
314 {
315 XF86ConfAdjacencyPtr aptr;
316 XF86ConfInactivePtr iptr;
317 XF86ConfInputrefPtr inptr;
318 XF86OptionPtr optr;
319
320 while (ptr) {
321 fprintf(cf, "Section \"ServerLayout\"\n");
322 if (ptr->lay_comment)
323 fprintf(cf, "%s", ptr->lay_comment);
324 if (ptr->lay_identifier)
325 fprintf(cf, "\tIdentifier \"%s\"\n", ptr->lay_identifier);
326
327 for (aptr = ptr->lay_adjacency_lst; aptr; aptr = aptr->list.next) {
328 fprintf(cf, "\tScreen ");
329 if (aptr->adj_scrnum >= 0)
330 fprintf(cf, "%2d", aptr->adj_scrnum);
331 else
332 fprintf(cf, " ");
333 fprintf(cf, " \"%s\"", aptr->adj_screen_str);
334 switch (aptr->adj_where) {
335 case CONF_ADJ_OBSOLETE:
336 fprintf(cf, " \"%s\"", aptr->adj_top_str);
337 fprintf(cf, " \"%s\"", aptr->adj_bottom_str);
338 fprintf(cf, " \"%s\"", aptr->adj_right_str);
339 fprintf(cf, " \"%s\"\n", aptr->adj_left_str);
340 break;
341 case CONF_ADJ_ABSOLUTE:
342 if (aptr->adj_x != -1)
343 fprintf(cf, " %d %d\n", aptr->adj_x, aptr->adj_y);
344 else
345 fprintf(cf, "\n");
346 break;
347 case CONF_ADJ_RIGHTOF:
348 fprintf(cf, " RightOf \"%s\"\n", aptr->adj_refscreen);
349 break;
350 case CONF_ADJ_LEFTOF:
351 fprintf(cf, " LeftOf \"%s\"\n", aptr->adj_refscreen);
352 break;
353 case CONF_ADJ_ABOVE:
354 fprintf(cf, " Above \"%s\"\n", aptr->adj_refscreen);
355 break;
356 case CONF_ADJ_BELOW:
357 fprintf(cf, " Below \"%s\"\n", aptr->adj_refscreen);
358 break;
359 case CONF_ADJ_RELATIVE:
360 fprintf(cf, " Relative \"%s\" %d %d\n", aptr->adj_refscreen,
361 aptr->adj_x, aptr->adj_y);
362 break;
363 }
364 }
365 for (iptr = ptr->lay_inactive_lst; iptr; iptr = iptr->list.next)
366 fprintf(cf, "\tInactive \"%s\"\n", iptr->inactive_device_str);
367 for (inptr = ptr->lay_input_lst; inptr; inptr = inptr->list.next) {
368 fprintf(cf, "\tInputDevice \"%s\"", inptr->iref_inputdev_str);
369 for (optr = inptr->iref_option_lst; optr; optr = optr->list.next) {
370 fprintf(cf, " \"%s\"", optr->opt_name);
371 }
372 fprintf(cf, "\n");
373 }
374 xf86printOptionList(cf, ptr->lay_option_lst, 1);
375 fprintf(cf, "EndSection\n\n");
376 ptr = ptr->list.next;
377 }
378 }
379
380 static void
xf86freeAdjacencyList(XF86ConfAdjacencyPtr ptr)381 xf86freeAdjacencyList(XF86ConfAdjacencyPtr ptr)
382 {
383 XF86ConfAdjacencyPtr prev;
384
385 while (ptr) {
386 TestFree(ptr->adj_screen_str);
387 TestFree(ptr->adj_top_str);
388 TestFree(ptr->adj_bottom_str);
389 TestFree(ptr->adj_left_str);
390 TestFree(ptr->adj_right_str);
391
392 prev = ptr;
393 ptr = ptr->list.next;
394 free(prev);
395 }
396
397 }
398
399 static void
xf86freeInputrefList(XF86ConfInputrefPtr ptr)400 xf86freeInputrefList(XF86ConfInputrefPtr ptr)
401 {
402 XF86ConfInputrefPtr prev;
403
404 while (ptr) {
405 TestFree(ptr->iref_inputdev_str);
406 xf86optionListFree(ptr->iref_option_lst);
407 prev = ptr;
408 ptr = ptr->list.next;
409 free(prev);
410 }
411
412 }
413
414 void
xf86freeLayoutList(XF86ConfLayoutPtr ptr)415 xf86freeLayoutList(XF86ConfLayoutPtr ptr)
416 {
417 XF86ConfLayoutPtr prev;
418
419 while (ptr) {
420 TestFree(ptr->lay_identifier);
421 TestFree(ptr->lay_comment);
422 xf86freeAdjacencyList(ptr->lay_adjacency_lst);
423 xf86freeInputrefList(ptr->lay_input_lst);
424 prev = ptr;
425 ptr = ptr->list.next;
426 free(prev);
427 }
428 }
429
430 int
xf86layoutAddInputDevices(XF86ConfigPtr config,XF86ConfLayoutPtr layout)431 xf86layoutAddInputDevices(XF86ConfigPtr config, XF86ConfLayoutPtr layout)
432 {
433 int count = 0;
434 XF86ConfInputPtr input = config->conf_input_lst;
435 XF86ConfInputrefPtr inptr;
436
437 /* add all AutoServerLayout devices to the server layout */
438 while (input) {
439 if (xf86CheckBoolOption
440 (input->inp_option_lst, "AutoServerLayout", FALSE)) {
441 XF86ConfInputrefPtr iref = layout->lay_input_lst;
442
443 /* avoid duplicates if referenced but lists AutoServerLayout too */
444 while (iref) {
445 if (strcmp(iref->iref_inputdev_str, input->inp_identifier) == 0)
446 break;
447 iref = iref->list.next;
448 }
449
450 if (!iref) {
451 XF86ConfInputrefPtr iptr;
452
453 iptr = calloc(1, sizeof(XF86ConfInputrefRec));
454 iptr->iref_inputdev_str = input->inp_identifier;
455 layout->lay_input_lst = (XF86ConfInputrefPtr)
456 xf86addListItem((glp) layout->lay_input_lst, (glp) iptr);
457 count++;
458 }
459 }
460 input = input->list.next;
461 }
462
463 inptr = layout->lay_input_lst;
464 while (inptr) {
465 input = xf86findInput(inptr->iref_inputdev_str, config->conf_input_lst);
466 if (!input) {
467 xf86validationError(UNDEFINED_INPUT_MSG,
468 inptr->iref_inputdev_str,
469 layout->lay_identifier);
470 return -1;
471 }
472 else
473 inptr->iref_inputdev = input;
474 inptr = inptr->list.next;
475 }
476
477 return count;
478 }
479
480 int
xf86validateLayout(XF86ConfigPtr p)481 xf86validateLayout(XF86ConfigPtr p)
482 {
483 XF86ConfLayoutPtr layout = p->conf_layout_lst;
484 XF86ConfAdjacencyPtr adj;
485 XF86ConfInactivePtr iptr;
486 XF86ConfScreenPtr screen;
487 XF86ConfDevicePtr device;
488
489 while (layout) {
490 adj = layout->lay_adjacency_lst;
491 while (adj) {
492 /* the first one can't be "" but all others can */
493 screen = xf86findScreen(adj->adj_screen_str, p->conf_screen_lst);
494 if (!screen) {
495 xf86validationError(UNDEFINED_SCREEN_MSG,
496 adj->adj_screen_str,
497 layout->lay_identifier);
498 return FALSE;
499 }
500 else
501 adj->adj_screen = screen;
502
503 adj = adj->list.next;
504 }
505 iptr = layout->lay_inactive_lst;
506 while (iptr) {
507 device = xf86findDevice(iptr->inactive_device_str,
508 p->conf_device_lst);
509 if (!device) {
510 xf86validationError(UNDEFINED_DEVICE_LAY_MSG,
511 iptr->inactive_device_str,
512 layout->lay_identifier);
513 return FALSE;
514 }
515 else
516 iptr->inactive_device = device;
517 iptr = iptr->list.next;
518 }
519
520 if (xf86layoutAddInputDevices(p, layout) == -1)
521 return FALSE;
522
523 layout = layout->list.next;
524 }
525 return TRUE;
526 }
527
528 XF86ConfLayoutPtr
xf86findLayout(const char * name,XF86ConfLayoutPtr list)529 xf86findLayout(const char *name, XF86ConfLayoutPtr list)
530 {
531 while (list) {
532 if (xf86nameCompare(list->lay_identifier, name) == 0)
533 return list;
534 list = list->list.next;
535 }
536 return NULL;
537 }
538