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