mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		| @@ -171,6 +171,7 @@ dist_tmux_SOURCES = \ | |||||||
| 	tmux.c \ | 	tmux.c \ | ||||||
| 	tmux.h \ | 	tmux.h \ | ||||||
| 	tty-acs.c \ | 	tty-acs.c \ | ||||||
|  | 	tty-features.c \ | ||||||
| 	tty-keys.c \ | 	tty-keys.c \ | ||||||
| 	tty-term.c \ | 	tty-term.c \ | ||||||
| 	tty.c \ | 	tty.c \ | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								client.c
									
									
									
									
									
								
							| @@ -57,7 +57,7 @@ static struct client_files client_files = RB_INITIALIZER(&client_files); | |||||||
| static __dead void	 client_exec(const char *,const char *); | static __dead void	 client_exec(const char *,const char *); | ||||||
| static int		 client_get_lock(char *); | static int		 client_get_lock(char *); | ||||||
| static int		 client_connect(struct event_base *, const char *, int); | static int		 client_connect(struct event_base *, const char *, int); | ||||||
| static void		 client_send_identify(const char *, const char *); | static void		 client_send_identify(const char *, const char *, int); | ||||||
| static void		 client_signal(int); | static void		 client_signal(int); | ||||||
| static void		 client_dispatch(struct imsg *, void *); | static void		 client_dispatch(struct imsg *, void *); | ||||||
| static void		 client_dispatch_attached(struct imsg *); | static void		 client_dispatch_attached(struct imsg *); | ||||||
| @@ -233,7 +233,7 @@ client_exit(void) | |||||||
|  |  | ||||||
| /* Client main loop. */ | /* Client main loop. */ | ||||||
| int | int | ||||||
| client_main(struct event_base *base, int argc, char **argv, int flags) | client_main(struct event_base *base, int argc, char **argv, int flags, int feat) | ||||||
| { | { | ||||||
| 	struct cmd_parse_result	*pr; | 	struct cmd_parse_result	*pr; | ||||||
| 	struct msg_command	*data; | 	struct msg_command	*data; | ||||||
| @@ -342,7 +342,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Send identify messages. */ | 	/* Send identify messages. */ | ||||||
| 	client_send_identify(ttynam, cwd); | 	client_send_identify(ttynam, cwd, feat); | ||||||
|  |  | ||||||
| 	/* Send first command. */ | 	/* Send first command. */ | ||||||
| 	if (msg == MSG_COMMAND) { | 	if (msg == MSG_COMMAND) { | ||||||
| @@ -408,7 +408,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags) | |||||||
|  |  | ||||||
| /* Send identify messages to server. */ | /* Send identify messages to server. */ | ||||||
| static void | static void | ||||||
| client_send_identify(const char *ttynam, const char *cwd) | client_send_identify(const char *ttynam, const char *cwd, int feat) | ||||||
| { | { | ||||||
| 	const char	 *s; | 	const char	 *s; | ||||||
| 	char		**ss; | 	char		**ss; | ||||||
| @@ -421,6 +421,7 @@ client_send_identify(const char *ttynam, const char *cwd) | |||||||
| 	if ((s = getenv("TERM")) == NULL) | 	if ((s = getenv("TERM")) == NULL) | ||||||
| 		s = ""; | 		s = ""; | ||||||
| 	proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1); | 	proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1); | ||||||
|  | 	proc_send(client_peer, MSG_IDENTIFY_FEATURES, -1, &feat, sizeof feat); | ||||||
|  |  | ||||||
| 	proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, | 	proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, | ||||||
| 	    strlen(ttynam) + 1); | 	    strlen(ttynam) + 1); | ||||||
|   | |||||||
| @@ -42,22 +42,24 @@ const struct cmd_entry cmd_show_messages_entry = { | |||||||
| 	.exec = cmd_show_messages_exec | 	.exec = cmd_show_messages_exec | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int	cmd_show_messages_terminals(struct cmdq_item *, int); |  | ||||||
|  |  | ||||||
| static int | static int | ||||||
| cmd_show_messages_terminals(struct cmdq_item *item, int blank) | cmd_show_messages_terminals(struct cmd *self, struct cmdq_item *item, int blank) | ||||||
| { | { | ||||||
|  | 	struct args	*args = cmd_get_args(self); | ||||||
|  | 	struct client	*tc = cmdq_get_target_client(item); | ||||||
| 	struct tty_term	*term; | 	struct tty_term	*term; | ||||||
| 	u_int		 i, n; | 	u_int		 i, n; | ||||||
|  |  | ||||||
| 	n = 0; | 	n = 0; | ||||||
| 	LIST_FOREACH(term, &tty_terms, entry) { | 	LIST_FOREACH(term, &tty_terms, entry) { | ||||||
|  | 		if (args_has(args, 't') && term != tc->tty.term) | ||||||
|  | 			continue; | ||||||
| 		if (blank) { | 		if (blank) { | ||||||
| 			cmdq_print(item, "%s", ""); | 			cmdq_print(item, "%s", ""); | ||||||
| 			blank = 0; | 			blank = 0; | ||||||
| 		} | 		} | ||||||
| 		cmdq_print(item, "Terminal %u: %s [references=%u, flags=0x%x]:", | 		cmdq_print(item, "Terminal %u: %s for %s, flags=0x%x:", n, | ||||||
| 		    n, term->name, term->references, term->flags); | 		    term->name, term->tty->client->name, term->flags); | ||||||
| 		n++; | 		n++; | ||||||
| 		for (i = 0; i < tty_term_ncodes(); i++) | 		for (i = 0; i < tty_term_ncodes(); i++) | ||||||
| 			cmdq_print(item, "%s", tty_term_describe(term, i)); | 			cmdq_print(item, "%s", tty_term_describe(term, i)); | ||||||
| @@ -76,7 +78,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item) | |||||||
|  |  | ||||||
| 	done = blank = 0; | 	done = blank = 0; | ||||||
| 	if (args_has(args, 'T')) { | 	if (args_has(args, 'T')) { | ||||||
| 		blank = cmd_show_messages_terminals(item, blank); | 		blank = cmd_show_messages_terminals(self, item, blank); | ||||||
| 		done = 1; | 		done = 1; | ||||||
| 	} | 	} | ||||||
| 	if (args_has(args, 'J')) { | 	if (args_has(args, 'J')) { | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								format.c
									
									
									
									
									
								
							| @@ -2553,8 +2553,9 @@ format_defaults_client(struct format_tree *ft, struct client *c) | |||||||
| 	format_add(ft, "client_control_mode", "%d", | 	format_add(ft, "client_control_mode", "%d", | ||||||
| 		!!(c->flags & CLIENT_CONTROL)); | 		!!(c->flags & CLIENT_CONTROL)); | ||||||
|  |  | ||||||
| 	if (tty->term_name != NULL) | 	format_add(ft, "client_termname", "%s", c->term_name); | ||||||
| 		format_add(ft, "client_termname", "%s", tty->term_name); | 	format_add(ft, "client_termfeatures", "%s", | ||||||
|  | 	    tty_get_features(c->term_features)); | ||||||
|  |  | ||||||
| 	format_add_tv(ft, "client_created", &c->creation_time); | 	format_add_tv(ft, "client_created", &c->creation_time); | ||||||
| 	format_add_tv(ft, "client_activity", &c->activity_time); | 	format_add_tv(ft, "client_activity", &c->activity_time); | ||||||
| @@ -2569,7 +2570,7 @@ format_defaults_client(struct format_tree *ft, struct client *c) | |||||||
| 		format_add(ft, "client_prefix", "%d", 1); | 		format_add(ft, "client_prefix", "%d", 1); | ||||||
| 	format_add(ft, "client_key_table", "%s", c->keytable->name); | 	format_add(ft, "client_key_table", "%s", c->keytable->name); | ||||||
|  |  | ||||||
| 	if (tty_get_flags(tty) & TERM_UTF8) | 	if (c->flags & CLIENT_UTF8) | ||||||
| 		format_add(ft, "client_utf8", "%d", 1); | 		format_add(ft, "client_utf8", "%d", 1); | ||||||
| 	else | 	else | ||||||
| 		format_add(ft, "client_utf8", "%d", 0); | 		format_add(ft, "client_utf8", "%d", 0); | ||||||
|   | |||||||
| @@ -260,9 +260,16 @@ const struct options_table_entry options_table[] = { | |||||||
| 	  .type = OPTIONS_TABLE_STRING, | 	  .type = OPTIONS_TABLE_STRING, | ||||||
| 	  .scope = OPTIONS_TABLE_SERVER, | 	  .scope = OPTIONS_TABLE_SERVER, | ||||||
| 	  .flags = OPTIONS_TABLE_IS_ARRAY, | 	  .flags = OPTIONS_TABLE_IS_ARRAY, | ||||||
| 	  .default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" | 	  .default_str = "tmux*:XT,screen*:XT", | ||||||
| 			 ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007" | 	  .separator = "," | ||||||
| 			 ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT", | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "terminal-features", | ||||||
|  | 	  .type = OPTIONS_TABLE_STRING, | ||||||
|  | 	  .scope = OPTIONS_TABLE_SERVER, | ||||||
|  | 	  .flags = OPTIONS_TABLE_IS_ARRAY, | ||||||
|  | 	  .default_str = "xterm*:clipboard:ccolour:cstyle:title," | ||||||
|  | 	                 "screen*:title", | ||||||
| 	  .separator = "," | 	  .separator = "," | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -294,7 +294,7 @@ server_client_lost(struct client *c) | |||||||
| 	if (c->flags & CLIENT_TERMINAL) | 	if (c->flags & CLIENT_TERMINAL) | ||||||
| 		tty_free(&c->tty); | 		tty_free(&c->tty); | ||||||
| 	free(c->ttyname); | 	free(c->ttyname); | ||||||
| 	free(c->term); | 	free(c->term_name); | ||||||
|  |  | ||||||
| 	status_free(c); | 	status_free(c); | ||||||
|  |  | ||||||
| @@ -1843,6 +1843,7 @@ server_client_dispatch(struct imsg *imsg, void *arg) | |||||||
| 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE; | 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE; | ||||||
|  |  | ||||||
| 	switch (imsg->hdr.type) { | 	switch (imsg->hdr.type) { | ||||||
|  | 	case MSG_IDENTIFY_FEATURES: | ||||||
| 	case MSG_IDENTIFY_FLAGS: | 	case MSG_IDENTIFY_FLAGS: | ||||||
| 	case MSG_IDENTIFY_TERM: | 	case MSG_IDENTIFY_TERM: | ||||||
| 	case MSG_IDENTIFY_TTYNAME: | 	case MSG_IDENTIFY_TTYNAME: | ||||||
| @@ -2001,7 +2002,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) | |||||||
| { | { | ||||||
| 	const char	*data, *home; | 	const char	*data, *home; | ||||||
| 	size_t		 datalen; | 	size_t		 datalen; | ||||||
| 	int		 flags; | 	int		 flags, feat; | ||||||
| 	char		*name; | 	char		*name; | ||||||
|  |  | ||||||
| 	if (c->flags & CLIENT_IDENTIFIED) | 	if (c->flags & CLIENT_IDENTIFIED) | ||||||
| @@ -2011,6 +2012,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) | |||||||
| 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE; | 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE; | ||||||
|  |  | ||||||
| 	switch (imsg->hdr.type)	{ | 	switch (imsg->hdr.type)	{ | ||||||
|  | 	case MSG_IDENTIFY_FEATURES: | ||||||
|  | 		if (datalen != sizeof feat) | ||||||
|  | 			fatalx("bad MSG_IDENTIFY_FEATURES size"); | ||||||
|  | 		memcpy(&feat, data, sizeof feat); | ||||||
|  | 		c->term_features |= feat; | ||||||
|  | 		log_debug("client %p IDENTIFY_FEATURES %s", c, | ||||||
|  | 		    tty_get_features(feat)); | ||||||
|  | 		break; | ||||||
| 	case MSG_IDENTIFY_FLAGS: | 	case MSG_IDENTIFY_FLAGS: | ||||||
| 		if (datalen != sizeof flags) | 		if (datalen != sizeof flags) | ||||||
| 			fatalx("bad MSG_IDENTIFY_FLAGS size"); | 			fatalx("bad MSG_IDENTIFY_FLAGS size"); | ||||||
| @@ -2021,7 +2030,10 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) | |||||||
| 	case MSG_IDENTIFY_TERM: | 	case MSG_IDENTIFY_TERM: | ||||||
| 		if (datalen == 0 || data[datalen - 1] != '\0') | 		if (datalen == 0 || data[datalen - 1] != '\0') | ||||||
| 			fatalx("bad MSG_IDENTIFY_TERM string"); | 			fatalx("bad MSG_IDENTIFY_TERM string"); | ||||||
| 		c->term = xstrdup(data); | 		if (*data == '\0') | ||||||
|  | 			c->term_name = xstrdup("unknown"); | ||||||
|  | 		else | ||||||
|  | 			c->term_name = xstrdup(data); | ||||||
| 		log_debug("client %p IDENTIFY_TERM %s", c, data); | 		log_debug("client %p IDENTIFY_TERM %s", c, data); | ||||||
| 		break; | 		break; | ||||||
| 	case MSG_IDENTIFY_TTYNAME: | 	case MSG_IDENTIFY_TTYNAME: | ||||||
| @@ -2086,14 +2098,10 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) | |||||||
| 		control_start(c); | 		control_start(c); | ||||||
| 		c->tty.fd = -1; | 		c->tty.fd = -1; | ||||||
| 	} else if (c->fd != -1) { | 	} else if (c->fd != -1) { | ||||||
| 		if (tty_init(&c->tty, c, c->fd, c->term) != 0) { | 		if (tty_init(&c->tty, c, c->fd) != 0) { | ||||||
| 			close(c->fd); | 			close(c->fd); | ||||||
| 			c->fd = -1; | 			c->fd = -1; | ||||||
| 		} else { | 		} else { | ||||||
| 			if (c->flags & CLIENT_UTF8) |  | ||||||
| 				c->tty.term_flags |= TERM_UTF8; |  | ||||||
| 			if (c->flags & CLIENT_256COLOURS) |  | ||||||
| 				c->tty.term_flags |= TERM_256COLOURS; |  | ||||||
| 			tty_resize(&c->tty); | 			tty_resize(&c->tty); | ||||||
| 			c->flags |= CLIENT_TERMINAL; | 			c->flags |= CLIENT_TERMINAL; | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										94
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -28,6 +28,7 @@ | |||||||
| .Op Fl f Ar file | .Op Fl f Ar file | ||||||
| .Op Fl L Ar socket-name | .Op Fl L Ar socket-name | ||||||
| .Op Fl S Ar socket-path | .Op Fl S Ar socket-path | ||||||
|  | .Op Fl T Ar features | ||||||
| .Op Ar command Op Ar flags | .Op Ar command Op Ar flags | ||||||
| .Ek | .Ek | ||||||
| .Sh DESCRIPTION | .Sh DESCRIPTION | ||||||
| @@ -98,6 +99,8 @@ The options are as follows: | |||||||
| Force | Force | ||||||
| .Nm | .Nm | ||||||
| to assume the terminal supports 256 colours. | to assume the terminal supports 256 colours. | ||||||
|  | This is equivalent to | ||||||
|  | .Fl T Ar 256 . | ||||||
| .It Fl C | .It Fl C | ||||||
| Start in control mode (see the | Start in control mode (see the | ||||||
| .Sx CONTROL MODE | .Sx CONTROL MODE | ||||||
| @@ -186,6 +189,14 @@ that is set does not contain | |||||||
| .Qq UTF-8 | .Qq UTF-8 | ||||||
| or | or | ||||||
| .Qq UTF8 . | .Qq UTF8 . | ||||||
|  | This is equivalent to | ||||||
|  | .Fl T Ar UTF-8 . | ||||||
|  | .It Fl T Ar features | ||||||
|  | Set terminal features for the client. | ||||||
|  | This is a comma-separated list of features. | ||||||
|  | See the | ||||||
|  | .Ic terminal-features | ||||||
|  | option. | ||||||
| .It Fl v | .It Fl v | ||||||
| Request verbose logging. | Request verbose logging. | ||||||
| Log messages will be saved into | Log messages will be saved into | ||||||
| @@ -3166,6 +3177,63 @@ disallowedWindowOps: 20,21,SetXprop | |||||||
| Or changing this property from the | Or changing this property from the | ||||||
| .Xr xterm 1 | .Xr xterm 1 | ||||||
| interactive menu when required. | interactive menu when required. | ||||||
|  | .It Ic terminal-features[] Ar string | ||||||
|  | Set terminal features for terminal types read from | ||||||
|  | .Xr terminfo 5 . | ||||||
|  | .Nm | ||||||
|  | has a set of named terminal features. | ||||||
|  | Each will apply appropriate changes to the | ||||||
|  | .Xr terminfo 5 | ||||||
|  | entry in use. | ||||||
|  | .Pp | ||||||
|  | .Nm | ||||||
|  | can detect features for a few common terminals; this option can be used to | ||||||
|  | easily tell tmux about features supported by terminals it cannot detect. | ||||||
|  | The | ||||||
|  | .Ic terminal-overrides | ||||||
|  | option allows individual | ||||||
|  | .Xr terminfo 5 | ||||||
|  | capabilities to be set instead, | ||||||
|  | .Ic terminal-features | ||||||
|  | is intended for classes of functionality supported in a standard way but not | ||||||
|  | reported by | ||||||
|  | .Xr terminfo 5 . | ||||||
|  | Care must be taken only to configure this with features the terminal actually | ||||||
|  | support. | ||||||
|  | .Pp | ||||||
|  | This is an array option where each entry is a colon-separated string made up | ||||||
|  | of a terminal type pattern (matched using | ||||||
|  | .Xr fnmatch 3 ) | ||||||
|  | followed by a list of terminal features. | ||||||
|  | The available features are: | ||||||
|  | .Bl -tag -width Ds | ||||||
|  | .It 256 | ||||||
|  | Supports 256 colours with the SGR escape sequences. | ||||||
|  | .It clipboard | ||||||
|  | Allows setting the system clipboard. | ||||||
|  | .It ccolour | ||||||
|  | Allows setting the cursor colour. | ||||||
|  | .It cstyle | ||||||
|  | Allows setting the cursor style. | ||||||
|  | .It margins | ||||||
|  | Supports DECSLRM margins. | ||||||
|  | .It overline | ||||||
|  | Supports the overline SGR attribute. | ||||||
|  | .It rectfill | ||||||
|  | Supports the DECFRA rectangle fill escape sequence. | ||||||
|  | .It RGB | ||||||
|  | Supports RGB colour with the SGR escape sequences. | ||||||
|  | .It sync | ||||||
|  | Supports synchronized updates. | ||||||
|  | .It title | ||||||
|  | Supports | ||||||
|  | .Xr xterm 1 | ||||||
|  | title setting. | ||||||
|  | .It usstyle | ||||||
|  | Allows underscore style and colour to be set. | ||||||
|  | .It UTF-8 | ||||||
|  | Is able to handle UTF-8 output. | ||||||
|  | .El | ||||||
| .It Ic terminal-overrides[] Ar string | .It Ic terminal-overrides[] Ar string | ||||||
| Allow terminal descriptions read using | Allow terminal descriptions read using | ||||||
| .Xr terminfo 5 | .Xr terminfo 5 | ||||||
| @@ -4383,6 +4451,7 @@ The following variables are available, where appropriate: | |||||||
| .It Li "client_readonly" Ta "" Ta "1 if client is readonly" | .It Li "client_readonly" Ta "" Ta "1 if client is readonly" | ||||||
| .It Li "client_session" Ta "" Ta "Name of the client's session" | .It Li "client_session" Ta "" Ta "Name of the client's session" | ||||||
| .It Li "client_termname" Ta "" Ta "Terminal name of client" | .It Li "client_termname" Ta "" Ta "Terminal name of client" | ||||||
|  | .It Li "client_termfeatures" Ta "" Ta "Terminal features of client" | ||||||
| .It Li "client_tty" Ta "" Ta "Pseudo terminal of client" | .It Li "client_tty" Ta "" Ta "Pseudo terminal of client" | ||||||
| .It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8" | .It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8" | ||||||
| .It Li "client_width" Ta "" Ta "Width of client" | .It Li "client_width" Ta "" Ta "Width of client" | ||||||
| @@ -5465,7 +5534,10 @@ The server crashed or otherwise exited without telling the client the reason. | |||||||
| .Sh TERMINFO EXTENSIONS | .Sh TERMINFO EXTENSIONS | ||||||
| .Nm | .Nm | ||||||
| understands some unofficial extensions to | understands some unofficial extensions to | ||||||
| .Xr terminfo 5 : | .Xr terminfo 5. | ||||||
|  | It is not normally necessary to set these manually, instead the | ||||||
|  | .Ic terminal-features | ||||||
|  | option should be used. | ||||||
| .Bl -tag -width Ds | .Bl -tag -width Ds | ||||||
| .It Em \&Cs , Cr | .It Em \&Cs , Cr | ||||||
| Set the cursor colour. | Set the cursor colour. | ||||||
| @@ -5479,33 +5551,15 @@ $ printf '\e033]12;red\e033\e\e' | |||||||
| .Ed | .Ed | ||||||
| .It Em \&Smol | .It Em \&Smol | ||||||
| Enable the overline attribute. | Enable the overline attribute. | ||||||
| The capability is usually SGR 53 and can be added to |  | ||||||
| .Ic terminal-overrides |  | ||||||
| as: |  | ||||||
| .Bd -literal -offset indent |  | ||||||
| Smol=\eE[53m |  | ||||||
| .Ed |  | ||||||
| .It Em \&Smulx | .It Em \&Smulx | ||||||
| Set a styled underscore. | Set a styled underscore. | ||||||
| The single parameter is one of: 0 for no underscore, 1 for normal | The single parameter is one of: 0 for no underscore, 1 for normal | ||||||
| underscore, 2 for double underscore, 3 for curly underscore, 4 for dotted | underscore, 2 for double underscore, 3 for curly underscore, 4 for dotted | ||||||
| underscore and 5 for dashed underscore. | underscore and 5 for dashed underscore. | ||||||
| The capability can typically be added to |  | ||||||
| .Ic terminal-overrides |  | ||||||
| as: |  | ||||||
| .Bd -literal -offset indent |  | ||||||
| Smulx=\eE[4::%p1%dm |  | ||||||
| .Ed |  | ||||||
| .It Em \&Setulc | .It Em \&Setulc | ||||||
| Set the underscore colour. | Set the underscore colour. | ||||||
| The argument is (red * 65536) + (green * 256) + blue where each is between 0 | The argument is (red * 65536) + (green * 256) + blue where each is between 0 | ||||||
| and 255. | and 255. | ||||||
| The capability can typically be added to |  | ||||||
| .Ic terminal-overrides |  | ||||||
| as: |  | ||||||
| .Bd -literal -offset indent |  | ||||||
| Setulc=\eE[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m |  | ||||||
| .Ed |  | ||||||
| .It Em \&Ss , Se | .It Em \&Ss , Se | ||||||
| Set or reset the cursor style. | Set or reset the cursor style. | ||||||
| If set, a sequence such as this may be used | If set, a sequence such as this may be used | ||||||
| @@ -5518,7 +5572,7 @@ If | |||||||
| .Em Se | .Em Se | ||||||
| is not set, \&Ss with argument 0 will be used to reset the cursor style instead. | is not set, \&Ss with argument 0 will be used to reset the cursor style instead. | ||||||
| .It Em \&Sync | .It Em \&Sync | ||||||
| Show that the terminal supports synchronized updates. | Start (parameter is 1) or end (parameter is 2) a synchronized update. | ||||||
| .It Em \&Tc | .It Em \&Tc | ||||||
| Indicate that the terminal supports the | Indicate that the terminal supports the | ||||||
| .Ql direct colour | .Ql direct colour | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								tmux.c
									
									
									
									
									
								
							| @@ -55,7 +55,7 @@ usage(void) | |||||||
| { | { | ||||||
| 	fprintf(stderr, | 	fprintf(stderr, | ||||||
| 	    "usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n" | 	    "usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n" | ||||||
| 	    "            [-S socket-path] [command [flags]]\n", | 	    "            [-S socket-path] [-T features] [command [flags]]\n", | ||||||
| 	    getprogname()); | 	    getprogname()); | ||||||
| 	exit(1); | 	exit(1); | ||||||
| } | } | ||||||
| @@ -233,9 +233,11 @@ getversion(void) | |||||||
| int | int | ||||||
| main(int argc, char **argv) | main(int argc, char **argv) | ||||||
| { | { | ||||||
| 	char					*path, *label, *cause, **var; | 	char					*path = NULL, *label = NULL; | ||||||
|  | 	char					*cause, **var; | ||||||
| 	const char				*s, *shell, *cwd; | 	const char				*s, *shell, *cwd; | ||||||
| 	int					 opt, flags, keys; | 	int					 opt, flags = 0, keys; | ||||||
|  | 	int					 feat = 0; | ||||||
| 	const struct options_table_entry	*oe; | 	const struct options_table_entry	*oe; | ||||||
|  |  | ||||||
| 	if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL && | 	if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL && | ||||||
| @@ -252,14 +254,11 @@ main(int argc, char **argv) | |||||||
|  |  | ||||||
| 	if (**argv == '-') | 	if (**argv == '-') | ||||||
| 		flags = CLIENT_LOGIN; | 		flags = CLIENT_LOGIN; | ||||||
| 	else |  | ||||||
| 		flags = 0; |  | ||||||
|  |  | ||||||
| 	label = path = NULL; | 	while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:T:uUvV")) != -1) { | ||||||
| 	while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUvV")) != -1) { |  | ||||||
| 		switch (opt) { | 		switch (opt) { | ||||||
| 		case '2': | 		case '2': | ||||||
| 			flags |= CLIENT_256COLOURS; | 			tty_add_features(&feat, "256", ":,"); | ||||||
| 			break; | 			break; | ||||||
| 		case 'c': | 		case 'c': | ||||||
| 			shell_command = optarg; | 			shell_command = optarg; | ||||||
| @@ -289,6 +288,9 @@ main(int argc, char **argv) | |||||||
| 			free(path); | 			free(path); | ||||||
| 			path = xstrdup(optarg); | 			path = xstrdup(optarg); | ||||||
| 			break; | 			break; | ||||||
|  | 		case 'T': | ||||||
|  | 			tty_add_features(&feat, optarg, ":,"); | ||||||
|  | 			break; | ||||||
| 		case 'u': | 		case 'u': | ||||||
| 			flags |= CLIENT_UTF8; | 			flags |= CLIENT_UTF8; | ||||||
| 			break; | 			break; | ||||||
| @@ -396,5 +398,5 @@ main(int argc, char **argv) | |||||||
| 	free(label); | 	free(label); | ||||||
|  |  | ||||||
| 	/* Pass control to the client. */ | 	/* Pass control to the client. */ | ||||||
| 	exit(client_main(osdep_event_init(), argc, argv, flags)); | 	exit(client_main(event_init(), argc, argv, flags, feat)); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -476,6 +476,7 @@ enum msgtype { | |||||||
| 	MSG_IDENTIFY_DONE, | 	MSG_IDENTIFY_DONE, | ||||||
| 	MSG_IDENTIFY_CLIENTPID, | 	MSG_IDENTIFY_CLIENTPID, | ||||||
| 	MSG_IDENTIFY_CWD, | 	MSG_IDENTIFY_CWD, | ||||||
|  | 	MSG_IDENTIFY_FEATURES, | ||||||
|  |  | ||||||
| 	MSG_COMMAND = 200, | 	MSG_COMMAND = 200, | ||||||
| 	MSG_DETACH, | 	MSG_DETACH, | ||||||
| @@ -1178,7 +1179,8 @@ struct tty_key { | |||||||
| struct tty_code; | struct tty_code; | ||||||
| struct tty_term { | struct tty_term { | ||||||
| 	char		*name; | 	char		*name; | ||||||
| 	u_int		 references; | 	struct tty	*tty; | ||||||
|  | 	int		 features; | ||||||
|  |  | ||||||
| 	char		 acs[UCHAR_MAX + 1][2]; | 	char		 acs[UCHAR_MAX + 1][2]; | ||||||
|  |  | ||||||
| @@ -1189,8 +1191,6 @@ struct tty_term { | |||||||
| #define TERM_DECSLRM 0x4 | #define TERM_DECSLRM 0x4 | ||||||
| #define TERM_DECFRA 0x8 | #define TERM_DECFRA 0x8 | ||||||
| #define TERM_RGBCOLOURS 0x10 | #define TERM_RGBCOLOURS 0x10 | ||||||
| #define TERM_SYNC 0x20 |  | ||||||
| #define TERM_UTF8 0x40 |  | ||||||
| 	int		 flags; | 	int		 flags; | ||||||
|  |  | ||||||
| 	LIST_ENTRY(tty_term) entry; | 	LIST_ENTRY(tty_term) entry; | ||||||
| @@ -1254,8 +1254,6 @@ struct tty { | |||||||
| 	int		 flags; | 	int		 flags; | ||||||
|  |  | ||||||
| 	struct tty_term	*term; | 	struct tty_term	*term; | ||||||
| 	char		*term_name; |  | ||||||
| 	int		 term_flags; |  | ||||||
|  |  | ||||||
| 	u_int		 mouse_last_x; | 	u_int		 mouse_last_x; | ||||||
| 	u_int		 mouse_last_y; | 	u_int		 mouse_last_y; | ||||||
| @@ -1269,7 +1267,6 @@ struct tty { | |||||||
| 	struct event	 key_timer; | 	struct event	 key_timer; | ||||||
| 	struct tty_key	*key_tree; | 	struct tty_key	*key_tree; | ||||||
| }; | }; | ||||||
| #define tty_term_flags(tty) (tty->term->flags|tty->term_flags) |  | ||||||
|  |  | ||||||
| /* TTY command context. */ | /* TTY command context. */ | ||||||
| struct tty_ctx { | struct tty_ctx { | ||||||
| @@ -1500,7 +1497,9 @@ struct client { | |||||||
| 	char		*title; | 	char		*title; | ||||||
| 	const char	*cwd; | 	const char	*cwd; | ||||||
|  |  | ||||||
| 	char		*term; | 	char		*term_name; | ||||||
|  | 	int		 term_features; | ||||||
|  |  | ||||||
| 	char		*ttyname; | 	char		*ttyname; | ||||||
| 	struct tty	 tty; | 	struct tty	 tty; | ||||||
|  |  | ||||||
| @@ -1533,7 +1532,7 @@ struct client { | |||||||
| #define CLIENT_CONTROLCONTROL 0x4000 | #define CLIENT_CONTROLCONTROL 0x4000 | ||||||
| #define CLIENT_FOCUSED 0x8000 | #define CLIENT_FOCUSED 0x8000 | ||||||
| #define CLIENT_UTF8 0x10000 | #define CLIENT_UTF8 0x10000 | ||||||
| #define CLIENT_256COLOURS 0x20000 | /* 0x20000 unused */ | ||||||
| #define CLIENT_IDENTIFIED 0x40000 | #define CLIENT_IDENTIFIED 0x40000 | ||||||
| #define CLIENT_STATUSFORCE 0x80000 | #define CLIENT_STATUSFORCE 0x80000 | ||||||
| #define CLIENT_DOUBLECLICK 0x100000 | #define CLIENT_DOUBLECLICK 0x100000 | ||||||
| @@ -1955,7 +1954,7 @@ void	tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *, | |||||||
| void	tty_puts(struct tty *, const char *); | void	tty_puts(struct tty *, const char *); | ||||||
| void	tty_putc(struct tty *, u_char); | void	tty_putc(struct tty *, u_char); | ||||||
| void	tty_putn(struct tty *, const void *, size_t, u_int); | void	tty_putn(struct tty *, const void *, size_t, u_int); | ||||||
| int	tty_init(struct tty *, struct client *, int, char *); | int	tty_init(struct tty *, struct client *, int); | ||||||
| void	tty_resize(struct tty *); | void	tty_resize(struct tty *); | ||||||
| void	tty_set_size(struct tty *, u_int, u_int, u_int, u_int); | void	tty_set_size(struct tty *, u_int, u_int, u_int, u_int); | ||||||
| void	tty_start_tty(struct tty *); | void	tty_start_tty(struct tty *); | ||||||
| @@ -1970,8 +1969,7 @@ void	tty_sync_end(struct tty *); | |||||||
| int	tty_open(struct tty *, char **); | int	tty_open(struct tty *, char **); | ||||||
| void	tty_close(struct tty *); | void	tty_close(struct tty *); | ||||||
| void	tty_free(struct tty *); | void	tty_free(struct tty *); | ||||||
| void	tty_set_flags(struct tty *, int); | void	tty_update_features(struct tty *); | ||||||
| int	tty_get_flags(struct tty *); |  | ||||||
| void	tty_write(void (*)(struct tty *, const struct tty_ctx *), | void	tty_write(void (*)(struct tty *, const struct tty_ctx *), | ||||||
| 	    struct tty_ctx *); | 	    struct tty_ctx *); | ||||||
| void	tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *); | void	tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *); | ||||||
| @@ -2001,7 +1999,8 @@ void	tty_cmd_syncend(struct tty *, const struct tty_ctx *); | |||||||
| /* tty-term.c */ | /* tty-term.c */ | ||||||
| extern struct tty_terms tty_terms; | extern struct tty_terms tty_terms; | ||||||
| u_int		 tty_term_ncodes(void); | u_int		 tty_term_ncodes(void); | ||||||
| struct tty_term *tty_term_find(char *, int, char **); | void		 tty_term_apply(struct tty_term *, const char *, int); | ||||||
|  | struct tty_term *tty_term_create(struct tty *, char *, int *, int, char **); | ||||||
| void		 tty_term_free(struct tty_term *); | void		 tty_term_free(struct tty_term *); | ||||||
| int		 tty_term_has(struct tty_term *, enum tty_code_code); | int		 tty_term_has(struct tty_term *, enum tty_code_code); | ||||||
| const char	*tty_term_string(struct tty_term *, enum tty_code_code); | const char	*tty_term_string(struct tty_term *, enum tty_code_code); | ||||||
| @@ -2018,6 +2017,11 @@ int		 tty_term_number(struct tty_term *, enum tty_code_code); | |||||||
| int		 tty_term_flag(struct tty_term *, enum tty_code_code); | int		 tty_term_flag(struct tty_term *, enum tty_code_code); | ||||||
| const char	*tty_term_describe(struct tty_term *, enum tty_code_code); | const char	*tty_term_describe(struct tty_term *, enum tty_code_code); | ||||||
|  |  | ||||||
|  | /* tty-features.c */ | ||||||
|  | void		 tty_add_features(int *, const char *, const char *); | ||||||
|  | const char	*tty_get_features(int); | ||||||
|  | void		 tty_apply_features(struct tty_term *, int); | ||||||
|  |  | ||||||
| /* tty-acs.c */ | /* tty-acs.c */ | ||||||
| int		 tty_acs_needed(struct tty *); | int		 tty_acs_needed(struct tty *); | ||||||
| const char	*tty_acs_get(struct tty *, u_char); | const char	*tty_acs_get(struct tty *, u_char); | ||||||
| @@ -2163,7 +2167,7 @@ void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...); | |||||||
| void	cmd_wait_for_flush(void); | void	cmd_wait_for_flush(void); | ||||||
|  |  | ||||||
| /* client.c */ | /* client.c */ | ||||||
| int	client_main(struct event_base *, int, char **, int); | int	client_main(struct event_base *, int, char **, int, int); | ||||||
|  |  | ||||||
| /* key-bindings.c */ | /* key-bindings.c */ | ||||||
| struct key_table *key_bindings_get_table(const char *, int); | struct key_table *key_bindings_get_table(const char *, int); | ||||||
|   | |||||||
| @@ -99,7 +99,7 @@ tty_acs_needed(struct tty *tty) | |||||||
| 	    tty_term_number(tty->term, TTYC_U8) == 0) | 	    tty_term_number(tty->term, TTYC_U8) == 0) | ||||||
| 		return (1); | 		return (1); | ||||||
|  |  | ||||||
| 	if (tty_get_flags(tty) & TERM_UTF8) | 	if (tty->client->flags & CLIENT_UTF8) | ||||||
| 		return (0); | 		return (0); | ||||||
| 	return (1); | 	return (1); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										263
									
								
								tty-features.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								tty-features.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,263 @@ | |||||||
|  | /* $OpenBSD$ */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com> | ||||||
|  |  * | ||||||
|  |  * Permission to use, copy, modify, and distribute this software for any | ||||||
|  |  * purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  * copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | ||||||
|  |  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <sys/types.h> | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "tmux.h" | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Still hardcoded: | ||||||
|  |  * - bracket paste (sent if application asks for it); | ||||||
|  |  * - mouse (under kmous capability); | ||||||
|  |  * - focus events (under focus-events option); | ||||||
|  |  * - default colours (under AX or op capabilities); | ||||||
|  |  * - AIX colours (under colors >= 16); | ||||||
|  |  * - alternate escape (under XT). | ||||||
|  |  * | ||||||
|  |  * Also: | ||||||
|  |  * - XT is used to decide whether to send DA and DSR, | ||||||
|  |  * - DECSLRM and DECFRA use a flag instead of capabilities. | ||||||
|  |  * - UTF-8 is a separate flag on the client; needed for unattached clients. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* A named terminal feature. */ | ||||||
|  | struct tty_feature { | ||||||
|  | 	const char	 *name; | ||||||
|  | 	const char	**capabilities; | ||||||
|  | 	int		  flags; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal has xterm(1) title setting. */ | ||||||
|  | static const char *tty_feature_title_capabilities[] = { | ||||||
|  | 	"tsl=\\E]0;", /* should be using TS really */ | ||||||
|  | 	"fsl=\\a", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_title = { | ||||||
|  | 	"title", | ||||||
|  | 	tty_feature_title_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal can set the clipboard with OSC 52. */ | ||||||
|  | static const char *tty_feature_clipboard_capabilities[] = { | ||||||
|  | 	"Ms=\\E]52;%p1%s;%p2%s\\a", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_clipboard = { | ||||||
|  | 	"clipboard", | ||||||
|  | 	tty_feature_clipboard_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Terminal supports RGB colour. This replaces setab and setaf also since | ||||||
|  |  * terminals with RGB have versions that do not allow setting colours from the | ||||||
|  |  * 256 palette. | ||||||
|  |  */ | ||||||
|  | static const char *tty_feature_rgb_capabilities[] = { | ||||||
|  | 	"setrgbf=\\E[38;2;%p1%d;%p2%d;%p3%dm", | ||||||
|  | 	"setrgbb=\\E[48;2;%p1%d;%p2%d;%p3%dm", | ||||||
|  | 	"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", | ||||||
|  | 	"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_rgb = { | ||||||
|  | 	"RGB", | ||||||
|  | 	tty_feature_rgb_capabilities, | ||||||
|  | 	(TERM_256COLOURS|TERM_RGBCOLOURS) | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports 256 colours. */ | ||||||
|  | static const char *tty_feature_256_capabilities[] = { | ||||||
|  | 	"setab=\\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", | ||||||
|  | 	"setaf=\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_256 = { | ||||||
|  | 	"256", | ||||||
|  | 	tty_feature_256_capabilities, | ||||||
|  | 	TERM_256COLOURS | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports overline. */ | ||||||
|  | static const char *tty_feature_overline_capabilities[] = { | ||||||
|  | 	"Smol=\\E[53m", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_overline = { | ||||||
|  | 	"overline", | ||||||
|  | 	tty_feature_overline_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports underscore styles. */ | ||||||
|  | static const char *tty_feature_usstyle_capabilities[] = { | ||||||
|  | 	"Smulx=\E[4::%p1%dm", | ||||||
|  | 	"Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_usstyle = { | ||||||
|  | 	"usstyle", | ||||||
|  | 	tty_feature_usstyle_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports cursor styles. */ | ||||||
|  | static const char *tty_feature_cstyle_capabilities[] = { | ||||||
|  | 	"Ss=\\E[%p1%d q", | ||||||
|  | 	"Se=\\E[2 q", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_cstyle = { | ||||||
|  | 	"cstyle", | ||||||
|  | 	tty_feature_cstyle_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports cursor colours. */ | ||||||
|  | static const char *tty_feature_ccolour_capabilities[] = { | ||||||
|  | 	"Cs=\\E]12;%p1%s\\a", | ||||||
|  | 	"Cr=\\E]112\\a", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_ccolour = { | ||||||
|  | 	"ccolour", | ||||||
|  | 	tty_feature_ccolour_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports synchronized updates. */ | ||||||
|  | static const char *tty_feature_sync_capabilities[] = { | ||||||
|  | 	"Sync=\\EP=%p1%ds\\E\\\\", | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | static struct tty_feature tty_feature_sync = { | ||||||
|  | 	"sync", | ||||||
|  | 	tty_feature_sync_capabilities, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports DECSLRM margins. */ | ||||||
|  | static struct tty_feature tty_feature_margins = { | ||||||
|  | 	"margins", | ||||||
|  | 	NULL, | ||||||
|  | 	TERM_DECSLRM | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Terminal supports DECFRA rectangle fill. */ | ||||||
|  | static struct tty_feature tty_feature_rectfill = { | ||||||
|  | 	"rectfill", | ||||||
|  | 	NULL, | ||||||
|  | 	TERM_DECFRA | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Available terminal features. */ | ||||||
|  | static const struct tty_feature *tty_features[] = { | ||||||
|  | 	&tty_feature_256, | ||||||
|  | 	&tty_feature_clipboard, | ||||||
|  | 	&tty_feature_ccolour, | ||||||
|  | 	&tty_feature_cstyle, | ||||||
|  | 	&tty_feature_margins, | ||||||
|  | 	&tty_feature_overline, | ||||||
|  | 	&tty_feature_rectfill, | ||||||
|  | 	&tty_feature_rgb, | ||||||
|  | 	&tty_feature_sync, | ||||||
|  | 	&tty_feature_title, | ||||||
|  | 	&tty_feature_usstyle | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void | ||||||
|  | tty_add_features(int *feat, const char *s, const char *separators) | ||||||
|  | { | ||||||
|  | 	const struct tty_feature	 *tf; | ||||||
|  | 	char				 *next, *loop, *copy; | ||||||
|  | 	u_int				  i; | ||||||
|  |  | ||||||
|  | 	loop = copy = xstrdup(s); | ||||||
|  | 	while ((next = strsep(&loop, separators)) != NULL) { | ||||||
|  | 		for (i = 0; i < nitems(tty_features); i++) { | ||||||
|  | 			tf = tty_features[i]; | ||||||
|  | 			if (strcasecmp(tf->name, next) == 0) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		if (i == nitems(tty_features)) { | ||||||
|  | 			log_debug("unknown terminal feature: %s", next); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (~(*feat) & (1 << i)) { | ||||||
|  | 			log_debug("adding terminal feature: %s", tf->name); | ||||||
|  | 			(*feat) |= (1 << i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	free(copy); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const char * | ||||||
|  | tty_get_features(int feat) | ||||||
|  | { | ||||||
|  | 	const struct tty_feature	*tf; | ||||||
|  | 	static char			 s[512]; | ||||||
|  | 	u_int				 i; | ||||||
|  |  | ||||||
|  | 	*s = '\0'; | ||||||
|  | 	for (i = 0; i < nitems(tty_features); i++) { | ||||||
|  | 		if (~feat & (1 << i)) | ||||||
|  | 			continue; | ||||||
|  | 		tf = tty_features[i]; | ||||||
|  |  | ||||||
|  | 		strlcat(s, tf->name, sizeof s); | ||||||
|  | 		strlcat(s, ",", sizeof s); | ||||||
|  | 	} | ||||||
|  | 	if (*s != '\0') | ||||||
|  | 		s[strlen(s) - 1] = '\0'; | ||||||
|  | 	return (s); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | tty_apply_features(struct tty_term *term, int feat) | ||||||
|  | { | ||||||
|  | 	const struct tty_feature	 *tf; | ||||||
|  | 	const char			**capability; | ||||||
|  | 	u_int				  i; | ||||||
|  |  | ||||||
|  | 	if (feat == 0) | ||||||
|  | 		return; | ||||||
|  | 	log_debug("applying terminal features: %s", tty_get_features(feat)); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < nitems(tty_features); i++) { | ||||||
|  | 		if ((term->features & (1 << i)) || (~feat & (1 << i))) | ||||||
|  | 			continue; | ||||||
|  | 		tf = tty_features[i]; | ||||||
|  |  | ||||||
|  | 		log_debug("applying terminal feature: %s", tf->name); | ||||||
|  | 		if (tf->capabilities != NULL) { | ||||||
|  | 			capability = tf->capabilities; | ||||||
|  | 			while (*capability != NULL) { | ||||||
|  | 				log_debug("adding capability: %s", *capability); | ||||||
|  | 				tty_term_apply(term, *capability, 1); | ||||||
|  | 				capability++; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		term->flags |= tf->flags; | ||||||
|  | 	} | ||||||
|  | 	term->features |= feat; | ||||||
|  | } | ||||||
							
								
								
									
										62
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								tty-keys.c
									
									
									
									
									
								
							| @@ -1020,7 +1020,6 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | |||||||
| 	struct client	*c = tty->client; | 	struct client	*c = tty->client; | ||||||
| 	u_int		 i, n = 0; | 	u_int		 i, n = 0; | ||||||
| 	char		 tmp[64], *endptr, p[32] = { 0 }, *cp, *next; | 	char		 tmp[64], *endptr, p[32] = { 0 }, *cp, *next; | ||||||
| 	int		 flags = 0; |  | ||||||
|  |  | ||||||
| 	*size = 0; | 	*size = 0; | ||||||
| 	if (tty->flags & TTY_HAVEDA) | 	if (tty->flags & TTY_HAVEDA) | ||||||
| @@ -1060,24 +1059,42 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | |||||||
| 		n++; | 		n++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Set terminal flags. */ | 	/* Add terminal features. */ | ||||||
| 	switch (p[0]) { | 	switch (p[0]) { | ||||||
| 	case 41: /* VT420 */ | 	case 41: /* VT420 */ | ||||||
| 		flags |= (TERM_DECFRA|TERM_DECSLRM); | 		tty_add_features(&c->term_features, | ||||||
|  | 		    "margins," | ||||||
|  | 		    "rectfill", | ||||||
|  | 		    ","); | ||||||
| 		break; | 		break; | ||||||
| 	case 'M': /* mintty */ | 	case 'M': /* mintty */ | ||||||
| 		flags |= (TERM_256COLOURS|TERM_RGBCOLOURS); | 		tty_add_features(&c->term_features, | ||||||
|  | 		    "256," | ||||||
|  | 		    "RGB," | ||||||
|  | 		    "title", | ||||||
|  | 		    ","); | ||||||
| 		break; | 		break; | ||||||
| 	case 'T': /* tmux - new versons reply to DSR which will set RGB */ | 	case 'T': /* tmux */ | ||||||
| 		flags |= (TERM_UTF8|TERM_256COLOURS); | 		tty_add_features(&c->term_features, | ||||||
|  | 		    "256," | ||||||
|  | 		    "RGB," | ||||||
|  | 		    "ccolour," | ||||||
|  | 		    "cstyle," | ||||||
|  | 		    "overline," | ||||||
|  | 		    "title," | ||||||
|  | 		    "usstyle", | ||||||
|  | 		    ","); | ||||||
| 		break; | 		break; | ||||||
| 	case 'U': /* rxvt-unicode */ | 	case 'U': /* rxvt-unicode */ | ||||||
| 		flags |= (TERM_UTF8); | 		tty_add_features(&c->term_features, | ||||||
|  | 		    "256," | ||||||
|  | 		    "title", | ||||||
|  | 		    ","); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf); | 	log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf); | ||||||
|  |  | ||||||
| 	tty_set_flags(tty, flags); | 	tty_update_features(tty); | ||||||
| 	tty->flags |= TTY_HAVEDA; | 	tty->flags |= TTY_HAVEDA; | ||||||
|  |  | ||||||
| 	return (0); | 	return (0); | ||||||
| @@ -1094,7 +1111,6 @@ tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len, | |||||||
| 	struct client	*c = tty->client; | 	struct client	*c = tty->client; | ||||||
| 	u_int		 i; | 	u_int		 i; | ||||||
| 	char		 tmp[64]; | 	char		 tmp[64]; | ||||||
| 	int		 flags = 0; |  | ||||||
|  |  | ||||||
| 	*size = 0; | 	*size = 0; | ||||||
| 	if (tty->flags & TTY_HAVEDSR) | 	if (tty->flags & TTY_HAVEDSR) | ||||||
| @@ -1125,15 +1141,31 @@ tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len, | |||||||
| 	tmp[i] = '\0'; | 	tmp[i] = '\0'; | ||||||
| 	*size = 3 + i; | 	*size = 3 + i; | ||||||
|  |  | ||||||
| 	/* Set terminal flags. */ | 	/* Add terminal features. */ | ||||||
| 	if (strncmp(tmp, "ITERM2 ", 7) == 0) { | 	if (strncmp(tmp, "ITERM2 ", 7) == 0) { | ||||||
| 		flags |= (TERM_UTF8|TERM_DECSLRM|TERM_SYNC|TERM_256COLOURS| | 		tty_add_features(&c->term_features, | ||||||
| 		    TERM_RGBCOLOURS); | 		    "256," | ||||||
| 	} else if (strncmp(tmp, "TMUX ", 5) == 0) | 		    "RGB," | ||||||
| 		flags |= (TERM_UTF8|TERM_256COLOURS|TERM_RGBCOLOURS); | 		    "clipboard," | ||||||
|  | 		    "cstyle," | ||||||
|  | 		    "margins," | ||||||
|  | 		    "sync," | ||||||
|  | 		    "title,", | ||||||
|  | 		    ","); | ||||||
|  | 	} else if (strncmp(tmp, "TMUX ", 5) == 0) { | ||||||
|  | 		tty_add_features(&c->term_features, | ||||||
|  | 		    "256," | ||||||
|  | 		    "RGB," | ||||||
|  | 		    "ccolour," | ||||||
|  | 		    "cstyle," | ||||||
|  | 		    "overline," | ||||||
|  | 		    "title," | ||||||
|  | 		    "usstyle", | ||||||
|  | 		    ","); | ||||||
|  | 	} | ||||||
| 	log_debug("%s: received DSR %.*s", c->name, (int)*size, buf); | 	log_debug("%s: received DSR %.*s", c->name, (int)*size, buf); | ||||||
|  |  | ||||||
| 	tty_set_flags(tty, flags); | 	tty_update_features(tty); | ||||||
| 	tty->flags |= TTY_HAVEDSR; | 	tty->flags |= TTY_HAVEDSR; | ||||||
|  |  | ||||||
| 	return (0); | 	return (0); | ||||||
|   | |||||||
							
								
								
									
										100
									
								
								tty-term.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								tty-term.c
									
									
									
									
									
								
							| @@ -30,7 +30,6 @@ | |||||||
|  |  | ||||||
| #include "tmux.h" | #include "tmux.h" | ||||||
|  |  | ||||||
| static void	 tty_term_override(struct tty_term *, const char *); |  | ||||||
| static char	*tty_term_strip(const char *); | static char	*tty_term_strip(const char *); | ||||||
|  |  | ||||||
| struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms); | struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms); | ||||||
| @@ -263,7 +262,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { | |||||||
| 	[TTYC_SMUL] = { TTYCODE_STRING, "smul" }, | 	[TTYC_SMUL] = { TTYCODE_STRING, "smul" }, | ||||||
| 	[TTYC_SMXX] =  { TTYCODE_STRING, "smxx" }, | 	[TTYC_SMXX] =  { TTYCODE_STRING, "smxx" }, | ||||||
| 	[TTYC_SS] = { TTYCODE_STRING, "Ss" }, | 	[TTYC_SS] = { TTYCODE_STRING, "Ss" }, | ||||||
| 	[TTYC_SYNC] = { TTYCODE_FLAG, "Sync" }, | 	[TTYC_SYNC] = { TTYCODE_STRING, "Sync" }, | ||||||
| 	[TTYC_TC] = { TTYCODE_FLAG, "Tc" }, | 	[TTYC_TC] = { TTYCODE_FLAG, "Tc" }, | ||||||
| 	[TTYC_TSL] = { TTYCODE_STRING, "tsl" }, | 	[TTYC_TSL] = { TTYCODE_STRING, "tsl" }, | ||||||
| 	[TTYC_U8] = { TTYCODE_NUMBER, "U8" }, | 	[TTYC_U8] = { TTYCODE_NUMBER, "U8" }, | ||||||
| @@ -338,22 +337,18 @@ tty_term_override_next(const char *s, size_t *offset) | |||||||
| 	return (value); | 	return (value); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | void | ||||||
| tty_term_override(struct tty_term *term, const char *override) | tty_term_apply(struct tty_term *term, const char *capabilities, int quiet) | ||||||
| { | { | ||||||
| 	const struct tty_term_code_entry	*ent; | 	const struct tty_term_code_entry	*ent; | ||||||
| 	struct tty_code				*code; | 	struct tty_code				*code; | ||||||
| 	size_t                                   offset = 0; | 	size_t                                   offset = 0; | ||||||
| 	char					*cp, *value, *s; | 	char					*cp, *value, *s; | ||||||
| 	const char				*errstr; | 	const char				*errstr, *name = term->name; | ||||||
| 	u_int					 i; | 	u_int					 i; | ||||||
| 	int					 n, remove; | 	int					 n, remove; | ||||||
|  |  | ||||||
| 	s = tty_term_override_next(override, &offset); | 	while ((s = tty_term_override_next(capabilities, &offset)) != NULL) { | ||||||
| 	if (s == NULL || fnmatch(s, term->name, 0) != 0) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	while ((s = tty_term_override_next(override, &offset)) != NULL) { |  | ||||||
| 		if (*s == '\0') | 		if (*s == '\0') | ||||||
| 			continue; | 			continue; | ||||||
| 		value = NULL; | 		value = NULL; | ||||||
| @@ -372,12 +367,14 @@ tty_term_override(struct tty_term *term, const char *override) | |||||||
| 		} else | 		} else | ||||||
| 			value = xstrdup(""); | 			value = xstrdup(""); | ||||||
|  |  | ||||||
|  | 		if (!quiet) { | ||||||
| 			if (remove) | 			if (remove) | ||||||
| 			log_debug("%s override: %s@", term->name, s); | 				log_debug("%s override: %s@", name, s); | ||||||
| 			else if (*value == '\0') | 			else if (*value == '\0') | ||||||
| 			log_debug("%s override: %s", term->name, s); | 				log_debug("%s override: %s", name, s); | ||||||
| 			else | 			else | ||||||
| 			log_debug("%s override: %s=%s", term->name, s, value); | 				log_debug("%s override: %s=%s", name, s, value); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		for (i = 0; i < tty_term_ncodes(); i++) { | 		for (i = 0; i < tty_term_ncodes(); i++) { | ||||||
| 			ent = &tty_term_codes[i]; | 			ent = &tty_term_codes[i]; | ||||||
| @@ -417,7 +414,7 @@ tty_term_override(struct tty_term *term, const char *override) | |||||||
| } | } | ||||||
|  |  | ||||||
| struct tty_term * | struct tty_term * | ||||||
| tty_term_find(char *name, int fd, char **cause) | tty_term_create(struct tty *tty, char *name, int *feat, int fd, char **cause) | ||||||
| { | { | ||||||
| 	struct tty_term				*term; | 	struct tty_term				*term; | ||||||
| 	const struct tty_term_code_entry	*ent; | 	const struct tty_term_code_entry	*ent; | ||||||
| @@ -428,19 +425,14 @@ tty_term_find(char *name, int fd, char **cause) | |||||||
| 	u_int					 i; | 	u_int					 i; | ||||||
| 	int		 			 n, error; | 	int		 			 n, error; | ||||||
| 	const char				*s, *acs; | 	const char				*s, *acs; | ||||||
|  | 	size_t					 offset; | ||||||
|  | 	char					*first; | ||||||
|  |  | ||||||
| 	LIST_FOREACH(term, &tty_terms, entry) { | 	log_debug("adding term %s", name); | ||||||
| 		if (strcmp(term->name, name) == 0) { |  | ||||||
| 			term->references++; |  | ||||||
| 			return (term); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	log_debug("new term: %s", name); |  | ||||||
|  |  | ||||||
| 	term = xmalloc(sizeof *term); | 	term = xcalloc(1, sizeof *term); | ||||||
|  | 	term->tty = tty; | ||||||
| 	term->name = xstrdup(name); | 	term->name = xstrdup(name); | ||||||
| 	term->references = 1; |  | ||||||
| 	term->flags = 0; |  | ||||||
| 	term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes); | 	term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes); | ||||||
| 	LIST_INSERT_HEAD(&tty_terms, term, entry); | 	LIST_INSERT_HEAD(&tty_terms, term, entry); | ||||||
|  |  | ||||||
| @@ -498,12 +490,31 @@ tty_term_find(char *name, int fd, char **cause) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* Apply terminal features. */ | ||||||
|  | 	o = options_get_only(global_options, "terminal-features"); | ||||||
|  | 	a = options_array_first(o); | ||||||
|  | 	while (a != NULL) { | ||||||
|  | 		ov = options_array_item_value(a); | ||||||
|  | 		s = ov->string; | ||||||
|  |  | ||||||
|  | 		offset = 0; | ||||||
|  | 		first = tty_term_override_next(s, &offset); | ||||||
|  | 		if (first != NULL && fnmatch(first, term->name, 0) == 0) | ||||||
|  | 			tty_add_features(feat, s + offset, ":"); | ||||||
|  | 		a = options_array_next(a); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Apply terminal overrides. */ | 	/* Apply terminal overrides. */ | ||||||
| 	o = options_get_only(global_options, "terminal-overrides"); | 	o = options_get_only(global_options, "terminal-overrides"); | ||||||
| 	a = options_array_first(o); | 	a = options_array_first(o); | ||||||
| 	while (a != NULL) { | 	while (a != NULL) { | ||||||
| 		ov = options_array_item_value(a); | 		ov = options_array_item_value(a); | ||||||
| 		tty_term_override(term, ov->string); | 		s = ov->string; | ||||||
|  |  | ||||||
|  | 		offset = 0; | ||||||
|  | 		first = tty_term_override_next(s, &offset); | ||||||
|  | 		if (first != NULL && fnmatch(first, term->name, 0) == 0) | ||||||
|  | 			tty_term_apply(term, s + offset, 0); | ||||||
| 		a = options_array_next(a); | 		a = options_array_next(a); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -529,19 +540,18 @@ tty_term_find(char *name, int fd, char **cause) | |||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Set flag if terminal has 256 colours. */ | 	/* Add RGB feature if terminal has RGB colours. */ | ||||||
| 	if (tty_term_number(term, TTYC_COLORS) >= 256) | 	if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) && | ||||||
| 		term->flags |= TERM_256COLOURS; | 	    (!tty_term_has(term, TTYC_SETRGBF) || | ||||||
|  | 	    !tty_term_has(term, TTYC_SETRGBB))) | ||||||
|  | 		tty_add_features(feat, "RGB", ":,"); | ||||||
|  |  | ||||||
| 	/* Set flag if terminal has RGB colours. */ | 	/* Add feature if terminal has XT. */ | ||||||
| 	if ((tty_term_flag(term, TTYC_TC) || tty_term_has(term, TTYC_RGB)) || | 	if (tty_term_flag(term, TTYC_XT)) | ||||||
| 	    (tty_term_has(term, TTYC_SETRGBF) && | 		tty_add_features(feat, "title", ":,"); | ||||||
| 	    tty_term_has(term, TTYC_SETRGBB))) |  | ||||||
| 		term->flags |= TERM_RGBCOLOURS; |  | ||||||
|  |  | ||||||
| 	/* Set flag if terminal has synchronized updates. */ | 	/* Apply the features. */ | ||||||
| 	if (tty_term_flag(term, TTYC_SYNC)) | 	tty_apply_features(term, *feat); | ||||||
| 		term->flags |= TERM_SYNC; |  | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1 | 	 * Terminals without xenl (eat newline glitch) wrap at at $COLUMNS - 1 | ||||||
| @@ -565,18 +575,6 @@ tty_term_find(char *name, int fd, char **cause) | |||||||
| 	for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2) | 	for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2) | ||||||
| 		term->acs[(u_char) acs[0]][0] = acs[1]; | 		term->acs[(u_char) acs[0]][0] = acs[1]; | ||||||
|  |  | ||||||
| 	/* On terminals with xterm titles (XT), fill in tsl and fsl. */ |  | ||||||
| 	if (tty_term_flag(term, TTYC_XT) && |  | ||||||
| 	    !tty_term_has(term, TTYC_TSL) && |  | ||||||
| 	    !tty_term_has(term, TTYC_FSL)) { |  | ||||||
| 		code = &term->codes[TTYC_TSL]; |  | ||||||
| 		code->value.string = xstrdup("\033]0;"); |  | ||||||
| 		code->type = TTYCODE_STRING; |  | ||||||
| 		code = &term->codes[TTYC_FSL]; |  | ||||||
| 		code->value.string = xstrdup("\007"); |  | ||||||
| 		code->type = TTYCODE_STRING; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Log the capabilities. */ | 	/* Log the capabilities. */ | ||||||
| 	for (i = 0; i < tty_term_ncodes(); i++) | 	for (i = 0; i < tty_term_ncodes(); i++) | ||||||
| 		log_debug("%s%s", name, tty_term_describe(term, i)); | 		log_debug("%s%s", name, tty_term_describe(term, i)); | ||||||
| @@ -593,10 +591,7 @@ tty_term_free(struct tty_term *term) | |||||||
| { | { | ||||||
| 	u_int	i; | 	u_int	i; | ||||||
|  |  | ||||||
| 	if (--term->references != 0) | 	log_debug("removing term %s", term->name); | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	LIST_REMOVE(term, entry); |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < tty_term_ncodes(); i++) { | 	for (i = 0; i < tty_term_ncodes(); i++) { | ||||||
| 		if (term->codes[i].type == TTYCODE_STRING) | 		if (term->codes[i].type == TTYCODE_STRING) | ||||||
| @@ -604,6 +599,7 @@ tty_term_free(struct tty_term *term) | |||||||
| 	} | 	} | ||||||
| 	free(term->codes); | 	free(term->codes); | ||||||
|  |  | ||||||
|  | 	LIST_REMOVE(term, entry); | ||||||
| 	free(term->name); | 	free(term->name); | ||||||
| 	free(term); | 	free(term); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										119
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								tty.c
									
									
									
									
									
								
							| @@ -74,7 +74,7 @@ static void	tty_default_attributes(struct tty *, struct window_pane *, | |||||||
| 		    u_int); | 		    u_int); | ||||||
|  |  | ||||||
| #define tty_use_margin(tty) \ | #define tty_use_margin(tty) \ | ||||||
| 	(tty_get_flags(tty) & TERM_DECSLRM) | 	(tty->term->flags & TERM_DECSLRM) | ||||||
|  |  | ||||||
| #define tty_pane_full_width(tty, ctx) \ | #define tty_pane_full_width(tty, ctx) \ | ||||||
| 	((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) | 	((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) | ||||||
| @@ -96,27 +96,19 @@ tty_create_log(void) | |||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| tty_init(struct tty *tty, struct client *c, int fd, char *term) | tty_init(struct tty *tty, struct client *c, int fd) | ||||||
| { | { | ||||||
| 	if (!isatty(fd)) | 	if (!isatty(fd)) | ||||||
| 		return (-1); | 		return (-1); | ||||||
|  |  | ||||||
| 	memset(tty, 0, sizeof *tty); | 	memset(tty, 0, sizeof *tty); | ||||||
|  |  | ||||||
| 	if (term == NULL || *term == '\0') |  | ||||||
| 		tty->term_name = xstrdup("unknown"); |  | ||||||
| 	else |  | ||||||
| 		tty->term_name = xstrdup(term); |  | ||||||
|  |  | ||||||
| 	tty->fd = fd; | 	tty->fd = fd; | ||||||
| 	tty->client = c; | 	tty->client = c; | ||||||
|  |  | ||||||
| 	tty->cstyle = 0; | 	tty->cstyle = 0; | ||||||
| 	tty->ccolour = xstrdup(""); | 	tty->ccolour = xstrdup(""); | ||||||
|  |  | ||||||
| 	tty->flags = 0; |  | ||||||
| 	tty->term_flags = 0; |  | ||||||
|  |  | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -256,7 +248,10 @@ tty_write_callback(__unused int fd, __unused short events, void *data) | |||||||
| int | int | ||||||
| tty_open(struct tty *tty, char **cause) | tty_open(struct tty *tty, char **cause) | ||||||
| { | { | ||||||
| 	tty->term = tty_term_find(tty->term_name, tty->fd, cause); | 	struct client	*c = tty->client; | ||||||
|  |  | ||||||
|  | 	tty->term = tty_term_create(tty, c->term_name, &c->term_features, | ||||||
|  | 	    tty->fd, cause); | ||||||
| 	if (tty->term == NULL) { | 	if (tty->term == NULL) { | ||||||
| 		tty_close(tty); | 		tty_close(tty); | ||||||
| 		return (-1); | 		return (-1); | ||||||
| @@ -466,28 +461,20 @@ void | |||||||
| tty_free(struct tty *tty) | tty_free(struct tty *tty) | ||||||
| { | { | ||||||
| 	tty_close(tty); | 	tty_close(tty); | ||||||
|  |  | ||||||
| 	free(tty->ccolour); | 	free(tty->ccolour); | ||||||
| 	free(tty->term_name); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| tty_set_flags(struct tty *tty, int flags) | tty_update_features(struct tty *tty) | ||||||
| { | { | ||||||
| 	tty->term_flags |= flags; | 	struct client	*c = tty->client; | ||||||
|  |  | ||||||
|  | 	tty_apply_features(tty->term, c->term_features); | ||||||
|  |  | ||||||
| 	if (tty_use_margin(tty)) | 	if (tty_use_margin(tty)) | ||||||
| 		tty_puts(tty, "\033[?69h"); /* DECLRMM */ | 		tty_puts(tty, "\033[?69h"); /* DECLRMM */ | ||||||
| } | } | ||||||
|  |  | ||||||
| int |  | ||||||
| tty_get_flags(struct tty *tty) |  | ||||||
| { |  | ||||||
| 	if (tty->term != NULL) |  | ||||||
| 		return (tty->term->flags|tty->term_flags); |  | ||||||
| 	return (tty->term_flags); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void | void | ||||||
| tty_raw(struct tty *tty, const char *s) | tty_raw(struct tty *tty, const char *s) | ||||||
| { | { | ||||||
| @@ -585,7 +572,7 @@ tty_putc(struct tty *tty, u_char ch) | |||||||
| { | { | ||||||
| 	const char	*acs; | 	const char	*acs; | ||||||
|  |  | ||||||
| 	if ((tty_get_flags(tty) & TERM_NOXENL) && | 	if ((tty->term->flags & TERM_NOXENL) && | ||||||
| 	    ch >= 0x20 && ch != 0x7f && | 	    ch >= 0x20 && ch != 0x7f && | ||||||
| 	    tty->cy == tty->sy - 1 && | 	    tty->cy == tty->sy - 1 && | ||||||
| 	    tty->cx + 1 >= tty->sx) | 	    tty->cx + 1 >= tty->sx) | ||||||
| @@ -611,7 +598,7 @@ tty_putc(struct tty *tty, u_char ch) | |||||||
| 			 * where we think it should be after a line wrap - this | 			 * where we think it should be after a line wrap - this | ||||||
| 			 * means it works on sensible terminals as well. | 			 * means it works on sensible terminals as well. | ||||||
| 			 */ | 			 */ | ||||||
| 			if (tty_get_flags(tty) & TERM_NOXENL) | 			if (tty->term->flags & TERM_NOXENL) | ||||||
| 				tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx); | 				tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx); | ||||||
| 		} else | 		} else | ||||||
| 			tty->cx++; | 			tty->cx++; | ||||||
| @@ -621,7 +608,7 @@ tty_putc(struct tty *tty, u_char ch) | |||||||
| void | void | ||||||
| tty_putn(struct tty *tty, const void *buf, size_t len, u_int width) | tty_putn(struct tty *tty, const void *buf, size_t len, u_int width) | ||||||
| { | { | ||||||
| 	if ((tty_get_flags(tty) & TERM_NOXENL) && | 	if ((tty->term->flags & TERM_NOXENL) && | ||||||
| 	    tty->cy == tty->sy - 1 && | 	    tty->cy == tty->sy - 1 && | ||||||
| 	    tty->cx + len >= tty->sx) | 	    tty->cx + len >= tty->sx) | ||||||
| 		len = tty->sx - tty->cx - 1; | 		len = tty->sx - tty->cx - 1; | ||||||
| @@ -1179,7 +1166,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny, | |||||||
| 		 * background colour isn't default (because it doesn't work | 		 * background colour isn't default (because it doesn't work | ||||||
| 		 * after SGR 0). | 		 * after SGR 0). | ||||||
| 		 */ | 		 */ | ||||||
| 		if ((tty_get_flags(tty) & TERM_DECFRA) && !COLOUR_DEFAULT(bg)) { | 		if ((tty->term->flags & TERM_DECFRA) && !COLOUR_DEFAULT(bg)) { | ||||||
| 			xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x", | 			xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x", | ||||||
| 			    py + 1, px + 1, py + ny, px + nx); | 			    py + 1, px + 1, py + ny, px + nx); | ||||||
| 			tty_puts(tty, tmp); | 			tty_puts(tty, tmp); | ||||||
| @@ -1258,7 +1245,7 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc) | |||||||
| 		return (gc); | 		return (gc); | ||||||
|  |  | ||||||
| 	/* UTF-8 terminal and a UTF-8 character - fine. */ | 	/* UTF-8 terminal and a UTF-8 character - fine. */ | ||||||
| 	if (tty_get_flags(tty) & TERM_UTF8) | 	if (tty->client->flags & CLIENT_UTF8) | ||||||
| 		return (gc); | 		return (gc); | ||||||
|  |  | ||||||
| 	/* Replace by the right number of underscores. */ | 	/* Replace by the right number of underscores. */ | ||||||
| @@ -1440,8 +1427,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, | |||||||
| void | void | ||||||
| tty_sync_start(struct tty *tty) | tty_sync_start(struct tty *tty) | ||||||
| { | { | ||||||
| 	if ((~tty->flags & TTY_SYNCING) && (tty_get_flags(tty) & TERM_SYNC)) { | 	if ((~tty->flags & TTY_SYNCING) && tty_term_has(tty->term, TTYC_SYNC)) { | ||||||
| 		tty_puts(tty, "\033P=1s\033\\"); | 		tty_putcode1(tty, TTYC_SYNC, 1); | ||||||
| 		tty->flags |= TTY_SYNCING; | 		tty->flags |= TTY_SYNCING; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -1449,8 +1436,8 @@ tty_sync_start(struct tty *tty) | |||||||
| void | void | ||||||
| tty_sync_end(struct tty *tty) | tty_sync_end(struct tty *tty) | ||||||
| { | { | ||||||
| 	if (tty_get_flags(tty) & TERM_SYNC) { | 	if ((tty->flags & TTY_SYNCING) && tty_term_has(tty->term, TTYC_SYNC)) { | ||||||
| 		tty_puts(tty, "\033P=2s\033\\"); | 		tty_putcode1(tty, TTYC_SYNC, 2); | ||||||
| 		tty->flags &= ~TTY_SYNCING; | 		tty->flags &= ~TTY_SYNCING; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -1916,7 +1903,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) | |||||||
| 	    ctx->xoff + ctx->ocx + ctx->num > ctx->ox + ctx->sx)) { | 	    ctx->xoff + ctx->ocx + ctx->num > ctx->ox + ctx->sx)) { | ||||||
| 		if (!ctx->wrapped || | 		if (!ctx->wrapped || | ||||||
| 		    !tty_pane_full_width(tty, ctx) || | 		    !tty_pane_full_width(tty, ctx) || | ||||||
| 		    (tty_get_flags(tty) & TERM_NOXENL) || | 		    (tty->term->flags & TERM_NOXENL) || | ||||||
| 		    ctx->xoff + ctx->ocx != 0 || | 		    ctx->xoff + ctx->ocx != 0 || | ||||||
| 		    ctx->yoff + ctx->ocy != tty->cy + 1 || | 		    ctx->yoff + ctx->ocy != tty->cy + 1 || | ||||||
| 		    tty->cx < tty->sx || | 		    tty->cx < tty->sx || | ||||||
| @@ -1977,7 +1964,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp) | |||||||
| 	const struct grid_cell	*gcp; | 	const struct grid_cell	*gcp; | ||||||
|  |  | ||||||
| 	/* Skip last character if terminal is stupid. */ | 	/* Skip last character if terminal is stupid. */ | ||||||
| 	if ((tty_get_flags(tty) & TERM_NOXENL) && | 	if ((tty->term->flags & TERM_NOXENL) && | ||||||
| 	    tty->cy == tty->sy - 1 && | 	    tty->cy == tty->sy - 1 && | ||||||
| 	    tty->cx == tty->sx - 1) | 	    tty->cx == tty->sx - 1) | ||||||
| 		return; | 		return; | ||||||
| @@ -2140,7 +2127,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx, | |||||||
| { | { | ||||||
| 	if (!ctx->wrapped || | 	if (!ctx->wrapped || | ||||||
| 	    !tty_pane_full_width(tty, ctx) || | 	    !tty_pane_full_width(tty, ctx) || | ||||||
| 	    (tty_get_flags(tty) & TERM_NOXENL) || | 	    (tty->term->flags & TERM_NOXENL) || | ||||||
| 	    ctx->xoff + cx != 0 || | 	    ctx->xoff + cx != 0 || | ||||||
| 	    ctx->yoff + cy != tty->cy + 1 || | 	    ctx->yoff + cy != tty->cy + 1 || | ||||||
| 	    tty->cx < tty->sx || | 	    tty->cx < tty->sx || | ||||||
| @@ -2480,14 +2467,14 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) | |||||||
| 	/* Is this a 24-bit colour? */ | 	/* Is this a 24-bit colour? */ | ||||||
| 	if (gc->fg & COLOUR_FLAG_RGB) { | 	if (gc->fg & COLOUR_FLAG_RGB) { | ||||||
| 		/* Not a 24-bit terminal? Translate to 256-colour palette. */ | 		/* Not a 24-bit terminal? Translate to 256-colour palette. */ | ||||||
| 		if (tty_get_flags(tty) & TERM_RGBCOLOURS) | 		if (tty->term->flags & TERM_RGBCOLOURS) | ||||||
| 			return; | 			return; | ||||||
| 		colour_split_rgb(gc->fg, &r, &g, &b); | 		colour_split_rgb(gc->fg, &r, &g, &b); | ||||||
| 		gc->fg = colour_find_rgb(r, g, b); | 		gc->fg = colour_find_rgb(r, g, b); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* How many colours does this terminal have? */ | 	/* How many colours does this terminal have? */ | ||||||
| 	if (tty_get_flags(tty) & TERM_256COLOURS) | 	if (tty->term->flags & TERM_256COLOURS) | ||||||
| 		colours = 256; | 		colours = 256; | ||||||
| 	else | 	else | ||||||
| 		colours = tty_term_number(tty->term, TTYC_COLORS); | 		colours = tty_term_number(tty->term, TTYC_COLORS); | ||||||
| @@ -2529,14 +2516,14 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) | |||||||
| 	/* Is this a 24-bit colour? */ | 	/* Is this a 24-bit colour? */ | ||||||
| 	if (gc->bg & COLOUR_FLAG_RGB) { | 	if (gc->bg & COLOUR_FLAG_RGB) { | ||||||
| 		/* Not a 24-bit terminal? Translate to 256-colour palette. */ | 		/* Not a 24-bit terminal? Translate to 256-colour palette. */ | ||||||
| 		if (tty_get_flags(tty) & TERM_RGBCOLOURS) | 		if (tty->term->flags & TERM_RGBCOLOURS) | ||||||
| 			return; | 			return; | ||||||
| 		colour_split_rgb(gc->bg, &r, &g, &b); | 		colour_split_rgb(gc->bg, &r, &g, &b); | ||||||
| 		gc->bg = colour_find_rgb(r, g, b); | 		gc->bg = colour_find_rgb(r, g, b); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* How many colours does this terminal have? */ | 	/* How many colours does this terminal have? */ | ||||||
| 	if (tty_get_flags(tty) & TERM_256COLOURS) | 	if (tty->term->flags & TERM_256COLOURS) | ||||||
| 		colours = 256; | 		colours = 256; | ||||||
| 	else | 	else | ||||||
| 		colours = tty_term_number(tty->term, TTYC_COLORS); | 		colours = tty_term_number(tty->term, TTYC_COLORS); | ||||||
| @@ -2597,7 +2584,7 @@ tty_colours_fg(struct tty *tty, const struct grid_cell *gc) | |||||||
|  |  | ||||||
| 	/* Is this an aixterm bright colour? */ | 	/* Is this an aixterm bright colour? */ | ||||||
| 	if (gc->fg >= 90 && gc->fg <= 97) { | 	if (gc->fg >= 90 && gc->fg <= 97) { | ||||||
| 		if (tty_get_flags(tty) & TERM_256COLOURS) { | 		if (tty->term->flags & TERM_256COLOURS) { | ||||||
| 			xsnprintf(s, sizeof s, "\033[%dm", gc->fg); | 			xsnprintf(s, sizeof s, "\033[%dm", gc->fg); | ||||||
| 			tty_puts(tty, s); | 			tty_puts(tty, s); | ||||||
| 		} else | 		} else | ||||||
| @@ -2629,7 +2616,7 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc) | |||||||
|  |  | ||||||
| 	/* Is this an aixterm bright colour? */ | 	/* Is this an aixterm bright colour? */ | ||||||
| 	if (gc->bg >= 90 && gc->bg <= 97) { | 	if (gc->bg >= 90 && gc->bg <= 97) { | ||||||
| 		if (tty_get_flags(tty) & TERM_256COLOURS) { | 		if (tty->term->flags & TERM_256COLOURS) { | ||||||
| 			xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10); | 			xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10); | ||||||
| 			tty_puts(tty, s); | 			tty_puts(tty, s); | ||||||
| 		} else | 		} else | ||||||
| @@ -2674,67 +2661,25 @@ static int | |||||||
| tty_try_colour(struct tty *tty, int colour, const char *type) | tty_try_colour(struct tty *tty, int colour, const char *type) | ||||||
| { | { | ||||||
| 	u_char	r, g, b; | 	u_char	r, g, b; | ||||||
| 	char	s[32]; |  | ||||||
|  |  | ||||||
| 	if (colour & COLOUR_FLAG_256) { | 	if (colour & COLOUR_FLAG_256) { | ||||||
| 		/* | 		if (*type == '3' && tty_term_has(tty->term, TTYC_SETAF)) | ||||||
| 		 * If the user has specified -2 to the client (meaning |  | ||||||
| 		 * TERM_256COLOURS is set), setaf and setab may not work (or |  | ||||||
| 		 * they may not want to use them), so send the usual sequence. |  | ||||||
| 		 * |  | ||||||
| 		 * Also if RGB is set, setaf and setab do not support the 256 |  | ||||||
| 		 * colour palette so use the sequences directly there too. |  | ||||||
| 		 */ |  | ||||||
| 		if ((tty_get_flags(tty) & TERM_256COLOURS) || |  | ||||||
| 		    tty_term_has(tty->term, TTYC_RGB)) |  | ||||||
| 			goto fallback_256; |  | ||||||
|  |  | ||||||
| 		/* |  | ||||||
| 		 * If the terminfo entry has 256 colours and setaf and setab |  | ||||||
| 		 * exist, assume that they work correctly. |  | ||||||
| 		 */ |  | ||||||
| 		if (tty_get_flags(tty) & TERM_256COLOURS) { |  | ||||||
| 			if (*type == '3') { |  | ||||||
| 				if (!tty_term_has(tty->term, TTYC_SETAF)) |  | ||||||
| 					goto fallback_256; |  | ||||||
| 			tty_putcode1(tty, TTYC_SETAF, colour & 0xff); | 			tty_putcode1(tty, TTYC_SETAF, colour & 0xff); | ||||||
| 			} else { | 		else if (tty_term_has(tty->term, TTYC_SETAB)) | ||||||
| 				if (!tty_term_has(tty->term, TTYC_SETAB)) |  | ||||||
| 					goto fallback_256; |  | ||||||
| 			tty_putcode1(tty, TTYC_SETAB, colour & 0xff); | 			tty_putcode1(tty, TTYC_SETAB, colour & 0xff); | ||||||
| 			} |  | ||||||
| 		return (0); | 		return (0); | ||||||
| 	} | 	} | ||||||
| 		goto fallback_256; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (colour & COLOUR_FLAG_RGB) { | 	if (colour & COLOUR_FLAG_RGB) { | ||||||
| 		colour_split_rgb(colour & 0xffffff, &r, &g, &b); | 		colour_split_rgb(colour & 0xffffff, &r, &g, &b); | ||||||
| 		if (*type == '3') { | 		if (*type == '3' && tty_term_has(tty->term, TTYC_SETRGBF)) | ||||||
| 			if (!tty_term_has(tty->term, TTYC_SETRGBF)) |  | ||||||
| 				goto fallback_rgb; |  | ||||||
| 			tty_putcode3(tty, TTYC_SETRGBF, r, g, b); | 			tty_putcode3(tty, TTYC_SETRGBF, r, g, b); | ||||||
| 		} else { | 		else if (tty_term_has(tty->term, TTYC_SETRGBB)) | ||||||
| 			if (!tty_term_has(tty->term, TTYC_SETRGBB)) |  | ||||||
| 				goto fallback_rgb; |  | ||||||
| 			tty_putcode3(tty, TTYC_SETRGBB, r, g, b); | 			tty_putcode3(tty, TTYC_SETRGBB, r, g, b); | ||||||
| 		} |  | ||||||
| 		return (0); | 		return (0); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return (-1); | 	return (-1); | ||||||
|  |  | ||||||
| fallback_256: |  | ||||||
| 	xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff); |  | ||||||
| 	log_debug("%s: 256 colour fallback: %s", tty->client->name, s); |  | ||||||
| 	tty_puts(tty, s); |  | ||||||
| 	return (0); |  | ||||||
|  |  | ||||||
| fallback_rgb: |  | ||||||
| 	xsnprintf(s, sizeof s, "\033[%s;2;%d;%d;%dm", type, r, g, b); |  | ||||||
| 	log_debug("%s: RGB colour fallback: %s", tty->client->name, s); |  | ||||||
| 	tty_puts(tty, s); |  | ||||||
| 	return (0); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Thomas Adam
					Thomas Adam