mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Support OSC 52 ? to read the top buffer inside tmux (when set-clipboard
is changed to on), also add refresh-client -l to ask tmux to use the same mechanism to get the clipboard from the terminal outside tmux. GitHub issue 1477.
This commit is contained in:
		| @@ -31,8 +31,8 @@ const struct cmd_entry cmd_refresh_client_entry = { | |||||||
| 	.name = "refresh-client", | 	.name = "refresh-client", | ||||||
| 	.alias = "refresh", | 	.alias = "refresh", | ||||||
|  |  | ||||||
| 	.args = { "C:St:", 0, 0 }, | 	.args = { "C:lSt:", 0, 0 }, | ||||||
| 	.usage = "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE, | 	.usage = "[-lS] [-C size] " CMD_TARGET_CLIENT_USAGE, | ||||||
|  |  | ||||||
| 	.flags = CMD_AFTERHOOK, | 	.flags = CMD_AFTERHOOK, | ||||||
| 	.exec = cmd_refresh_client_exec | 	.exec = cmd_refresh_client_exec | ||||||
| @@ -49,7 +49,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL) | 	if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL) | ||||||
| 		return (CMD_RETURN_ERROR); | 		return (CMD_RETURN_ERROR); | ||||||
|  |  | ||||||
| 	if (args_has(args, 'C')) { | 	if (args_has(args, 'l')) { | ||||||
|  | 		if (c->session != NULL) | ||||||
|  | 			tty_putcode_ptr2(&c->tty, TTYC_MS, "", "?"); | ||||||
|  | 	} else if (args_has(args, 'C')) { | ||||||
| 		if ((size = args_get(args, 'C')) == NULL) { | 		if ((size = args_get(args, 'C')) == NULL) { | ||||||
| 			cmdq_error(item, "missing size"); | 			cmdq_error(item, "missing size"); | ||||||
| 			return (CMD_RETURN_ERROR); | 			return (CMD_RETURN_ERROR); | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								input.c
									
									
									
									
									
								
							| @@ -93,6 +93,10 @@ struct input_ctx { | |||||||
| 	u_char		       *input_buf; | 	u_char		       *input_buf; | ||||||
| 	size_t			input_len; | 	size_t			input_len; | ||||||
| 	size_t			input_space; | 	size_t			input_space; | ||||||
|  | 	enum { | ||||||
|  | 		INPUT_END_ST, | ||||||
|  | 		INPUT_END_BEL | ||||||
|  | 	}			input_end; | ||||||
|  |  | ||||||
| 	struct input_param	param_list[24]; | 	struct input_param	param_list[24]; | ||||||
| 	u_int			param_list_len; | 	u_int			param_list_len; | ||||||
| @@ -126,11 +130,11 @@ static void	input_set_state(struct window_pane *, | |||||||
| 		    const struct input_transition *); | 		    const struct input_transition *); | ||||||
| static void	input_reset_cell(struct input_ctx *); | static void	input_reset_cell(struct input_ctx *); | ||||||
|  |  | ||||||
| static void	input_osc_4(struct window_pane *, const char *); | static void	input_osc_4(struct input_ctx *, const char *); | ||||||
| static void	input_osc_10(struct window_pane *, const char *); | static void	input_osc_10(struct input_ctx *, const char *); | ||||||
| static void	input_osc_11(struct window_pane *, const char *); | static void	input_osc_11(struct input_ctx *, const char *); | ||||||
| static void	input_osc_52(struct window_pane *, const char *); | static void	input_osc_52(struct input_ctx *, const char *); | ||||||
| static void	input_osc_104(struct window_pane *, const char *); | static void	input_osc_104(struct input_ctx *, const char *); | ||||||
|  |  | ||||||
| /* Transition entry/exit handlers. */ | /* Transition entry/exit handlers. */ | ||||||
| static void	input_clear(struct input_ctx *); | static void	input_clear(struct input_ctx *); | ||||||
| @@ -161,6 +165,7 @@ static void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); | |||||||
| static void	input_csi_dispatch_sgr(struct input_ctx *); | static void	input_csi_dispatch_sgr(struct input_ctx *); | ||||||
| static int	input_dcs_dispatch(struct input_ctx *); | static int	input_dcs_dispatch(struct input_ctx *); | ||||||
| static int	input_top_bit_set(struct input_ctx *); | static int	input_top_bit_set(struct input_ctx *); | ||||||
|  | static int	input_end_bel(struct input_ctx *); | ||||||
|  |  | ||||||
| /* Command table comparison function. */ | /* Command table comparison function. */ | ||||||
| static int	input_table_compare(const void *, const void *); | static int	input_table_compare(const void *, const void *); | ||||||
| @@ -487,7 +492,7 @@ static const struct input_transition input_state_esc_enter_table[] = { | |||||||
| 	{ -1, -1, NULL, NULL } | 	{ -1, -1, NULL, NULL } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* esc_interm state table. */ | /* esc_intermediate state table. */ | ||||||
| static const struct input_transition input_state_esc_intermediate_table[] = { | static const struct input_transition input_state_esc_intermediate_table[] = { | ||||||
| 	INPUT_STATE_ANYWHERE, | 	INPUT_STATE_ANYWHERE, | ||||||
|  |  | ||||||
| @@ -602,7 +607,7 @@ static const struct input_transition input_state_dcs_parameter_table[] = { | |||||||
| 	{ -1, -1, NULL, NULL } | 	{ -1, -1, NULL, NULL } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* dcs_interm state table. */ | /* dcs_intermediate state table. */ | ||||||
| static const struct input_transition input_state_dcs_intermediate_table[] = { | static const struct input_transition input_state_dcs_intermediate_table[] = { | ||||||
| 	INPUT_STATE_ANYWHERE, | 	INPUT_STATE_ANYWHERE, | ||||||
|  |  | ||||||
| @@ -655,12 +660,12 @@ static const struct input_transition input_state_dcs_ignore_table[] = { | |||||||
| static const struct input_transition input_state_osc_string_table[] = { | static const struct input_transition input_state_osc_string_table[] = { | ||||||
| 	INPUT_STATE_ANYWHERE, | 	INPUT_STATE_ANYWHERE, | ||||||
|  |  | ||||||
| 	{ 0x00, 0x06, NULL,	    NULL }, | 	{ 0x00, 0x06, NULL,	     NULL }, | ||||||
| 	{ 0x07, 0x07, NULL,	    &input_state_ground }, | 	{ 0x07, 0x07, input_end_bel, &input_state_ground }, | ||||||
| 	{ 0x08, 0x17, NULL,	    NULL }, | 	{ 0x08, 0x17, NULL,	     NULL }, | ||||||
| 	{ 0x19, 0x19, NULL,	    NULL }, | 	{ 0x19, 0x19, NULL,	     NULL }, | ||||||
| 	{ 0x1c, 0x1f, NULL,	    NULL }, | 	{ 0x1c, 0x1f, NULL,	     NULL }, | ||||||
| 	{ 0x20, 0xff, input_input,  NULL }, | 	{ 0x20, 0xff, input_input,   NULL }, | ||||||
|  |  | ||||||
| 	{ -1, -1, NULL, NULL } | 	{ -1, -1, NULL, NULL } | ||||||
| }; | }; | ||||||
| @@ -993,8 +998,8 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval) | |||||||
| static void | static void | ||||||
| input_reply(struct input_ctx *ictx, const char *fmt, ...) | input_reply(struct input_ctx *ictx, const char *fmt, ...) | ||||||
| { | { | ||||||
| 	va_list	ap; | 	va_list	 ap; | ||||||
| 	char   *reply; | 	char	*reply; | ||||||
|  |  | ||||||
| 	va_start(ap, fmt); | 	va_start(ap, fmt); | ||||||
| 	xvasprintf(&reply, fmt, ap); | 	xvasprintf(&reply, fmt, ap); | ||||||
| @@ -1019,6 +1024,8 @@ input_clear(struct input_ctx *ictx) | |||||||
| 	*ictx->input_buf = '\0'; | 	*ictx->input_buf = '\0'; | ||||||
| 	ictx->input_len = 0; | 	ictx->input_len = 0; | ||||||
|  |  | ||||||
|  | 	ictx->input_end = INPUT_END_ST; | ||||||
|  |  | ||||||
| 	ictx->flags &= ~INPUT_DISCARD; | 	ictx->flags &= ~INPUT_DISCARD; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -2046,6 +2053,17 @@ input_csi_dispatch_sgr(struct input_ctx *ictx) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* End of input with BEL. */ | ||||||
|  | static int | ||||||
|  | input_end_bel(struct input_ctx *ictx) | ||||||
|  | { | ||||||
|  | 	log_debug("%s", __func__); | ||||||
|  |  | ||||||
|  | 	ictx->input_end = INPUT_END_BEL; | ||||||
|  |  | ||||||
|  | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* DCS string started. */ | /* DCS string started. */ | ||||||
| static void | static void | ||||||
| input_enter_dcs(struct input_ctx *ictx) | input_enter_dcs(struct input_ctx *ictx) | ||||||
| @@ -2102,7 +2120,8 @@ input_exit_osc(struct input_ctx *ictx) | |||||||
| 	if (ictx->input_len < 1 || *p < '0' || *p > '9') | 	if (ictx->input_len < 1 || *p < '0' || *p > '9') | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	log_debug("%s: \"%s\"", __func__, p); | 	log_debug("%s: \"%s\" (end %s)", __func__, p, | ||||||
|  | 	    ictx->input_end == INPUT_END_ST ? "ST" : "BEL"); | ||||||
|  |  | ||||||
| 	option = 0; | 	option = 0; | ||||||
| 	while (*p >= '0' && *p <= '9') | 	while (*p >= '0' && *p <= '9') | ||||||
| @@ -2119,23 +2138,23 @@ input_exit_osc(struct input_ctx *ictx) | |||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case 4: | 	case 4: | ||||||
| 		input_osc_4(ictx->wp, p); | 		input_osc_4(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 10: | 	case 10: | ||||||
| 		input_osc_10(ictx->wp, p); | 		input_osc_10(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 11: | 	case 11: | ||||||
| 		input_osc_11(ictx->wp, p); | 		input_osc_11(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 12: | 	case 12: | ||||||
| 		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */ | 		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */ | ||||||
| 			screen_set_cursor_colour(ictx->ctx.s, p); | 			screen_set_cursor_colour(ictx->ctx.s, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 52: | 	case 52: | ||||||
| 		input_osc_52(ictx->wp, p); | 		input_osc_52(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 104: | 	case 104: | ||||||
| 		input_osc_104(ictx->wp, p); | 		input_osc_104(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 112: | 	case 112: | ||||||
| 		if (*p == '\0') /* no arguments allowed */ | 		if (*p == '\0') /* no arguments allowed */ | ||||||
| @@ -2237,11 +2256,12 @@ input_top_bit_set(struct input_ctx *ictx) | |||||||
|  |  | ||||||
| /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ | /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ | ||||||
| static void | static void | ||||||
| input_osc_4(struct window_pane *wp, const char *p) | input_osc_4(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
| 	char	*copy, *s, *next = NULL; | 	struct window_pane	*wp = ictx->wp; | ||||||
| 	long	 idx; | 	char			*copy, *s, *next = NULL; | ||||||
| 	u_int	 r, g, b; | 	long	 		idx; | ||||||
|  | 	u_int			 r, g, b; | ||||||
|  |  | ||||||
| 	copy = s = xstrdup(p); | 	copy = s = xstrdup(p); | ||||||
| 	while (s != NULL && *s != '\0') { | 	while (s != NULL && *s != '\0') { | ||||||
| @@ -2271,9 +2291,10 @@ bad: | |||||||
|  |  | ||||||
| /* Handle the OSC 10 sequence for setting foreground colour. */ | /* Handle the OSC 10 sequence for setting foreground colour. */ | ||||||
| static void | static void | ||||||
| input_osc_10(struct window_pane *wp, const char *p) | input_osc_10(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
| 	u_int	 r, g, b; | 	struct window_pane	*wp = ictx->wp; | ||||||
|  | 	u_int			 r, g, b; | ||||||
|  |  | ||||||
| 	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) | 	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) | ||||||
| 	    goto bad; | 	    goto bad; | ||||||
| @@ -2289,9 +2310,10 @@ bad: | |||||||
|  |  | ||||||
| /* Handle the OSC 11 sequence for setting background colour. */ | /* Handle the OSC 11 sequence for setting background colour. */ | ||||||
| static void | static void | ||||||
| input_osc_11(struct window_pane *wp, const char *p) | input_osc_11(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
| 	u_int	 r, g, b; | 	struct window_pane	*wp = ictx->wp; | ||||||
|  | 	u_int			 r, g, b; | ||||||
|  |  | ||||||
| 	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) | 	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) | ||||||
| 	    goto bad; | 	    goto bad; | ||||||
| @@ -2307,13 +2329,16 @@ bad: | |||||||
|  |  | ||||||
| /* Handle the OSC 52 sequence for setting the clipboard. */ | /* Handle the OSC 52 sequence for setting the clipboard. */ | ||||||
| static void | static void | ||||||
| input_osc_52(struct window_pane *wp, const char *p) | input_osc_52(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
|  | 	struct window_pane	*wp = ictx->wp; | ||||||
| 	char			*end; | 	char			*end; | ||||||
|  | 	const char		*buf; | ||||||
| 	size_t			 len; | 	size_t			 len; | ||||||
| 	u_char			*out; | 	u_char			*out; | ||||||
| 	int			 outlen, state; | 	int			 outlen, state; | ||||||
| 	struct screen_write_ctx	 ctx; | 	struct screen_write_ctx	 ctx; | ||||||
|  | 	struct paste_buffer	*pb; | ||||||
|  |  | ||||||
| 	state = options_get_number(global_options, "set-clipboard"); | 	state = options_get_number(global_options, "set-clipboard"); | ||||||
| 	if (state != 2) | 	if (state != 2) | ||||||
| @@ -2324,6 +2349,32 @@ input_osc_52(struct window_pane *wp, const char *p) | |||||||
| 	end++; | 	end++; | ||||||
| 	if (*end == '\0') | 	if (*end == '\0') | ||||||
| 		return; | 		return; | ||||||
|  | 	log_debug("%s: %s", __func__, end); | ||||||
|  |  | ||||||
|  | 	if (strcmp(end, "?") == 0) { | ||||||
|  | 		if ((pb = paste_get_top(NULL)) != NULL) { | ||||||
|  | 			buf = paste_buffer_data(pb, &len); | ||||||
|  | 			outlen = 4 * ((len + 2) / 3) + 1; | ||||||
|  | 			out = xmalloc(outlen); | ||||||
|  | 			if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) { | ||||||
|  | 				abort(); | ||||||
|  | 				free(out); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			outlen = 0; | ||||||
|  | 			out = NULL; | ||||||
|  | 		} | ||||||
|  | 		bufferevent_write(wp->event, "\033]52;;", 6); | ||||||
|  | 		if (outlen != 0) | ||||||
|  | 			bufferevent_write(wp->event, out, outlen); | ||||||
|  | 		if (ictx->input_end == INPUT_END_BEL) | ||||||
|  | 			bufferevent_write(wp->event, "\007", 1); | ||||||
|  | 		else | ||||||
|  | 			bufferevent_write(wp->event, "\033\\", 2); | ||||||
|  | 		free(out); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	len = (strlen(end) / 4) * 3; | 	len = (strlen(end) / 4) * 3; | ||||||
| 	if (len == 0) | 	if (len == 0) | ||||||
| @@ -2345,10 +2396,11 @@ input_osc_52(struct window_pane *wp, const char *p) | |||||||
|  |  | ||||||
| /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */ | /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */ | ||||||
| static void | static void | ||||||
| input_osc_104(struct window_pane *wp, const char *p) | input_osc_104(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
| 	char	*copy, *s; | 	struct window_pane	*wp = ictx->wp; | ||||||
| 	long	idx; | 	char			*copy, *s; | ||||||
|  | 	long			idx; | ||||||
|  |  | ||||||
| 	if (*p == '\0') { | 	if (*p == '\0') { | ||||||
| 		window_pane_reset_palette(wp); | 		window_pane_reset_palette(wp); | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -917,8 +917,8 @@ is used, the | |||||||
| .Ic update-environment | .Ic update-environment | ||||||
| option will not be applied. | option will not be applied. | ||||||
| .It Xo Ic refresh-client | .It Xo Ic refresh-client | ||||||
|  | .Op Fl lS | ||||||
| .Op Fl C Ar width,height | .Op Fl C Ar width,height | ||||||
| .Op Fl S |  | ||||||
| .Op Fl t Ar target-client | .Op Fl t Ar target-client | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic refresh ) | .D1 (alias: Ic refresh ) | ||||||
| @@ -931,6 +931,10 @@ is specified, only update the client's status line. | |||||||
| .Pp | .Pp | ||||||
| .Fl C | .Fl C | ||||||
| sets the width and height of a control client. | sets the width and height of a control client. | ||||||
|  | .Fl l | ||||||
|  | requests the clipboard from the client using the | ||||||
|  | .Xr xterm 1 | ||||||
|  | escape sequence and stores it in a new paste buffer. | ||||||
| .It Xo Ic rename-session | .It Xo Ic rename-session | ||||||
| .Op Fl t Ar target-session | .Op Fl t Ar target-session | ||||||
| .Ar new-name | .Ar new-name | ||||||
| @@ -3890,7 +3894,7 @@ option. | |||||||
| .El | .El | ||||||
| .Pp | .Pp | ||||||
| When a pane is first created, its title is the hostname. | When a pane is first created, its title is the hostname. | ||||||
| A pane's title can be set via the OSC title setting sequence, for example: | A pane's title can be set via the title setting escape sequence, for example: | ||||||
| .Bd -literal -offset indent | .Bd -literal -offset indent | ||||||
| $ printf '\e033]2;My Title\e033\e\e' | $ printf '\e033]2;My Title\e033\e\e' | ||||||
| .Ed | .Ed | ||||||
| @@ -4444,7 +4448,7 @@ Indicate that the terminal supports the | |||||||
| .Ql direct colour | .Ql direct colour | ||||||
| RGB escape sequence (for example, \ee[38;2;255;255;255m). | RGB escape sequence (for example, \ee[38;2;255;255;255m). | ||||||
| .Pp | .Pp | ||||||
| If supported, this is used for the OSC initialize colour escape sequence (which | If supported, this is used for the initialize colour escape sequence (which | ||||||
| may be enabled by adding the | may be enabled by adding the | ||||||
| .Ql initc | .Ql initc | ||||||
| and | and | ||||||
|   | |||||||
							
								
								
									
										103
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								tty-keys.c
									
									
									
									
									
								
							| @@ -19,7 +19,10 @@ | |||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <sys/time.h> | #include <sys/time.h> | ||||||
|  |  | ||||||
|  | #include <netinet/in.h> | ||||||
|  |  | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
|  | #include <resolv.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <termios.h> | #include <termios.h> | ||||||
| @@ -44,6 +47,8 @@ static int	tty_keys_next1(struct tty *, const char *, size_t, key_code *, | |||||||
| 		    size_t *, int); | 		    size_t *, int); | ||||||
| static void	tty_keys_callback(int, short, void *); | static void	tty_keys_callback(int, short, void *); | ||||||
| static int	tty_keys_mouse(struct tty *, const char *, size_t, size_t *); | static int	tty_keys_mouse(struct tty *, const char *, size_t, size_t *); | ||||||
|  | static int	tty_keys_clipboard(struct tty *, const char *, size_t, | ||||||
|  | 		    size_t *); | ||||||
| static int	tty_keys_device_attributes(struct tty *, const char *, size_t, | static int	tty_keys_device_attributes(struct tty *, const char *, size_t, | ||||||
| 		    size_t *); | 		    size_t *); | ||||||
|  |  | ||||||
| @@ -571,6 +576,17 @@ tty_keys_next(struct tty *tty) | |||||||
| 		return (0); | 		return (0); | ||||||
| 	log_debug("%s: keys are %zu (%.*s)", c->name, len, (int)len, buf); | 	log_debug("%s: keys are %zu (%.*s)", c->name, len, (int)len, buf); | ||||||
|  |  | ||||||
|  | 	/* Is this a clipboard response? */ | ||||||
|  | 	switch (tty_keys_clipboard(tty, buf, len, &size)) { | ||||||
|  | 	case 0:		/* yes */ | ||||||
|  | 		key = KEYC_UNKNOWN; | ||||||
|  | 		goto complete_key; | ||||||
|  | 	case -1:	/* no, or not valid */ | ||||||
|  | 		break; | ||||||
|  | 	case 1:		/* partial */ | ||||||
|  | 		goto partial_key; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Is this a device attributes response? */ | 	/* Is this a device attributes response? */ | ||||||
| 	switch (tty_keys_device_attributes(tty, buf, len, &size)) { | 	switch (tty_keys_device_attributes(tty, buf, len, &size)) { | ||||||
| 	case 0:		/* yes */ | 	case 0:		/* yes */ | ||||||
| @@ -871,6 +887,93 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) | |||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Handle OSC 52 clipboard input. Returns 0 for success, -1 for failure, 1 for | ||||||
|  |  * partial. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, | ||||||
|  |     size_t *size) | ||||||
|  | { | ||||||
|  | 	size_t	 end, terminator, needed; | ||||||
|  | 	char	*copy, *out; | ||||||
|  | 	int	 outlen; | ||||||
|  |  | ||||||
|  | 	*size = 0; | ||||||
|  |  | ||||||
|  | 	/* First three bytes are always \033]52;. */ | ||||||
|  | 	if (buf[0] != '\033') | ||||||
|  | 		return (-1); | ||||||
|  | 	if (len == 1) | ||||||
|  | 		return (1); | ||||||
|  | 	if (buf[1] != ']') | ||||||
|  | 		return (-1); | ||||||
|  | 	if (len == 2) | ||||||
|  | 		return (1); | ||||||
|  | 	if (buf[2] != '5') | ||||||
|  | 		return (-1); | ||||||
|  | 	if (len == 3) | ||||||
|  | 		return (1); | ||||||
|  | 	if (buf[3] != '2') | ||||||
|  | 		return (-1); | ||||||
|  | 	if (len == 4) | ||||||
|  | 		return (1); | ||||||
|  | 	if (buf[4] != ';') | ||||||
|  | 		return (-1); | ||||||
|  | 	if (len == 5) | ||||||
|  | 		return (1); | ||||||
|  |  | ||||||
|  | 	/* Find the terminator if any. */ | ||||||
|  | 	for (end = 5; end < len; end++) { | ||||||
|  | 		if (buf[end] == '\007') { | ||||||
|  | 			terminator = 1; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (end > 5 && buf[end - 1] == '\033' && buf[end] == '\\') { | ||||||
|  | 			terminator = 2; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (end == len) | ||||||
|  | 		return (1); | ||||||
|  | 	*size = end + terminator; | ||||||
|  |  | ||||||
|  | 	/* Skip the initial part. */ | ||||||
|  | 	buf += 5; | ||||||
|  | 	end -= 5; | ||||||
|  |  | ||||||
|  | 	/* Get the second argument. */ | ||||||
|  | 	while (end != 0 && *buf != ';') { | ||||||
|  | 		buf++; | ||||||
|  | 		end--; | ||||||
|  | 	} | ||||||
|  | 	if (end == 0 || end == 1) | ||||||
|  | 		return (0); | ||||||
|  | 	buf++; | ||||||
|  | 	end--; | ||||||
|  |  | ||||||
|  | 	/* It has to be a string so copy it. */ | ||||||
|  | 	copy = xmalloc(end + 1); | ||||||
|  | 	memcpy(copy, buf, end); | ||||||
|  | 	copy[end] = '\0'; | ||||||
|  |  | ||||||
|  | 	/* Convert from base64. */ | ||||||
|  | 	needed = (end / 4) * 3; | ||||||
|  | 	out = xmalloc(needed); | ||||||
|  | 	if ((outlen = b64_pton(copy, out, len)) == -1) { | ||||||
|  | 		free(out); | ||||||
|  | 		free(copy); | ||||||
|  | 		return (0); | ||||||
|  | 	} | ||||||
|  | 	free(copy); | ||||||
|  |  | ||||||
|  | 	/* Create a new paste buffer. */ | ||||||
|  | 	log_debug("%s: %.*s", __func__, outlen, out); | ||||||
|  | 	paste_add(out, outlen); | ||||||
|  |  | ||||||
|  | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for |  * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for | ||||||
|  * partial. |  * partial. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm