mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Support passing through escape sequences to the underlying terminal by
using DCS with a "tmux;" prefix. Escape characters in the sequences must be doubled. For example: $ printf '\033Ptmux;\033\033]12;red\007\033\\' Will pass \033]12;red\007 to the terminal (and change the cursor colour in xterm). From Kevin Goodsell.
This commit is contained in:
		
							
								
								
									
										73
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								input.c
									
									
									
									
									
								
							| @@ -41,6 +41,9 @@ | ||||
|  * | ||||
|  * - A state for the screen \033k...\033\\ sequence to rename a window. This is | ||||
|  *   pretty stupid but not supporting it is more trouble than it is worth. | ||||
|  * | ||||
|  * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to | ||||
|  *   be passed to the underlying teminal(s). | ||||
|  */ | ||||
|  | ||||
| /* Helper functions. */ | ||||
| @@ -50,8 +53,6 @@ void	input_reply(struct input_ctx *, const char *, ...); | ||||
|  | ||||
| /* Transition entry/exit handlers. */ | ||||
| void	input_clear(struct input_ctx *); | ||||
| void	input_enter_dcs(struct input_ctx *); | ||||
| void	input_exit_dcs(struct input_ctx *); | ||||
| void	input_enter_osc(struct input_ctx *); | ||||
| void	input_exit_osc(struct input_ctx *); | ||||
| void	input_enter_apc(struct input_ctx *); | ||||
| @@ -68,6 +69,7 @@ int	input_c0_dispatch(struct input_ctx *); | ||||
| int	input_esc_dispatch(struct input_ctx *); | ||||
| int	input_csi_dispatch(struct input_ctx *); | ||||
| void	input_csi_dispatch_sgr(struct input_ctx *); | ||||
| int	input_dcs_dispatch(struct input_ctx *); | ||||
| int	input_utf8_open(struct input_ctx *); | ||||
| int	input_utf8_add(struct input_ctx *); | ||||
| int	input_utf8_close(struct input_ctx *); | ||||
| @@ -204,6 +206,7 @@ const struct input_transition input_state_dcs_enter_table[]; | ||||
| const struct input_transition input_state_dcs_parameter_table[]; | ||||
| const struct input_transition input_state_dcs_intermediate_table[]; | ||||
| const struct input_transition input_state_dcs_handler_table[]; | ||||
| const struct input_transition input_state_dcs_escape_table[]; | ||||
| const struct input_transition input_state_dcs_ignore_table[]; | ||||
| const struct input_transition input_state_osc_string_table[]; | ||||
| const struct input_transition input_state_apc_string_table[]; | ||||
| @@ -286,10 +289,17 @@ const struct input_state input_state_dcs_intermediate = { | ||||
| /* dcs_handler state definition. */ | ||||
| const struct input_state input_state_dcs_handler = { | ||||
| 	"dcs_handler", | ||||
| 	input_enter_dcs, input_exit_dcs, | ||||
| 	NULL, NULL, | ||||
| 	input_state_dcs_handler_table | ||||
| }; | ||||
|  | ||||
| /* dcs_escape state definition. */ | ||||
| const struct input_state input_state_dcs_escape = { | ||||
| 	"dcs_escape", | ||||
| 	NULL, NULL, | ||||
| 	input_state_dcs_escape_table | ||||
| }; | ||||
|  | ||||
| /* dcs_ignore state definition. */ | ||||
| const struct input_state input_state_dcs_ignore = { | ||||
| 	"dcs_ignore", | ||||
| @@ -482,7 +492,7 @@ const struct input_transition input_state_dcs_enter_table[] = { | ||||
| 	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore }, | ||||
| 	{ 0x3b, 0x3b, input_parameter,	  &input_state_dcs_parameter }, | ||||
| 	{ 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter }, | ||||
| 	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler }, | ||||
| 	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler }, | ||||
| 	{ 0x7f, 0xff, NULL,		  NULL }, | ||||
|  | ||||
| 	{ -1, -1, NULL, NULL } | ||||
| @@ -500,7 +510,7 @@ const struct input_transition input_state_dcs_parameter_table[] = { | ||||
| 	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore }, | ||||
| 	{ 0x3b, 0x3b, input_parameter,	  NULL }, | ||||
| 	{ 0x3c, 0x3f, NULL,		  &input_state_dcs_ignore }, | ||||
| 	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler }, | ||||
| 	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler }, | ||||
| 	{ 0x7f, 0xff, NULL,		  NULL }, | ||||
|  | ||||
| 	{ -1, -1, NULL, NULL } | ||||
| @@ -515,7 +525,7 @@ const struct input_transition input_state_dcs_intermediate_table[] = { | ||||
| 	{ 0x1c, 0x1f, NULL,		  NULL }, | ||||
| 	{ 0x20, 0x2f, input_intermediate, NULL }, | ||||
| 	{ 0x30, 0x3f, NULL,		  &input_state_dcs_ignore }, | ||||
| 	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler }, | ||||
| 	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler }, | ||||
| 	{ 0x7f, 0xff, NULL,		  NULL }, | ||||
|  | ||||
| 	{ -1, -1, NULL, NULL } | ||||
| @@ -523,13 +533,22 @@ const struct input_transition input_state_dcs_intermediate_table[] = { | ||||
|  | ||||
| /* dcs_handler state table. */ | ||||
| const struct input_transition input_state_dcs_handler_table[] = { | ||||
| 	INPUT_STATE_ANYWHERE, | ||||
| 	/* No INPUT_STATE_ANYWHERE */ | ||||
|  | ||||
| 	{ 0x00, 0x17, NULL,	    NULL }, | ||||
| 	{ 0x19, 0x19, input_input,  NULL }, | ||||
| 	{ 0x1c, 0x1f, input_input,  NULL }, | ||||
| 	{ 0x20, 0x7e, input_input,  NULL }, | ||||
| 	{ 0x7f, 0xff, NULL,	    NULL }, | ||||
| 	{ 0x00, 0x1a, input_input,  NULL }, | ||||
| 	{ 0x1b, 0x1b, NULL,	    &input_state_dcs_escape }, | ||||
| 	{ 0x1c, 0xff, input_input,  NULL }, | ||||
|  | ||||
| 	{ -1, -1, NULL, NULL } | ||||
| }; | ||||
|  | ||||
| /* dcs_escape state table. */ | ||||
| const struct input_transition input_state_dcs_escape_table[] = { | ||||
| 	/* No INPUT_STATE_ANYWHERE */ | ||||
|  | ||||
| 	{ 0x00, 0x5b, input_input,	  &input_state_dcs_handler }, | ||||
| 	{ 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground }, | ||||
| 	{ 0x5d, 0xff, input_input,	  &input_state_dcs_handler }, | ||||
|  | ||||
| 	{ -1, -1, NULL, NULL } | ||||
| }; | ||||
| @@ -1391,20 +1410,26 @@ input_csi_dispatch_sgr(struct input_ctx *ictx) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* DCS string started. */ | ||||
| void | ||||
| input_enter_dcs(struct input_ctx *ictx) | ||||
| { | ||||
| 	log_debug("%s", __func__); | ||||
|  | ||||
| 	input_clear(ictx); | ||||
| } | ||||
|  | ||||
| /* DCS terminator (ST) received. */ | ||||
| void | ||||
| input_exit_dcs(unused struct input_ctx *ictx) | ||||
| int | ||||
| input_dcs_dispatch(struct input_ctx *ictx) | ||||
| { | ||||
| 	log_debug("%s", __func__); | ||||
| 	const char	prefix[] = "tmux;"; | ||||
| 	const u_int	prefix_len = (sizeof prefix) - 1; | ||||
|  | ||||
| 	if (ictx->flags & INPUT_DISCARD) | ||||
| 		return (0); | ||||
|  | ||||
| 	log_debug("%s: \"%s\"", __func__, ictx->input_buf); | ||||
|  | ||||
| 	/* Check for tmux prefix. */ | ||||
| 	if (ictx->input_len >= prefix_len && | ||||
| 	    strncmp(ictx->input_buf, prefix, prefix_len) == 0) { | ||||
| 		screen_write_rawstring(&ictx->ctx, | ||||
| 		    ictx->input_buf + prefix_len, ictx->input_len - prefix_len); | ||||
| 	} | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* OSC string started. */ | ||||
|   | ||||
| @@ -1191,3 +1191,15 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width) | ||||
| 		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) | ||||
| { | ||||
| 	struct tty_ctx		 ttyctx; | ||||
|  | ||||
| 	screen_write_initctx(ctx, &ttyctx, 0); | ||||
| 	ttyctx.ptr = str; | ||||
| 	ttyctx.num = len; | ||||
|  | ||||
| 	tty_write(tty_cmd_rawstring, &ttyctx); | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1426,6 +1426,7 @@ void	tty_cmd_insertline(struct tty *, const struct tty_ctx *); | ||||
| void	tty_cmd_linefeed(struct tty *, const struct tty_ctx *); | ||||
| void	tty_cmd_utf8character(struct tty *, const struct tty_ctx *); | ||||
| void	tty_cmd_reverseindex(struct tty *, const struct tty_ctx *); | ||||
| void	tty_cmd_rawstring(struct tty *, const struct tty_ctx *); | ||||
|  | ||||
| /* tty-term.c */ | ||||
| extern struct tty_terms tty_terms; | ||||
| @@ -1804,6 +1805,7 @@ void	 screen_write_clearstartofscreen(struct screen_write_ctx *); | ||||
| void	 screen_write_clearscreen(struct screen_write_ctx *); | ||||
| void	 screen_write_cell(struct screen_write_ctx *, | ||||
| 	     const struct grid_cell *, const struct utf8_data *); | ||||
| void	 screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); | ||||
|  | ||||
| /* screen-redraw.c */ | ||||
| void	 screen_redraw_screen(struct client *, int, int); | ||||
|   | ||||
							
								
								
									
										10
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tty.c
									
									
									
									
									
								
							| @@ -931,6 +931,16 @@ tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx) | ||||
| 	tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); | ||||
| } | ||||
|  | ||||
| void | ||||
| tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) | ||||
| { | ||||
| 	u_int	 i; | ||||
| 	u_char	*str = ctx->ptr; | ||||
|  | ||||
| 	for (i = 0; i < ctx->num; i++) | ||||
| 		tty_putc(tty, str[i]); | ||||
| } | ||||
|  | ||||
| void | ||||
| tty_cell( | ||||
|     struct tty *tty, const struct grid_cell *gc, const struct grid_utf8 *gu) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott