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