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