options-table.c revision 1.29
1/* $OpenBSD: options-table.c,v 1.29 2012/04/29 17:20:01 nicm Exp $ */ 2 3/* 4 * Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/types.h> 20 21#include <string.h> 22#include <paths.h> 23 24#include "tmux.h" 25 26/* 27 * This file has a tables with all the server, session and window 28 * options. These tables are the master copy of the options with their real 29 * (user-visible) types, range limits and default values. At start these are 30 * copied into the runtime global options trees (which only has number and 31 * string types). These tables are then used to loop up the real type when 32 * the user sets an option or its value needs to be shown. 33 */ 34 35/* Choice option type lists. */ 36const char *options_table_mode_keys_list[] = { 37 "emacs", "vi", NULL 38}; 39const char *options_table_mode_mouse_list[] = { 40 "off", "on", "copy-mode", NULL 41}; 42const char *options_table_clock_mode_style_list[] = { 43 "12", "24", NULL 44}; 45const char *options_table_status_keys_list[] = { 46 "emacs", "vi", NULL 47}; 48const char *options_table_status_justify_list[] = { 49 "left", "centre", "right", NULL 50}; 51const char *options_table_status_position_list[] = { 52 "top", "bottom", NULL 53}; 54const char *options_table_bell_action_list[] = { 55 "none", "any", "current", NULL 56}; 57 58/* Server options. */ 59const struct options_table_entry server_options_table[] = { 60 { .name = "buffer-limit", 61 .type = OPTIONS_TABLE_NUMBER, 62 .minimum = 1, 63 .maximum = INT_MAX, 64 .default_num = 20 65 }, 66 67 { .name = "escape-time", 68 .type = OPTIONS_TABLE_NUMBER, 69 .minimum = 0, 70 .maximum = INT_MAX, 71 .default_num = 500 72 }, 73 74 { .name = "exit-unattached", 75 .type = OPTIONS_TABLE_FLAG, 76 .default_num = 0 77 }, 78 79 { .name = "quiet", 80 .type = OPTIONS_TABLE_FLAG, 81 .default_num = 0 /* overridden in main() */ 82 }, 83 84 { .name = "set-clipboard", 85 .type = OPTIONS_TABLE_FLAG, 86 .default_num = 1 87 }, 88 89 { .name = NULL } 90}; 91 92/* Session options. */ 93const struct options_table_entry session_options_table[] = { 94 { .name = "base-index", 95 .type = OPTIONS_TABLE_NUMBER, 96 .minimum = 0, 97 .maximum = INT_MAX, 98 .default_num = 0 99 }, 100 101 { .name = "bell-action", 102 .type = OPTIONS_TABLE_CHOICE, 103 .choices = options_table_bell_action_list, 104 .default_num = BELL_ANY 105 }, 106 107 { .name = "bell-on-alert", 108 .type = OPTIONS_TABLE_FLAG, 109 .default_num = 0 110 }, 111 112 { .name = "default-command", 113 .type = OPTIONS_TABLE_STRING, 114 .default_str = "" 115 }, 116 117 { .name = "default-path", 118 .type = OPTIONS_TABLE_STRING, 119 .default_str = "" 120 }, 121 122 { .name = "default-shell", 123 .type = OPTIONS_TABLE_STRING, 124 .default_str = _PATH_BSHELL 125 }, 126 127 { .name = "default-terminal", 128 .type = OPTIONS_TABLE_STRING, 129 .default_str = "screen" 130 }, 131 132 { .name = "destroy-unattached", 133 .type = OPTIONS_TABLE_FLAG, 134 .default_num = 0 135 }, 136 137 { .name = "detach-on-destroy", 138 .type = OPTIONS_TABLE_FLAG, 139 .default_num = 1 140 }, 141 142 { .name = "display-panes-active-colour", 143 .type = OPTIONS_TABLE_COLOUR, 144 .default_num = 1 145 }, 146 147 { .name = "display-panes-colour", 148 .type = OPTIONS_TABLE_COLOUR, 149 .default_num = 4 150 }, 151 152 { .name = "display-panes-time", 153 .type = OPTIONS_TABLE_NUMBER, 154 .minimum = 1, 155 .maximum = INT_MAX, 156 .default_num = 1000 157 }, 158 159 { .name = "display-time", 160 .type = OPTIONS_TABLE_NUMBER, 161 .minimum = 1, 162 .maximum = INT_MAX, 163 .default_num = 750 164 }, 165 166 { .name = "history-limit", 167 .type = OPTIONS_TABLE_NUMBER, 168 .minimum = 0, 169 .maximum = INT_MAX, 170 .default_num = 2000 171 }, 172 173 { .name = "lock-after-time", 174 .type = OPTIONS_TABLE_NUMBER, 175 .minimum = 0, 176 .maximum = INT_MAX, 177 .default_num = 0 178 }, 179 180 { .name = "lock-command", 181 .type = OPTIONS_TABLE_STRING, 182 .default_str = "lock -np" 183 }, 184 185 { .name = "lock-server", 186 .type = OPTIONS_TABLE_FLAG, 187 .default_num = 1 188 }, 189 190 { .name = "message-attr", 191 .type = OPTIONS_TABLE_ATTRIBUTES, 192 .default_num = 0 193 }, 194 195 { .name = "message-bg", 196 .type = OPTIONS_TABLE_COLOUR, 197 .default_num = 3 198 }, 199 200 { .name = "message-command-attr", 201 .type = OPTIONS_TABLE_ATTRIBUTES, 202 .default_num = 0 203 }, 204 205 { .name = "message-command-bg", 206 .type = OPTIONS_TABLE_COLOUR, 207 .default_num = 0 208 }, 209 210 { .name = "message-command-fg", 211 .type = OPTIONS_TABLE_COLOUR, 212 .default_num = 3 213 }, 214 215 { .name = "message-fg", 216 .type = OPTIONS_TABLE_COLOUR, 217 .default_num = 0 218 }, 219 220 { .name = "message-limit", 221 .type = OPTIONS_TABLE_NUMBER, 222 .minimum = 0, 223 .maximum = INT_MAX, 224 .default_num = 20 225 }, 226 227 { .name = "mouse-resize-pane", 228 .type = OPTIONS_TABLE_FLAG, 229 .default_num = 0 230 }, 231 232 { .name = "mouse-select-pane", 233 .type = OPTIONS_TABLE_FLAG, 234 .default_num = 0 235 }, 236 237 { .name = "mouse-select-window", 238 .type = OPTIONS_TABLE_FLAG, 239 .default_num = 0 240 }, 241 242 { .name = "mouse-utf8", 243 .type = OPTIONS_TABLE_FLAG, 244 .default_num = 0 245 }, 246 247 { .name = "pane-active-border-bg", 248 .type = OPTIONS_TABLE_COLOUR, 249 .default_num = 8 250 }, 251 252 { .name = "pane-active-border-fg", 253 .type = OPTIONS_TABLE_COLOUR, 254 .default_num = 2 255 }, 256 257 { .name = "pane-border-bg", 258 .type = OPTIONS_TABLE_COLOUR, 259 .default_num = 8 260 }, 261 262 { .name = "pane-border-fg", 263 .type = OPTIONS_TABLE_COLOUR, 264 .default_num = 8 265 }, 266 267 { .name = "prefix", 268 .type = OPTIONS_TABLE_KEY, 269 .default_num = '\002', 270 }, 271 272 { .name = "prefix2", 273 .type = OPTIONS_TABLE_KEY, 274 .default_num = KEYC_NONE, 275 }, 276 277 { .name = "renumber-windows", 278 .type = OPTIONS_TABLE_FLAG, 279 .default_num = 0 280 }, 281 282 { .name = "repeat-time", 283 .type = OPTIONS_TABLE_NUMBER, 284 .minimum = 0, 285 .maximum = SHRT_MAX, 286 .default_num = 500 287 }, 288 289 { .name = "set-remain-on-exit", 290 .type = OPTIONS_TABLE_FLAG, 291 .default_num = 0 292 }, 293 294 { .name = "set-titles", 295 .type = OPTIONS_TABLE_FLAG, 296 .default_num = 0 297 }, 298 299 { .name = "set-titles-string", 300 .type = OPTIONS_TABLE_STRING, 301 .default_str = "#S:#I:#W - \"#T\"" 302 }, 303 304 { .name = "status", 305 .type = OPTIONS_TABLE_FLAG, 306 .default_num = 1 307 }, 308 309 { .name = "status-attr", 310 .type = OPTIONS_TABLE_ATTRIBUTES, 311 .default_num = 0 312 }, 313 314 { .name = "status-bg", 315 .type = OPTIONS_TABLE_COLOUR, 316 .default_num = 2 317 }, 318 319 { .name = "status-fg", 320 .type = OPTIONS_TABLE_COLOUR, 321 .default_num = 0 322 }, 323 324 { .name = "status-interval", 325 .type = OPTIONS_TABLE_NUMBER, 326 .minimum = 0, 327 .maximum = INT_MAX, 328 .default_num = 15 329 }, 330 331 { .name = "status-justify", 332 .type = OPTIONS_TABLE_CHOICE, 333 .choices = options_table_status_justify_list, 334 .default_num = 0 335 }, 336 337 { .name = "status-keys", 338 .type = OPTIONS_TABLE_CHOICE, 339 .choices = options_table_status_keys_list, 340 .default_num = MODEKEY_EMACS 341 }, 342 343 { .name = "status-left", 344 .type = OPTIONS_TABLE_STRING, 345 .default_str = "[#S]" 346 }, 347 348 { .name = "status-left-attr", 349 .type = OPTIONS_TABLE_ATTRIBUTES, 350 .default_num = 0 351 }, 352 353 { .name = "status-left-bg", 354 .type = OPTIONS_TABLE_COLOUR, 355 .default_num = 8 356 }, 357 358 { .name = "status-left-fg", 359 .type = OPTIONS_TABLE_COLOUR, 360 .default_num = 8 361 }, 362 363 { .name = "status-left-length", 364 .type = OPTIONS_TABLE_NUMBER, 365 .minimum = 0, 366 .maximum = SHRT_MAX, 367 .default_num = 10 368 }, 369 370 { .name = "status-position", 371 .type = OPTIONS_TABLE_CHOICE, 372 .choices = options_table_status_position_list, 373 .default_num = 1 374 }, 375 376 { .name = "status-right", 377 .type = OPTIONS_TABLE_STRING, 378 .default_str = "\"#22T\" %H:%M %d-%b-%y" 379 }, 380 381 { .name = "status-right-attr", 382 .type = OPTIONS_TABLE_ATTRIBUTES, 383 .default_num = 0 384 }, 385 386 { .name = "status-right-bg", 387 .type = OPTIONS_TABLE_COLOUR, 388 .default_num = 8 389 }, 390 391 { .name = "status-right-fg", 392 .type = OPTIONS_TABLE_COLOUR, 393 .default_num = 8 394 }, 395 396 { .name = "status-right-length", 397 .type = OPTIONS_TABLE_NUMBER, 398 .minimum = 0, 399 .maximum = SHRT_MAX, 400 .default_num = 40 401 }, 402 403 { .name = "status-utf8", 404 .type = OPTIONS_TABLE_FLAG, 405 .default_num = 0 /* overridden in main() */ 406 }, 407 408 { .name = "terminal-overrides", 409 .type = OPTIONS_TABLE_STRING, 410 .default_str = "*88col*:colors=88,*256col*:colors=256" 411 ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" 412 ":Cc=\\E]12;%p1%s\\007:Cr=\\E]112\\007" 413 ":Cs=\\E[%p1%d q:Csr=\\E[2 q,screen*:XT" 414 }, 415 416 { .name = "update-environment", 417 .type = OPTIONS_TABLE_STRING, 418 .default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID " 419 "SSH_CONNECTION WINDOWID XAUTHORITY" 420 421 }, 422 423 { .name = "visual-activity", 424 .type = OPTIONS_TABLE_FLAG, 425 .default_num = 0 426 }, 427 428 { .name = "visual-bell", 429 .type = OPTIONS_TABLE_FLAG, 430 .default_num = 0 431 }, 432 433 { .name = "visual-content", 434 .type = OPTIONS_TABLE_FLAG, 435 .default_num = 0 436 }, 437 438 { .name = "visual-silence", 439 .type = OPTIONS_TABLE_FLAG, 440 .default_num = 0 441 }, 442 443 { .name = "word-separators", 444 .type = OPTIONS_TABLE_STRING, 445 .default_str = " -_@" 446 }, 447 448 { .name = NULL } 449}; 450 451/* Window options. */ 452const struct options_table_entry window_options_table[] = { 453 { .name = "aggressive-resize", 454 .type = OPTIONS_TABLE_FLAG, 455 .default_num = 0 456 }, 457 458 { .name = "allow-rename", 459 .type = OPTIONS_TABLE_FLAG, 460 .default_num = 1 461 }, 462 463 { .name = "alternate-screen", 464 .type = OPTIONS_TABLE_FLAG, 465 .default_num = 1 466 }, 467 468 { .name = "automatic-rename", 469 .type = OPTIONS_TABLE_FLAG, 470 .default_num = 1 471 }, 472 473 474 { .name = "c0-change-trigger", 475 .type = OPTIONS_TABLE_NUMBER, 476 .default_num = 250, 477 .minimum = 0, 478 .maximum = USHRT_MAX 479 }, 480 481 { .name = "c0-change-interval", 482 .type = OPTIONS_TABLE_NUMBER, 483 .default_num = 100, 484 .minimum = 1, 485 .maximum = USHRT_MAX 486 }, 487 488 { .name = "clock-mode-colour", 489 .type = OPTIONS_TABLE_COLOUR, 490 .default_num = 4 491 }, 492 493 { .name = "clock-mode-style", 494 .type = OPTIONS_TABLE_CHOICE, 495 .choices = options_table_clock_mode_style_list, 496 .default_num = 1 497 }, 498 499 { .name = "force-height", 500 .type = OPTIONS_TABLE_NUMBER, 501 .minimum = 0, 502 .maximum = INT_MAX, 503 .default_num = 0 504 }, 505 506 { .name = "force-width", 507 .type = OPTIONS_TABLE_NUMBER, 508 .minimum = 0, 509 .maximum = INT_MAX, 510 .default_num = 0 511 }, 512 513 { .name = "layout-history-limit", 514 .type = OPTIONS_TABLE_NUMBER, 515 .minimum = 1, 516 .maximum = USHRT_MAX, 517 .default_num = 20 518 }, 519 520 { .name = "main-pane-height", 521 .type = OPTIONS_TABLE_NUMBER, 522 .minimum = 1, 523 .maximum = INT_MAX, 524 .default_num = 24 525 }, 526 527 { .name = "main-pane-width", 528 .type = OPTIONS_TABLE_NUMBER, 529 .minimum = 1, 530 .maximum = INT_MAX, 531 .default_num = 80 532 }, 533 534 { .name = "mode-attr", 535 .type = OPTIONS_TABLE_ATTRIBUTES, 536 .default_num = 0 537 }, 538 539 { .name = "mode-bg", 540 .type = OPTIONS_TABLE_COLOUR, 541 .default_num = 3 542 }, 543 544 { .name = "mode-fg", 545 .type = OPTIONS_TABLE_COLOUR, 546 .default_num = 0 547 }, 548 549 { .name = "mode-keys", 550 .type = OPTIONS_TABLE_CHOICE, 551 .choices = options_table_mode_keys_list, 552 .default_num = MODEKEY_EMACS 553 }, 554 555 { .name = "mode-mouse", 556 .type = OPTIONS_TABLE_CHOICE, 557 .choices = options_table_mode_mouse_list, 558 .default_num = 0 559 }, 560 561 { .name = "monitor-activity", 562 .type = OPTIONS_TABLE_FLAG, 563 .default_num = 0 564 }, 565 566 { .name = "monitor-content", 567 .type = OPTIONS_TABLE_STRING, 568 .default_str = "" 569 }, 570 571 { .name = "monitor-silence", 572 .type = OPTIONS_TABLE_NUMBER, 573 .minimum = 0, 574 .maximum = INT_MAX, 575 .default_num = 0 576 }, 577 578 { .name = "other-pane-height", 579 .type = OPTIONS_TABLE_NUMBER, 580 .minimum = 0, 581 .maximum = INT_MAX, 582 .default_num = 0 583 }, 584 585 { .name = "other-pane-width", 586 .type = OPTIONS_TABLE_NUMBER, 587 .minimum = 0, 588 .maximum = INT_MAX, 589 .default_num = 0 590 }, 591 592 { .name = "pane-base-index", 593 .type = OPTIONS_TABLE_NUMBER, 594 .minimum = 0, 595 .maximum = USHRT_MAX, 596 .default_num = 0 597 }, 598 599 { .name = "remain-on-exit", 600 .type = OPTIONS_TABLE_FLAG, 601 .default_num = 0 602 }, 603 604 { .name = "synchronize-panes", 605 .type = OPTIONS_TABLE_FLAG, 606 .default_num = 0 607 }, 608 609 { .name = "utf8", 610 .type = OPTIONS_TABLE_FLAG, 611 .default_num = 0 /* overridden in main() */ 612 }, 613 614 { .name = "window-status-activity-attr", 615 .type = OPTIONS_TABLE_ATTRIBUTES, 616 .default_num = GRID_ATTR_REVERSE 617 }, 618 619 { .name = "window-status-activity-bg", 620 .type = OPTIONS_TABLE_COLOUR, 621 .default_num = 8 622 }, 623 624 { .name = "window-status-activity-fg", 625 .type = OPTIONS_TABLE_COLOUR, 626 .default_num = 8 627 }, 628 629 { .name = "window-status-bell-attr", 630 .type = OPTIONS_TABLE_ATTRIBUTES, 631 .default_num = GRID_ATTR_REVERSE 632 }, 633 634 { .name = "window-status-bell-bg", 635 .type = OPTIONS_TABLE_COLOUR, 636 .default_num = 8 637 }, 638 639 { .name = "window-status-bell-fg", 640 .type = OPTIONS_TABLE_COLOUR, 641 .default_num = 8 642 }, 643 644 { .name = "window-status-content-attr", 645 .type = OPTIONS_TABLE_ATTRIBUTES, 646 .default_num = GRID_ATTR_REVERSE 647 }, 648 649 { .name = "window-status-content-bg", 650 .type = OPTIONS_TABLE_COLOUR, 651 .default_num = 8 652 }, 653 654 { .name = "window-status-content-fg", 655 .type = OPTIONS_TABLE_COLOUR, 656 .default_num = 8 657 }, 658 659 { .name = "window-status-attr", 660 .type = OPTIONS_TABLE_ATTRIBUTES, 661 .default_num = 0 662 }, 663 664 { .name = "window-status-bg", 665 .type = OPTIONS_TABLE_COLOUR, 666 .default_num = 8 667 }, 668 669 { .name = "window-status-current-attr", 670 .type = OPTIONS_TABLE_ATTRIBUTES, 671 .default_num = 0 672 }, 673 674 { .name = "window-status-current-bg", 675 .type = OPTIONS_TABLE_COLOUR, 676 .default_num = 8 677 }, 678 679 { .name = "window-status-current-fg", 680 .type = OPTIONS_TABLE_COLOUR, 681 .default_num = 8 682 }, 683 684 { .name = "window-status-current-format", 685 .type = OPTIONS_TABLE_STRING, 686 .default_str = "#I:#W#F" 687 }, 688 689 { .name = "window-status-fg", 690 .type = OPTIONS_TABLE_COLOUR, 691 .default_num = 8 692 }, 693 694 { .name = "window-status-format", 695 .type = OPTIONS_TABLE_STRING, 696 .default_str = "#I:#W#F" 697 }, 698 699 { .name = "window-status-separator", 700 .type = OPTIONS_TABLE_STRING, 701 .default_str = " " 702 }, 703 704 { .name = "wrap-search", 705 .type = OPTIONS_TABLE_FLAG, 706 .default_num = 1 707 }, 708 709 { .name = "xterm-keys", 710 .type = OPTIONS_TABLE_FLAG, 711 .default_num = 0 712 }, 713 714 { .name = NULL } 715}; 716 717/* Populate an options tree from a table. */ 718void 719options_table_populate_tree( 720 const struct options_table_entry *table, struct options *oo) 721{ 722 const struct options_table_entry *oe; 723 724 for (oe = table; oe->name != NULL; oe++) { 725 if (oe->default_str != NULL) 726 options_set_string(oo, oe->name, "%s", oe->default_str); 727 else 728 options_set_number(oo, oe->name, oe->default_num); 729 } 730} 731 732/* Print an option using its type from the table. */ 733const char * 734options_table_print_entry( 735 const struct options_table_entry *oe, struct options_entry *o) 736{ 737 static char out[BUFSIZ]; 738 const char *s; 739 740 *out = '\0'; 741 switch (oe->type) { 742 case OPTIONS_TABLE_STRING: 743 xsnprintf(out, sizeof out, "\"%s\"", o->str); 744 break; 745 case OPTIONS_TABLE_NUMBER: 746 xsnprintf(out, sizeof out, "%lld", o->num); 747 break; 748 case OPTIONS_TABLE_KEY: 749 xsnprintf(out, sizeof out, "%s", key_string_lookup_key(o->num)); 750 break; 751 case OPTIONS_TABLE_COLOUR: 752 s = colour_tostring(o->num); 753 xsnprintf(out, sizeof out, "%s", s); 754 break; 755 case OPTIONS_TABLE_ATTRIBUTES: 756 s = attributes_tostring(o->num); 757 xsnprintf(out, sizeof out, "%s", s); 758 break; 759 case OPTIONS_TABLE_FLAG: 760 if (o->num) 761 strlcpy(out, "on", sizeof out); 762 else 763 strlcpy(out, "off", sizeof out); 764 break; 765 case OPTIONS_TABLE_CHOICE: 766 s = oe->choices[o->num]; 767 xsnprintf(out, sizeof out, "%s", s); 768 break; 769 } 770 return (out); 771} 772 773/* Find an option. */ 774int 775options_table_find( 776 const char *optstr, const struct options_table_entry **table, 777 const struct options_table_entry **oe) 778{ 779 static const struct options_table_entry *tables[] = { 780 server_options_table, 781 window_options_table, 782 session_options_table 783 }; 784 const struct options_table_entry *oe_loop; 785 u_int i; 786 787 for (i = 0; i < nitems(tables); i++) { 788 for (oe_loop = tables[i]; oe_loop->name != NULL; oe_loop++) { 789 if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0) 790 continue; 791 792 /* If already found, ambiguous. */ 793 if (*oe != NULL) 794 return (-1); 795 *oe = oe_loop; 796 *table = tables[i]; 797 798 /* Bail now if an exact match. */ 799 if (strcmp((*oe)->name, optstr) == 0) 800 break; 801 } 802 } 803 return (0); 804} 805