Layout.c (18181B)
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 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 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 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 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 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 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 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 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 }