xref: /openbsd-src/usr.bin/tmux/options-table.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
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. */
36 const char *options_table_mode_keys_list[] = {
37 	"emacs", "vi", NULL
38 };
39 const char *options_table_mode_mouse_list[] = {
40 	"off", "on", "copy-mode", NULL
41 };
42 const char *options_table_clock_mode_style_list[] = {
43 	"12", "24", NULL
44 };
45 const char *options_table_status_keys_list[] = {
46 	"emacs", "vi", NULL
47 };
48 const char *options_table_status_justify_list[] = {
49 	"left", "centre", "right", NULL
50 };
51 const char *options_table_status_position_list[] = {
52 	"top", "bottom", NULL
53 };
54 const char *options_table_bell_action_list[] = {
55 	"none", "any", "current", NULL
56 };
57 
58 /* Server options. */
59 const 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. */
93 const 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. */
452 const 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. */
718 void
719 options_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. */
733 const char *
734 options_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. */
774 int
775 options_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