xref: /netbsd-src/external/bsd/tmux/dist/tty-features.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
19fb66d81Schristos /* $OpenBSD$ */
29fb66d81Schristos 
39fb66d81Schristos /*
49fb66d81Schristos  * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
59fb66d81Schristos  *
69fb66d81Schristos  * Permission to use, copy, modify, and distribute this software for any
79fb66d81Schristos  * purpose with or without fee is hereby granted, provided that the above
89fb66d81Schristos  * copyright notice and this permission notice appear in all copies.
99fb66d81Schristos  *
109fb66d81Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
119fb66d81Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
129fb66d81Schristos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
139fb66d81Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
149fb66d81Schristos  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
159fb66d81Schristos  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
169fb66d81Schristos  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
179fb66d81Schristos  */
189fb66d81Schristos 
199fb66d81Schristos #include <sys/types.h>
209fb66d81Schristos 
219fb66d81Schristos #include <stdlib.h>
229fb66d81Schristos #include <string.h>
239fb66d81Schristos 
24c23f9150Swiz #if defined(HAVE_CURSES_H)
25c23f9150Swiz #include <curses.h>
26c23f9150Swiz #elif defined(HAVE_NCURSES_H)
27c23f9150Swiz #include <ncurses.h>
28c23f9150Swiz #endif
29c23f9150Swiz 
309fb66d81Schristos #include "tmux.h"
319fb66d81Schristos 
329fb66d81Schristos /*
339fb66d81Schristos  * Still hardcoded:
349fb66d81Schristos  * - default colours (under AX or op capabilities);
359fb66d81Schristos  * - AIX colours (under colors >= 16);
369fb66d81Schristos  * - alternate escape (if terminal is VT100-like).
379fb66d81Schristos  *
389fb66d81Schristos  * Also:
399fb66d81Schristos  * - DECFRA uses a flag instead of capabilities;
409fb66d81Schristos  * - UTF-8 is a separate flag on the client; needed for unattached clients.
419fb66d81Schristos  */
429fb66d81Schristos 
439fb66d81Schristos /* A named terminal feature. */
449fb66d81Schristos struct tty_feature {
459fb66d81Schristos 	const char		*name;
46c23f9150Swiz 	const char *const	*capabilities;
479fb66d81Schristos 	int			 flags;
489fb66d81Schristos };
499fb66d81Schristos 
509fb66d81Schristos /* Terminal has xterm(1) title setting. */
51c23f9150Swiz static const char *const tty_feature_title_capabilities[] = {
529fb66d81Schristos 	"tsl=\\E]0;", /* should be using TS really */
539fb66d81Schristos 	"fsl=\\a",
549fb66d81Schristos 	NULL
559fb66d81Schristos };
569fb66d81Schristos static const struct tty_feature tty_feature_title = {
579fb66d81Schristos 	"title",
589fb66d81Schristos 	tty_feature_title_capabilities,
599fb66d81Schristos 	0
609fb66d81Schristos };
619fb66d81Schristos 
626db26757Swiz /* Terminal has OSC 7 working directory. */
63c23f9150Swiz static const char *const tty_feature_osc7_capabilities[] = {
646db26757Swiz 	"Swd=\\E]7;",
656db26757Swiz 	"fsl=\\a",
666db26757Swiz 	NULL
676db26757Swiz };
686db26757Swiz static const struct tty_feature tty_feature_osc7 = {
696db26757Swiz 	"osc7",
706db26757Swiz 	tty_feature_osc7_capabilities,
716db26757Swiz 	0
726db26757Swiz };
736db26757Swiz 
74de7701e2Schristos /* Terminal has mouse support. */
75c23f9150Swiz static const char *const tty_feature_mouse_capabilities[] = {
76de7701e2Schristos 	"kmous=\\E[M",
77de7701e2Schristos 	NULL
78de7701e2Schristos };
79de7701e2Schristos static const struct tty_feature tty_feature_mouse = {
80de7701e2Schristos 	"mouse",
81de7701e2Schristos 	tty_feature_mouse_capabilities,
82de7701e2Schristos 	0
83de7701e2Schristos };
84de7701e2Schristos 
859fb66d81Schristos /* Terminal can set the clipboard with OSC 52. */
86c23f9150Swiz static const char *const tty_feature_clipboard_capabilities[] = {
879fb66d81Schristos 	"Ms=\\E]52;%p1%s;%p2%s\\a",
889fb66d81Schristos 	NULL
899fb66d81Schristos };
909fb66d81Schristos static const struct tty_feature tty_feature_clipboard = {
919fb66d81Schristos 	"clipboard",
929fb66d81Schristos 	tty_feature_clipboard_capabilities,
939fb66d81Schristos 	0
949fb66d81Schristos };
959fb66d81Schristos 
96c23f9150Swiz /* Terminal supports OSC 8 hyperlinks. */
97c23f9150Swiz static const char *tty_feature_hyperlinks_capabilities[] = {
98c23f9150Swiz #if defined (__OpenBSD__) || (defined(NCURSES_VERSION_MAJOR) && \
99c23f9150Swiz 	(NCURSES_VERSION_MAJOR > 5 || \
100c23f9150Swiz 	(NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 8)))
101c23f9150Swiz 	"*:Hls=\\E]8;%?%p1%l%tid=%p1%s%;;%p2%s\\E\\\\",
102c23f9150Swiz #endif
103c23f9150Swiz 	NULL
104c23f9150Swiz };
105c23f9150Swiz static const struct tty_feature tty_feature_hyperlinks = {
106c23f9150Swiz 	"hyperlinks",
107c23f9150Swiz 	tty_feature_hyperlinks_capabilities,
108c23f9150Swiz 	0
109c23f9150Swiz };
110c23f9150Swiz 
1119fb66d81Schristos /*
1129fb66d81Schristos  * Terminal supports RGB colour. This replaces setab and setaf also since
1139fb66d81Schristos  * terminals with RGB have versions that do not allow setting colours from the
1149fb66d81Schristos  * 256 palette.
1159fb66d81Schristos  */
116c23f9150Swiz static const char *const tty_feature_rgb_capabilities[] = {
1179fb66d81Schristos 	"AX",
1189fb66d81Schristos 	"setrgbf=\\E[38;2;%p1%d;%p2%d;%p3%dm",
1199fb66d81Schristos 	"setrgbb=\\E[48;2;%p1%d;%p2%d;%p3%dm",
1209fb66d81Schristos 	"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
1219fb66d81Schristos 	"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
1229fb66d81Schristos 	NULL
1239fb66d81Schristos };
1249fb66d81Schristos static const struct tty_feature tty_feature_rgb = {
1259fb66d81Schristos 	"RGB",
1269fb66d81Schristos 	tty_feature_rgb_capabilities,
1279fb66d81Schristos 	TERM_256COLOURS|TERM_RGBCOLOURS
1289fb66d81Schristos };
1299fb66d81Schristos 
1309fb66d81Schristos /* Terminal supports 256 colours. */
131c23f9150Swiz static const char *const tty_feature_256_capabilities[] = {
1329fb66d81Schristos 	"AX",
1339fb66d81Schristos 	"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m",
1349fb66d81Schristos 	"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m",
1359fb66d81Schristos 	NULL
1369fb66d81Schristos };
1379fb66d81Schristos static const struct tty_feature tty_feature_256 = {
1389fb66d81Schristos 	"256",
1399fb66d81Schristos 	tty_feature_256_capabilities,
1409fb66d81Schristos 	TERM_256COLOURS
1419fb66d81Schristos };
1429fb66d81Schristos 
1439fb66d81Schristos /* Terminal supports overline. */
144c23f9150Swiz static const char *const tty_feature_overline_capabilities[] = {
1459fb66d81Schristos 	"Smol=\\E[53m",
1469fb66d81Schristos 	NULL
1479fb66d81Schristos };
1489fb66d81Schristos static const struct tty_feature tty_feature_overline = {
1499fb66d81Schristos 	"overline",
1509fb66d81Schristos 	tty_feature_overline_capabilities,
1519fb66d81Schristos 	0
1529fb66d81Schristos };
1539fb66d81Schristos 
1549fb66d81Schristos /* Terminal supports underscore styles. */
155c23f9150Swiz static const char *const tty_feature_usstyle_capabilities[] = {
1569fb66d81Schristos 	"Smulx=\\E[4::%p1%dm",
1579fb66d81Schristos 	"Setulc=\\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m",
158c23f9150Swiz 	"Setulc1=\\E[58::5::%p1%dm",
1599fb66d81Schristos 	"ol=\\E[59m",
1609fb66d81Schristos 	NULL
1619fb66d81Schristos };
1629fb66d81Schristos static const struct tty_feature tty_feature_usstyle = {
1639fb66d81Schristos 	"usstyle",
1649fb66d81Schristos 	tty_feature_usstyle_capabilities,
1659fb66d81Schristos 	0
1669fb66d81Schristos };
1679fb66d81Schristos 
1689fb66d81Schristos /* Terminal supports bracketed paste. */
169c23f9150Swiz static const char *const tty_feature_bpaste_capabilities[] = {
1709fb66d81Schristos 	"Enbp=\\E[?2004h",
1719fb66d81Schristos 	"Dsbp=\\E[?2004l",
1729fb66d81Schristos 	NULL
1739fb66d81Schristos };
1749fb66d81Schristos static const struct tty_feature tty_feature_bpaste = {
1759fb66d81Schristos 	"bpaste",
1769fb66d81Schristos 	tty_feature_bpaste_capabilities,
1779fb66d81Schristos 	0
1789fb66d81Schristos };
1799fb66d81Schristos 
1809fb66d81Schristos /* Terminal supports focus reporting. */
181c23f9150Swiz static const char *const tty_feature_focus_capabilities[] = {
1829fb66d81Schristos 	"Enfcs=\\E[?1004h",
1839fb66d81Schristos 	"Dsfcs=\\E[?1004l",
1849fb66d81Schristos 	NULL
1859fb66d81Schristos };
1869fb66d81Schristos static const struct tty_feature tty_feature_focus = {
1879fb66d81Schristos 	"focus",
1889fb66d81Schristos 	tty_feature_focus_capabilities,
1899fb66d81Schristos 	0
1909fb66d81Schristos };
1919fb66d81Schristos 
1929fb66d81Schristos /* Terminal supports cursor styles. */
193c23f9150Swiz static const char *const tty_feature_cstyle_capabilities[] = {
1949fb66d81Schristos 	"Ss=\\E[%p1%d q",
1959fb66d81Schristos 	"Se=\\E[2 q",
1969fb66d81Schristos 	NULL
1979fb66d81Schristos };
1989fb66d81Schristos static const struct tty_feature tty_feature_cstyle = {
1999fb66d81Schristos 	"cstyle",
2009fb66d81Schristos 	tty_feature_cstyle_capabilities,
2019fb66d81Schristos 	0
2029fb66d81Schristos };
2039fb66d81Schristos 
2049fb66d81Schristos /* Terminal supports cursor colours. */
205c23f9150Swiz static const char *const tty_feature_ccolour_capabilities[] = {
2069fb66d81Schristos 	"Cs=\\E]12;%p1%s\\a",
2079fb66d81Schristos 	"Cr=\\E]112\\a",
2089fb66d81Schristos 	NULL
2099fb66d81Schristos };
2109fb66d81Schristos static const struct tty_feature tty_feature_ccolour = {
2119fb66d81Schristos 	"ccolour",
2129fb66d81Schristos 	tty_feature_ccolour_capabilities,
2139fb66d81Schristos 	0
2149fb66d81Schristos };
2159fb66d81Schristos 
2169fb66d81Schristos /* Terminal supports strikethrough. */
217c23f9150Swiz static const char *const tty_feature_strikethrough_capabilities[] = {
2189fb66d81Schristos 	"smxx=\\E[9m",
2199fb66d81Schristos 	NULL
2209fb66d81Schristos };
2219fb66d81Schristos static const struct tty_feature tty_feature_strikethrough = {
2229fb66d81Schristos 	"strikethrough",
2239fb66d81Schristos 	tty_feature_strikethrough_capabilities,
2249fb66d81Schristos 	0
2259fb66d81Schristos };
2269fb66d81Schristos 
2279fb66d81Schristos /* Terminal supports synchronized updates. */
228c23f9150Swiz static const char *const tty_feature_sync_capabilities[] = {
229c23f9150Swiz 	"Sync=\\E[?2026%?%p1%{1}%-%tl%eh%;",
2309fb66d81Schristos 	NULL
2319fb66d81Schristos };
2329fb66d81Schristos static const struct tty_feature tty_feature_sync = {
2339fb66d81Schristos 	"sync",
2349fb66d81Schristos 	tty_feature_sync_capabilities,
2359fb66d81Schristos 	0
2369fb66d81Schristos };
2379fb66d81Schristos 
2389fb66d81Schristos /* Terminal supports extended keys. */
239c23f9150Swiz static const char *const tty_feature_extkeys_capabilities[] = {
240*f8cf1a91Swiz 	"Eneks=\\E[>4;2m",
2419fb66d81Schristos 	"Dseks=\\E[>4m",
2429fb66d81Schristos 	NULL
2439fb66d81Schristos };
2449fb66d81Schristos static const struct tty_feature tty_feature_extkeys = {
2459fb66d81Schristos 	"extkeys",
2469fb66d81Schristos 	tty_feature_extkeys_capabilities,
2479fb66d81Schristos 	0
2489fb66d81Schristos };
2499fb66d81Schristos 
2509fb66d81Schristos /* Terminal supports DECSLRM margins. */
251c23f9150Swiz static const char *const tty_feature_margins_capabilities[] = {
2529fb66d81Schristos 	"Enmg=\\E[?69h",
2539fb66d81Schristos 	"Dsmg=\\E[?69l",
2549fb66d81Schristos 	"Clmg=\\E[s",
2559fb66d81Schristos 	"Cmg=\\E[%i%p1%d;%p2%ds",
2569fb66d81Schristos 	NULL
2579fb66d81Schristos };
2589fb66d81Schristos static const struct tty_feature tty_feature_margins = {
2599fb66d81Schristos 	"margins",
2609fb66d81Schristos 	tty_feature_margins_capabilities,
2619fb66d81Schristos 	TERM_DECSLRM
2629fb66d81Schristos };
2639fb66d81Schristos 
2649fb66d81Schristos /* Terminal supports DECFRA rectangle fill. */
265c23f9150Swiz static const char *const tty_feature_rectfill_capabilities[] = {
266de7701e2Schristos 	"Rect",
267de7701e2Schristos 	NULL
268de7701e2Schristos };
2699fb66d81Schristos static const struct tty_feature tty_feature_rectfill = {
2709fb66d81Schristos 	"rectfill",
271de7701e2Schristos 	tty_feature_rectfill_capabilities,
2729fb66d81Schristos 	TERM_DECFRA
2739fb66d81Schristos };
2749fb66d81Schristos 
275c23f9150Swiz /* Use builtin function keys only. */
276c23f9150Swiz static const char *const tty_feature_ignorefkeys_capabilities[] = {
277c23f9150Swiz 	"kf0@",
278c23f9150Swiz 	"kf1@",
279c23f9150Swiz 	"kf2@",
280c23f9150Swiz 	"kf3@",
281c23f9150Swiz 	"kf4@",
282c23f9150Swiz 	"kf5@",
283c23f9150Swiz 	"kf6@",
284c23f9150Swiz 	"kf7@",
285c23f9150Swiz 	"kf8@",
286c23f9150Swiz 	"kf9@",
287c23f9150Swiz 	"kf10@",
288c23f9150Swiz 	"kf11@",
289c23f9150Swiz 	"kf12@",
290c23f9150Swiz 	"kf13@",
291c23f9150Swiz 	"kf14@",
292c23f9150Swiz 	"kf15@",
293c23f9150Swiz 	"kf16@",
294c23f9150Swiz 	"kf17@",
295c23f9150Swiz 	"kf18@",
296c23f9150Swiz 	"kf19@",
297c23f9150Swiz 	"kf20@",
298c23f9150Swiz 	"kf21@",
299c23f9150Swiz 	"kf22@",
300c23f9150Swiz 	"kf23@",
301c23f9150Swiz 	"kf24@",
302c23f9150Swiz 	"kf25@",
303c23f9150Swiz 	"kf26@",
304c23f9150Swiz 	"kf27@",
305c23f9150Swiz 	"kf28@",
306c23f9150Swiz 	"kf29@",
307c23f9150Swiz 	"kf30@",
308c23f9150Swiz 	"kf31@",
309c23f9150Swiz 	"kf32@",
310c23f9150Swiz 	"kf33@",
311c23f9150Swiz 	"kf34@",
312c23f9150Swiz 	"kf35@",
313c23f9150Swiz 	"kf36@",
314c23f9150Swiz 	"kf37@",
315c23f9150Swiz 	"kf38@",
316c23f9150Swiz 	"kf39@",
317c23f9150Swiz 	"kf40@",
318c23f9150Swiz 	"kf41@",
319c23f9150Swiz 	"kf42@",
320c23f9150Swiz 	"kf43@",
321c23f9150Swiz 	"kf44@",
322c23f9150Swiz 	"kf45@",
323c23f9150Swiz 	"kf46@",
324c23f9150Swiz 	"kf47@",
325c23f9150Swiz 	"kf48@",
326c23f9150Swiz 	"kf49@",
327c23f9150Swiz 	"kf50@",
328c23f9150Swiz 	"kf51@",
329c23f9150Swiz 	"kf52@",
330c23f9150Swiz 	"kf53@",
331c23f9150Swiz 	"kf54@",
332c23f9150Swiz 	"kf55@",
333c23f9150Swiz 	"kf56@",
334c23f9150Swiz 	"kf57@",
335c23f9150Swiz 	"kf58@",
336c23f9150Swiz 	"kf59@",
337c23f9150Swiz 	"kf60@",
338c23f9150Swiz 	"kf61@",
339c23f9150Swiz 	"kf62@",
340c23f9150Swiz 	"kf63@",
341c23f9150Swiz 	NULL
342c23f9150Swiz };
343c23f9150Swiz static const struct tty_feature tty_feature_ignorefkeys = {
344c23f9150Swiz 	"ignorefkeys",
345c23f9150Swiz 	tty_feature_ignorefkeys_capabilities,
346c23f9150Swiz 	0
347c23f9150Swiz };
348c23f9150Swiz 
349c23f9150Swiz /* Terminal has sixel capability. */
350c23f9150Swiz static const char *const tty_feature_sixel_capabilities[] = {
351c23f9150Swiz 	"Sxl",
352c23f9150Swiz 	NULL
353c23f9150Swiz };
354c23f9150Swiz static const struct tty_feature tty_feature_sixel = {
355c23f9150Swiz 	"sixel",
356c23f9150Swiz 	tty_feature_sixel_capabilities,
357c23f9150Swiz 	TERM_SIXEL
358c23f9150Swiz };
359c23f9150Swiz 
3609fb66d81Schristos /* Available terminal features. */
361c23f9150Swiz static const struct tty_feature *const tty_features[] = {
3629fb66d81Schristos 	&tty_feature_256,
3639fb66d81Schristos 	&tty_feature_bpaste,
3649fb66d81Schristos 	&tty_feature_ccolour,
3659fb66d81Schristos 	&tty_feature_clipboard,
366c23f9150Swiz 	&tty_feature_hyperlinks,
3679fb66d81Schristos 	&tty_feature_cstyle,
3689fb66d81Schristos 	&tty_feature_extkeys,
3699fb66d81Schristos 	&tty_feature_focus,
370c23f9150Swiz 	&tty_feature_ignorefkeys,
3719fb66d81Schristos 	&tty_feature_margins,
372de7701e2Schristos 	&tty_feature_mouse,
3736db26757Swiz 	&tty_feature_osc7,
3749fb66d81Schristos 	&tty_feature_overline,
3759fb66d81Schristos 	&tty_feature_rectfill,
3769fb66d81Schristos 	&tty_feature_rgb,
377c23f9150Swiz 	&tty_feature_sixel,
3789fb66d81Schristos 	&tty_feature_strikethrough,
3799fb66d81Schristos 	&tty_feature_sync,
3809fb66d81Schristos 	&tty_feature_title,
3819fb66d81Schristos 	&tty_feature_usstyle
3829fb66d81Schristos };
3839fb66d81Schristos 
3849fb66d81Schristos void
3859fb66d81Schristos tty_add_features(int *feat, const char *s, const char *separators)
3869fb66d81Schristos {
3879fb66d81Schristos 	const struct tty_feature	 *tf;
3889fb66d81Schristos 	char				 *next, *loop, *copy;
3899fb66d81Schristos 	u_int				  i;
3909fb66d81Schristos 
3919fb66d81Schristos 	log_debug("adding terminal features %s", s);
3929fb66d81Schristos 
3939fb66d81Schristos 	loop = copy = xstrdup(s);
3949fb66d81Schristos 	while ((next = strsep(&loop, separators)) != NULL) {
3959fb66d81Schristos 		for (i = 0; i < nitems(tty_features); i++) {
3969fb66d81Schristos 			tf = tty_features[i];
3979fb66d81Schristos 			if (strcasecmp(tf->name, next) == 0)
3989fb66d81Schristos 				break;
3999fb66d81Schristos 		}
4009fb66d81Schristos 		if (i == nitems(tty_features)) {
4019fb66d81Schristos 			log_debug("unknown terminal feature: %s", next);
4029fb66d81Schristos 			break;
4039fb66d81Schristos 		}
4049fb66d81Schristos 		if (~(*feat) & (1 << i)) {
4059fb66d81Schristos 			log_debug("adding terminal feature: %s", tf->name);
4069fb66d81Schristos 			(*feat) |= (1 << i);
4079fb66d81Schristos 		}
4089fb66d81Schristos 	}
4099fb66d81Schristos 	free(copy);
4109fb66d81Schristos }
4119fb66d81Schristos 
4129fb66d81Schristos const char *
4139fb66d81Schristos tty_get_features(int feat)
4149fb66d81Schristos {
4159fb66d81Schristos 	const struct tty_feature	*tf;
4169fb66d81Schristos 	static char			 s[512];
4179fb66d81Schristos 	u_int				 i;
4189fb66d81Schristos 
4199fb66d81Schristos 	*s = '\0';
4209fb66d81Schristos 	for (i = 0; i < nitems(tty_features); i++) {
4219fb66d81Schristos 		if (~feat & (1 << i))
4229fb66d81Schristos 			continue;
4239fb66d81Schristos 		tf = tty_features[i];
4249fb66d81Schristos 
4259fb66d81Schristos 		strlcat(s, tf->name, sizeof s);
4269fb66d81Schristos 		strlcat(s, ",", sizeof s);
4279fb66d81Schristos 	}
4289fb66d81Schristos 	if (*s != '\0')
4299fb66d81Schristos 		s[strlen(s) - 1] = '\0';
4309fb66d81Schristos 	return (s);
4319fb66d81Schristos }
4329fb66d81Schristos 
4339fb66d81Schristos int
4349fb66d81Schristos tty_apply_features(struct tty_term *term, int feat)
4359fb66d81Schristos {
4369fb66d81Schristos 	const struct tty_feature	*tf;
437c23f9150Swiz 	const char *const		*capability;
4389fb66d81Schristos 	u_int				 i;
4399fb66d81Schristos 
4409fb66d81Schristos 	if (feat == 0)
4419fb66d81Schristos 		return (0);
4429fb66d81Schristos 	log_debug("applying terminal features: %s", tty_get_features(feat));
4439fb66d81Schristos 
4449fb66d81Schristos 	for (i = 0; i < nitems(tty_features); i++) {
4459fb66d81Schristos 		if ((term->features & (1 << i)) || (~feat & (1 << i)))
4469fb66d81Schristos 			continue;
4479fb66d81Schristos 		tf = tty_features[i];
4489fb66d81Schristos 
4499fb66d81Schristos 		log_debug("applying terminal feature: %s", tf->name);
4509fb66d81Schristos 		if (tf->capabilities != NULL) {
4519fb66d81Schristos 			capability = tf->capabilities;
4529fb66d81Schristos 			while (*capability != NULL) {
4539fb66d81Schristos 				log_debug("adding capability: %s", *capability);
4549fb66d81Schristos 				tty_term_apply(term, *capability, 1);
4559fb66d81Schristos 				capability++;
4569fb66d81Schristos 			}
4579fb66d81Schristos 		}
4589fb66d81Schristos 		term->flags |= tf->flags;
4599fb66d81Schristos 	}
4609fb66d81Schristos 	if ((term->features | feat) == term->features)
4619fb66d81Schristos 		return (0);
4629fb66d81Schristos 	term->features |= feat;
4639fb66d81Schristos 	return (1);
4649fb66d81Schristos }
4659fb66d81Schristos 
4669fb66d81Schristos void
4679fb66d81Schristos tty_default_features(int *feat, const char *name, u_int version)
4689fb66d81Schristos {
469c23f9150Swiz 	static const struct {
4709fb66d81Schristos 		const char	*name;
4719fb66d81Schristos 		u_int		 version;
4729fb66d81Schristos 		const char	*features;
4739fb66d81Schristos 	} table[] = {
4749fb66d81Schristos #define TTY_FEATURES_BASE_MODERN_XTERM \
475de7701e2Schristos 	"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
4769fb66d81Schristos 		{ .name = "mintty",
4779fb66d81Schristos 		  .features = TTY_FEATURES_BASE_MODERN_XTERM
4789fb66d81Schristos 			      ",ccolour,cstyle,extkeys,margins,overline,usstyle"
4799fb66d81Schristos 		},
4809fb66d81Schristos 		{ .name = "tmux",
4819fb66d81Schristos 		  .features = TTY_FEATURES_BASE_MODERN_XTERM
482c23f9150Swiz 			      ",ccolour,cstyle,focus,overline,usstyle,hyperlinks"
4839fb66d81Schristos 		},
4849fb66d81Schristos 		{ .name = "rxvt-unicode",
485c23f9150Swiz 		  .features = "256,bpaste,ccolour,cstyle,mouse,title,ignorefkeys"
4869fb66d81Schristos 		},
4879fb66d81Schristos 		{ .name = "iTerm2",
4889fb66d81Schristos 		  .features = TTY_FEATURES_BASE_MODERN_XTERM
489c23f9150Swiz 			      ",cstyle,extkeys,margins,usstyle,sync,osc7,hyperlinks"
4909fb66d81Schristos 		},
4919fb66d81Schristos 		{ .name = "XTerm",
492de7701e2Schristos 		  /*
493de7701e2Schristos 		   * xterm also supports DECSLRM and DECFRA, but they can be
494de7701e2Schristos 		   * disabled so not set it here - they will be added if
495de7701e2Schristos 		   * secondary DA shows VT420.
496de7701e2Schristos 		   */
4979fb66d81Schristos 		  .features = TTY_FEATURES_BASE_MODERN_XTERM
498de7701e2Schristos 			      ",ccolour,cstyle,extkeys,focus"
4999fb66d81Schristos 		}
5009fb66d81Schristos 	};
5019fb66d81Schristos 	u_int	i;
5029fb66d81Schristos 
5039fb66d81Schristos 	for (i = 0; i < nitems(table); i++) {
5049fb66d81Schristos 		if (strcmp(table[i].name, name) != 0)
5059fb66d81Schristos 			continue;
5069fb66d81Schristos 		if (version != 0 && version < table[i].version)
5079fb66d81Schristos 			continue;
5089fb66d81Schristos 		tty_add_features(feat, table[i].features, ",");
5099fb66d81Schristos 	}
5109fb66d81Schristos }
511