options-table.c revision 1.34
1/* $OpenBSD: options-table.c,v 1.34 2013/03/24 09:21:27 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 = "assume-paste-time", 95 .type = OPTIONS_TABLE_NUMBER, 96 .minimum = 0, 97 .maximum = INT_MAX, 98 .default_num = 1, 99 }, 100 101 { .name = "base-index", 102 .type = OPTIONS_TABLE_NUMBER, 103 .minimum = 0, 104 .maximum = INT_MAX, 105 .default_num = 0 106 }, 107 108 { .name = "bell-action", 109 .type = OPTIONS_TABLE_CHOICE, 110 .choices = options_table_bell_action_list, 111 .default_num = BELL_ANY 112 }, 113 114 { .name = "bell-on-alert", 115 .type = OPTIONS_TABLE_FLAG, 116 .default_num = 0 117 }, 118 119 { .name = "default-command", 120 .type = OPTIONS_TABLE_STRING, 121 .default_str = "" 122 }, 123 124 { .name = "default-path", 125 .type = OPTIONS_TABLE_STRING, 126 .default_str = "" 127 }, 128 129 { .name = "default-shell", 130 .type = OPTIONS_TABLE_STRING, 131 .default_str = _PATH_BSHELL 132 }, 133 134 { .name = "default-terminal", 135 .type = OPTIONS_TABLE_STRING, 136 .default_str = "screen" 137 }, 138 139 { .name = "destroy-unattached", 140 .type = OPTIONS_TABLE_FLAG, 141 .default_num = 0 142 }, 143 144 { .name = "detach-on-destroy", 145 .type = OPTIONS_TABLE_FLAG, 146 .default_num = 1 147 }, 148 149 { .name = "display-panes-active-colour", 150 .type = OPTIONS_TABLE_COLOUR, 151 .default_num = 1 152 }, 153 154 { .name = "display-panes-colour", 155 .type = OPTIONS_TABLE_COLOUR, 156 .default_num = 4 157 }, 158 159 { .name = "display-panes-time", 160 .type = OPTIONS_TABLE_NUMBER, 161 .minimum = 1, 162 .maximum = INT_MAX, 163 .default_num = 1000 164 }, 165 166 { .name = "display-time", 167 .type = OPTIONS_TABLE_NUMBER, 168 .minimum = 1, 169 .maximum = INT_MAX, 170 .default_num = 750 171 }, 172 173 { .name = "history-limit", 174 .type = OPTIONS_TABLE_NUMBER, 175 .minimum = 0, 176 .maximum = INT_MAX, 177 .default_num = 2000 178 }, 179 180 { .name = "lock-after-time", 181 .type = OPTIONS_TABLE_NUMBER, 182 .minimum = 0, 183 .maximum = INT_MAX, 184 .default_num = 0 185 }, 186 187 { .name = "lock-command", 188 .type = OPTIONS_TABLE_STRING, 189 .default_str = "lock -np" 190 }, 191 192 { .name = "lock-server", 193 .type = OPTIONS_TABLE_FLAG, 194 .default_num = 1 195 }, 196 197 { .name = "message-attr", 198 .type = OPTIONS_TABLE_ATTRIBUTES, 199 .default_num = 0 200 }, 201 202 { .name = "message-bg", 203 .type = OPTIONS_TABLE_COLOUR, 204 .default_num = 3 205 }, 206 207 { .name = "message-command-attr", 208 .type = OPTIONS_TABLE_ATTRIBUTES, 209 .default_num = 0 210 }, 211 212 { .name = "message-command-bg", 213 .type = OPTIONS_TABLE_COLOUR, 214 .default_num = 0 215 }, 216 217 { .name = "message-command-fg", 218 .type = OPTIONS_TABLE_COLOUR, 219 .default_num = 3 220 }, 221 222 { .name = "message-fg", 223 .type = OPTIONS_TABLE_COLOUR, 224 .default_num = 0 225 }, 226 227 { .name = "message-limit", 228 .type = OPTIONS_TABLE_NUMBER, 229 .minimum = 0, 230 .maximum = INT_MAX, 231 .default_num = 20 232 }, 233 234 { .name = "mouse-resize-pane", 235 .type = OPTIONS_TABLE_FLAG, 236 .default_num = 0 237 }, 238 239 { .name = "mouse-select-pane", 240 .type = OPTIONS_TABLE_FLAG, 241 .default_num = 0 242 }, 243 244 { .name = "mouse-select-window", 245 .type = OPTIONS_TABLE_FLAG, 246 .default_num = 0 247 }, 248 249 { .name = "mouse-utf8", 250 .type = OPTIONS_TABLE_FLAG, 251 .default_num = 0 252 }, 253 254 { .name = "pane-active-border-bg", 255 .type = OPTIONS_TABLE_COLOUR, 256 .default_num = 8 257 }, 258 259 { .name = "pane-active-border-fg", 260 .type = OPTIONS_TABLE_COLOUR, 261 .default_num = 2 262 }, 263 264 { .name = "pane-border-bg", 265 .type = OPTIONS_TABLE_COLOUR, 266 .default_num = 8 267 }, 268 269 { .name = "pane-border-fg", 270 .type = OPTIONS_TABLE_COLOUR, 271 .default_num = 8 272 }, 273 274 { .name = "prefix", 275 .type = OPTIONS_TABLE_KEY, 276 .default_num = '\002', 277 }, 278 279 { .name = "prefix2", 280 .type = OPTIONS_TABLE_KEY, 281 .default_num = KEYC_NONE, 282 }, 283 284 { .name = "renumber-windows", 285 .type = OPTIONS_TABLE_FLAG, 286 .default_num = 0 287 }, 288 289 { .name = "repeat-time", 290 .type = OPTIONS_TABLE_NUMBER, 291 .minimum = 0, 292 .maximum = SHRT_MAX, 293 .default_num = 500 294 }, 295 296 { .name = "set-remain-on-exit", 297 .type = OPTIONS_TABLE_FLAG, 298 .default_num = 0 299 }, 300 301 { .name = "set-titles", 302 .type = OPTIONS_TABLE_FLAG, 303 .default_num = 0 304 }, 305 306 { .name = "set-titles-string", 307 .type = OPTIONS_TABLE_STRING, 308 .default_str = "#S:#I:#W - \"#T\"" 309 }, 310 311 { .name = "status", 312 .type = OPTIONS_TABLE_FLAG, 313 .default_num = 1 314 }, 315 316 { .name = "status-attr", 317 .type = OPTIONS_TABLE_ATTRIBUTES, 318 .default_num = 0 319 }, 320 321 { .name = "status-bg", 322 .type = OPTIONS_TABLE_COLOUR, 323 .default_num = 2 324 }, 325 326 { .name = "status-fg", 327 .type = OPTIONS_TABLE_COLOUR, 328 .default_num = 0 329 }, 330 331 { .name = "status-interval", 332 .type = OPTIONS_TABLE_NUMBER, 333 .minimum = 0, 334 .maximum = INT_MAX, 335 .default_num = 15 336 }, 337 338 { .name = "status-justify", 339 .type = OPTIONS_TABLE_CHOICE, 340 .choices = options_table_status_justify_list, 341 .default_num = 0 342 }, 343 344 { .name = "status-keys", 345 .type = OPTIONS_TABLE_CHOICE, 346 .choices = options_table_status_keys_list, 347 .default_num = MODEKEY_EMACS 348 }, 349 350 { .name = "status-left", 351 .type = OPTIONS_TABLE_STRING, 352 .default_str = "[#S]" 353 }, 354 355 { .name = "status-left-attr", 356 .type = OPTIONS_TABLE_ATTRIBUTES, 357 .default_num = 0 358 }, 359 360 { .name = "status-left-bg", 361 .type = OPTIONS_TABLE_COLOUR, 362 .default_num = 8 363 }, 364 365 { .name = "status-left-fg", 366 .type = OPTIONS_TABLE_COLOUR, 367 .default_num = 8 368 }, 369 370 { .name = "status-left-length", 371 .type = OPTIONS_TABLE_NUMBER, 372 .minimum = 0, 373 .maximum = SHRT_MAX, 374 .default_num = 10 375 }, 376 377 { .name = "status-position", 378 .type = OPTIONS_TABLE_CHOICE, 379 .choices = options_table_status_position_list, 380 .default_num = 1 381 }, 382 383 { .name = "status-right", 384 .type = OPTIONS_TABLE_STRING, 385 .default_str = "\"#22T\" %H:%M %d-%b-%y" 386 }, 387 388 { .name = "status-right-attr", 389 .type = OPTIONS_TABLE_ATTRIBUTES, 390 .default_num = 0 391 }, 392 393 { .name = "status-right-bg", 394 .type = OPTIONS_TABLE_COLOUR, 395 .default_num = 8 396 }, 397 398 { .name = "status-right-fg", 399 .type = OPTIONS_TABLE_COLOUR, 400 .default_num = 8 401 }, 402 403 { .name = "status-right-length", 404 .type = OPTIONS_TABLE_NUMBER, 405 .minimum = 0, 406 .maximum = SHRT_MAX, 407 .default_num = 40 408 }, 409 410 { .name = "status-utf8", 411 .type = OPTIONS_TABLE_FLAG, 412 .default_num = 0 /* overridden in main() */ 413 }, 414 415 { .name = "terminal-overrides", 416 .type = OPTIONS_TABLE_STRING, 417 .default_str = "*88col*:colors=88,*256col*:colors=256" 418 ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" 419 ":Cc=\\E]12;%p1%s\\007:Cr=\\E]112\\007" 420 ":Cs=\\E[%p1%d q:Csr=\\E[2 q,screen*:XT" 421 }, 422 423 { .name = "update-environment", 424 .type = OPTIONS_TABLE_STRING, 425 .default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID " 426 "SSH_CONNECTION WINDOWID XAUTHORITY" 427 428 }, 429 430 { .name = "visual-activity", 431 .type = OPTIONS_TABLE_FLAG, 432 .default_num = 0 433 }, 434 435 { .name = "visual-bell", 436 .type = OPTIONS_TABLE_FLAG, 437 .default_num = 0 438 }, 439 440 { .name = "visual-content", 441 .type = OPTIONS_TABLE_FLAG, 442 .default_num = 0 443 }, 444 445 { .name = "visual-silence", 446 .type = OPTIONS_TABLE_FLAG, 447 .default_num = 0 448 }, 449 450 { .name = "word-separators", 451 .type = OPTIONS_TABLE_STRING, 452 .default_str = " -_@" 453 }, 454 455 { .name = NULL } 456}; 457 458/* Window options. */ 459const struct options_table_entry window_options_table[] = { 460 { .name = "aggressive-resize", 461 .type = OPTIONS_TABLE_FLAG, 462 .default_num = 0 463 }, 464 465 { .name = "allow-rename", 466 .type = OPTIONS_TABLE_FLAG, 467 .default_num = 1 468 }, 469 470 { .name = "alternate-screen", 471 .type = OPTIONS_TABLE_FLAG, 472 .default_num = 1 473 }, 474 475 { .name = "automatic-rename", 476 .type = OPTIONS_TABLE_FLAG, 477 .default_num = 1 478 }, 479 480 { .name = "c0-change-trigger", 481 .type = OPTIONS_TABLE_NUMBER, 482 .default_num = 250, 483 .minimum = 0, 484 .maximum = USHRT_MAX 485 }, 486 487 { .name = "c0-change-interval", 488 .type = OPTIONS_TABLE_NUMBER, 489 .default_num = 100, 490 .minimum = 1, 491 .maximum = USHRT_MAX 492 }, 493 494 { .name = "clock-mode-colour", 495 .type = OPTIONS_TABLE_COLOUR, 496 .default_num = 4 497 }, 498 499 { .name = "clock-mode-style", 500 .type = OPTIONS_TABLE_CHOICE, 501 .choices = options_table_clock_mode_style_list, 502 .default_num = 1 503 }, 504 505 { .name = "command-prefix", 506 .type = OPTIONS_TABLE_STRING, 507 .default_str = "exec " 508 }, 509 510 { .name = "force-height", 511 .type = OPTIONS_TABLE_NUMBER, 512 .minimum = 0, 513 .maximum = INT_MAX, 514 .default_num = 0 515 }, 516 517 { .name = "force-width", 518 .type = OPTIONS_TABLE_NUMBER, 519 .minimum = 0, 520 .maximum = INT_MAX, 521 .default_num = 0 522 }, 523 524 { .name = "main-pane-height", 525 .type = OPTIONS_TABLE_NUMBER, 526 .minimum = 1, 527 .maximum = INT_MAX, 528 .default_num = 24 529 }, 530 531 { .name = "main-pane-width", 532 .type = OPTIONS_TABLE_NUMBER, 533 .minimum = 1, 534 .maximum = INT_MAX, 535 .default_num = 80 536 }, 537 538 { .name = "mode-attr", 539 .type = OPTIONS_TABLE_ATTRIBUTES, 540 .default_num = 0 541 }, 542 543 { .name = "mode-bg", 544 .type = OPTIONS_TABLE_COLOUR, 545 .default_num = 3 546 }, 547 548 { .name = "mode-fg", 549 .type = OPTIONS_TABLE_COLOUR, 550 .default_num = 0 551 }, 552 553 { .name = "mode-keys", 554 .type = OPTIONS_TABLE_CHOICE, 555 .choices = options_table_mode_keys_list, 556 .default_num = MODEKEY_EMACS 557 }, 558 559 { .name = "mode-mouse", 560 .type = OPTIONS_TABLE_CHOICE, 561 .choices = options_table_mode_mouse_list, 562 .default_num = 0 563 }, 564 565 { .name = "monitor-activity", 566 .type = OPTIONS_TABLE_FLAG, 567 .default_num = 0 568 }, 569 570 { .name = "monitor-content", 571 .type = OPTIONS_TABLE_STRING, 572 .default_str = "" 573 }, 574 575 { .name = "monitor-silence", 576 .type = OPTIONS_TABLE_NUMBER, 577 .minimum = 0, 578 .maximum = INT_MAX, 579 .default_num = 0 580 }, 581 582 { .name = "other-pane-height", 583 .type = OPTIONS_TABLE_NUMBER, 584 .minimum = 0, 585 .maximum = INT_MAX, 586 .default_num = 0 587 }, 588 589 { .name = "other-pane-width", 590 .type = OPTIONS_TABLE_NUMBER, 591 .minimum = 0, 592 .maximum = INT_MAX, 593 .default_num = 0 594 }, 595 596 { .name = "pane-base-index", 597 .type = OPTIONS_TABLE_NUMBER, 598 .minimum = 0, 599 .maximum = USHRT_MAX, 600 .default_num = 0 601 }, 602 603 { .name = "remain-on-exit", 604 .type = OPTIONS_TABLE_FLAG, 605 .default_num = 0 606 }, 607 608 { .name = "synchronize-panes", 609 .type = OPTIONS_TABLE_FLAG, 610 .default_num = 0 611 }, 612 613 { .name = "utf8", 614 .type = OPTIONS_TABLE_FLAG, 615 .default_num = 0 /* overridden in main() */ 616 }, 617 618 { .name = "window-status-activity-attr", 619 .type = OPTIONS_TABLE_ATTRIBUTES, 620 .default_num = GRID_ATTR_REVERSE 621 }, 622 623 { .name = "window-status-activity-bg", 624 .type = OPTIONS_TABLE_COLOUR, 625 .default_num = 8 626 }, 627 628 { .name = "window-status-activity-fg", 629 .type = OPTIONS_TABLE_COLOUR, 630 .default_num = 8 631 }, 632 633 { .name = "window-status-bell-attr", 634 .type = OPTIONS_TABLE_ATTRIBUTES, 635 .default_num = GRID_ATTR_REVERSE 636 }, 637 638 { .name = "window-status-bell-bg", 639 .type = OPTIONS_TABLE_COLOUR, 640 .default_num = 8 641 }, 642 643 { .name = "window-status-bell-fg", 644 .type = OPTIONS_TABLE_COLOUR, 645 .default_num = 8 646 }, 647 648 { .name = "window-status-content-attr", 649 .type = OPTIONS_TABLE_ATTRIBUTES, 650 .default_num = GRID_ATTR_REVERSE 651 }, 652 653 { .name = "window-status-content-bg", 654 .type = OPTIONS_TABLE_COLOUR, 655 .default_num = 8 656 }, 657 658 { .name = "window-status-content-fg", 659 .type = OPTIONS_TABLE_COLOUR, 660 .default_num = 8 661 }, 662 663 { .name = "window-status-attr", 664 .type = OPTIONS_TABLE_ATTRIBUTES, 665 .default_num = 0 666 }, 667 668 { .name = "window-status-bg", 669 .type = OPTIONS_TABLE_COLOUR, 670 .default_num = 8 671 }, 672 673 { .name = "window-status-current-attr", 674 .type = OPTIONS_TABLE_ATTRIBUTES, 675 .default_num = 0 676 }, 677 678 { .name = "window-status-current-bg", 679 .type = OPTIONS_TABLE_COLOUR, 680 .default_num = 8 681 }, 682 683 { .name = "window-status-current-fg", 684 .type = OPTIONS_TABLE_COLOUR, 685 .default_num = 8 686 }, 687 688 { .name = "window-status-current-format", 689 .type = OPTIONS_TABLE_STRING, 690 .default_str = "#I:#W#F" 691 }, 692 693 { .name = "window-status-last-attr", 694 .type = OPTIONS_TABLE_ATTRIBUTES, 695 .default_num = 0 696 }, 697 698 { .name = "window-status-last-bg", 699 .type = OPTIONS_TABLE_COLOUR, 700 .default_num = 8 701 }, 702 703 { .name = "window-status-last-fg", 704 .type = OPTIONS_TABLE_COLOUR, 705 .default_num = 8 706 }, 707 708 { .name = "window-status-fg", 709 .type = OPTIONS_TABLE_COLOUR, 710 .default_num = 8 711 }, 712 713 { .name = "window-status-format", 714 .type = OPTIONS_TABLE_STRING, 715 .default_str = "#I:#W#F" 716 }, 717 718 { .name = "window-status-separator", 719 .type = OPTIONS_TABLE_STRING, 720 .default_str = " " 721 }, 722 723 { .name = "wrap-search", 724 .type = OPTIONS_TABLE_FLAG, 725 .default_num = 1 726 }, 727 728 { .name = "xterm-keys", 729 .type = OPTIONS_TABLE_FLAG, 730 .default_num = 0 731 }, 732 733 { .name = NULL } 734}; 735 736/* Populate an options tree from a table. */ 737void 738options_table_populate_tree( 739 const struct options_table_entry *table, struct options *oo) 740{ 741 const struct options_table_entry *oe; 742 743 for (oe = table; oe->name != NULL; oe++) { 744 if (oe->default_str != NULL) 745 options_set_string(oo, oe->name, "%s", oe->default_str); 746 else 747 options_set_number(oo, oe->name, oe->default_num); 748 } 749} 750 751/* Print an option using its type from the table. */ 752const char * 753options_table_print_entry(const struct options_table_entry *oe, 754 struct options_entry *o, int no_quotes) 755{ 756 static char out[BUFSIZ]; 757 const char *s; 758 759 *out = '\0'; 760 switch (oe->type) { 761 case OPTIONS_TABLE_STRING: 762 if (no_quotes) 763 xsnprintf(out, sizeof out, "%s", o->str); 764 else 765 xsnprintf(out, sizeof out, "\"%s\"", o->str); 766 break; 767 case OPTIONS_TABLE_NUMBER: 768 xsnprintf(out, sizeof out, "%lld", o->num); 769 break; 770 case OPTIONS_TABLE_KEY: 771 xsnprintf(out, sizeof out, "%s", 772 key_string_lookup_key(o->num)); 773 break; 774 case OPTIONS_TABLE_COLOUR: 775 s = colour_tostring(o->num); 776 xsnprintf(out, sizeof out, "%s", s); 777 break; 778 case OPTIONS_TABLE_ATTRIBUTES: 779 s = attributes_tostring(o->num); 780 xsnprintf(out, sizeof out, "%s", s); 781 break; 782 case OPTIONS_TABLE_FLAG: 783 if (o->num) 784 strlcpy(out, "on", sizeof out); 785 else 786 strlcpy(out, "off", sizeof out); 787 break; 788 case OPTIONS_TABLE_CHOICE: 789 s = oe->choices[o->num]; 790 xsnprintf(out, sizeof out, "%s", s); 791 break; 792 } 793 return (out); 794} 795 796/* Find an option. */ 797int 798options_table_find( 799 const char *optstr, const struct options_table_entry **table, 800 const struct options_table_entry **oe) 801{ 802 static const struct options_table_entry *tables[] = { 803 server_options_table, 804 window_options_table, 805 session_options_table 806 }; 807 const struct options_table_entry *oe_loop; 808 u_int i; 809 810 for (i = 0; i < nitems(tables); i++) { 811 for (oe_loop = tables[i]; oe_loop->name != NULL; oe_loop++) { 812 if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0) 813 continue; 814 815 /* If already found, ambiguous. */ 816 if (*oe != NULL) 817 return (-1); 818 *oe = oe_loop; 819 *table = tables[i]; 820 821 /* Bail now if an exact match. */ 822 if (strcmp((*oe)->name, optstr) == 0) 823 break; 824 } 825 } 826 return (0); 827} 828