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:
		
							
								
								
									
										2
									
								
								cfg.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cfg.c
									
									
									
									
									
								
							| @@ -286,8 +286,6 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet) | |||||||
| 		} | 		} | ||||||
| 		free(buf); | 		free(buf); | ||||||
|  |  | ||||||
| 		if (cmdlist == NULL) |  | ||||||
| 			continue; |  | ||||||
| 		new_item = cmdq_get_command(cmdlist, NULL, NULL, 0); | 		new_item = cmdq_get_command(cmdlist, NULL, NULL, 0); | ||||||
| 		if (item != NULL) | 		if (item != NULL) | ||||||
| 			cmdq_insert_after(item, new_item); | 			cmdq_insert_after(item, new_item); | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								cmd-find.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								cmd-find.c
									
									
									
									
									
								
							| @@ -587,8 +587,6 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane) | |||||||
|  |  | ||||||
| 	/* Try special characters. */ | 	/* Try special characters. */ | ||||||
| 	if (strcmp(pane, "!") == 0) { | 	if (strcmp(pane, "!") == 0) { | ||||||
| 		if (fs->w->last == NULL) |  | ||||||
| 			return (-1); |  | ||||||
| 		fs->wp = fs->w->last; | 		fs->wp = fs->w->last; | ||||||
| 		if (fs->wp == NULL) | 		if (fs->wp == NULL) | ||||||
| 			return (-1); | 			return (-1); | ||||||
| @@ -912,16 +910,12 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags) | |||||||
| 	 */ | 	 */ | ||||||
| 	fs->w = wp->window; | 	fs->w = wp->window; | ||||||
| 	if (cmd_find_best_session_with_window(fs) != 0) { | 	if (cmd_find_best_session_with_window(fs) != 0) { | ||||||
| 		if (wp != NULL) { | 		/* | ||||||
| 			/* | 		 * The window may have been destroyed but the pane | ||||||
| 			 * The window may have been destroyed but the pane | 		 * still on all_window_panes due to something else | ||||||
| 			 * still on all_window_panes due to something else | 		 * holding a reference. | ||||||
| 			 * holding a reference. | 		 */ | ||||||
| 			 */ | 		goto unknown_pane; | ||||||
| 			goto unknown_pane; |  | ||||||
| 		} |  | ||||||
| 		cmd_find_clear_state(fs, 0); |  | ||||||
| 		return (-1); |  | ||||||
| 	} | 	} | ||||||
| 	fs->wl = fs->s->curw; | 	fs->wl = fs->s->curw; | ||||||
| 	fs->w = fs->wl->window; | 	fs->w = fs->wl->window; | ||||||
|   | |||||||
| @@ -59,7 +59,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	struct client			*c = item->client; | 	struct client			*c = item->client; | ||||||
| 	FILE				*f; | 	FILE				*f; | ||||||
| 	const char			*path, *bufname; | 	const char			*path, *bufname; | ||||||
| 	char				*pdata, *new_pdata, *cause, *file; | 	char				*pdata = NULL, *new_pdata, *cause; | ||||||
|  | 	char				*file; | ||||||
| 	size_t				 psize; | 	size_t				 psize; | ||||||
| 	int				 ch, error; | 	int				 ch, error; | ||||||
|  |  | ||||||
| @@ -89,8 +90,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	f = fopen(file, "rb"); | 	f = fopen(file, "rb"); | ||||||
| 	if (f == NULL) { | 	if (f == NULL) { | ||||||
| 		cmdq_error(item, "%s: %s", file, strerror(errno)); | 		cmdq_error(item, "%s: %s", file, strerror(errno)); | ||||||
| 		free(file); | 		goto error; | ||||||
| 		return (CMD_RETURN_ERROR); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pdata = NULL; | 	pdata = NULL; | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ | |||||||
|  |  | ||||||
| static enum cmd_retval	cmd_pipe_pane_exec(struct cmd *, struct cmdq_item *); | static enum cmd_retval	cmd_pipe_pane_exec(struct cmd *, struct cmdq_item *); | ||||||
|  |  | ||||||
|  | static void cmd_pipe_pane_read_callback(struct bufferevent *, void *); | ||||||
| static void cmd_pipe_pane_write_callback(struct bufferevent *, void *); | static void cmd_pipe_pane_write_callback(struct bufferevent *, void *); | ||||||
| static void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *); | static void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *); | ||||||
|  |  | ||||||
| @@ -42,8 +43,8 @@ const struct cmd_entry cmd_pipe_pane_entry = { | |||||||
| 	.name = "pipe-pane", | 	.name = "pipe-pane", | ||||||
| 	.alias = "pipep", | 	.alias = "pipep", | ||||||
|  |  | ||||||
| 	.args = { "ot:", 0, 1 }, | 	.args = { "IOot:", 0, 1 }, | ||||||
| 	.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]", | 	.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [command]", | ||||||
|  |  | ||||||
| 	.target = { 't', CMD_FIND_PANE, 0 }, | 	.target = { 't', CMD_FIND_PANE, 0 }, | ||||||
|  |  | ||||||
| @@ -60,7 +61,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	struct session		*s = item->target.s; | 	struct session		*s = item->target.s; | ||||||
| 	struct winlink		*wl = item->target.wl; | 	struct winlink		*wl = item->target.wl; | ||||||
| 	char			*cmd; | 	char			*cmd; | ||||||
| 	int			 old_fd, pipe_fd[2], null_fd; | 	int			 old_fd, pipe_fd[2], null_fd, in, out; | ||||||
| 	struct format_tree	*ft; | 	struct format_tree	*ft; | ||||||
| 	sigset_t		 set, oldset; | 	sigset_t		 set, oldset; | ||||||
|  |  | ||||||
| @@ -90,6 +91,15 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if (args_has(self->args, 'o') && old_fd != -1) | 	if (args_has(self->args, 'o') && old_fd != -1) | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
|  |  | ||||||
|  | 	/* What do we want to do? Neither -I or -O is -O. */ | ||||||
|  | 	if (args_has(self->args, 'I')) { | ||||||
|  | 		in = 1; | ||||||
|  | 		out = args_has(self->args, 'O'); | ||||||
|  | 	} else { | ||||||
|  | 		in = 0; | ||||||
|  | 		out = 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Open the new pipe. */ | 	/* Open the new pipe. */ | ||||||
| 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { | 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { | ||||||
| 		cmdq_error(item, "socketpair error: %s", strerror(errno)); | 		cmdq_error(item, "socketpair error: %s", strerror(errno)); | ||||||
| @@ -118,19 +128,25 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		sigprocmask(SIG_SETMASK, &oldset, NULL); | 		sigprocmask(SIG_SETMASK, &oldset, NULL); | ||||||
| 		close(pipe_fd[0]); | 		close(pipe_fd[0]); | ||||||
|  |  | ||||||
| 		if (dup2(pipe_fd[1], STDIN_FILENO) == -1) |  | ||||||
| 			_exit(1); |  | ||||||
| 		if (pipe_fd[1] != STDIN_FILENO) |  | ||||||
| 			close(pipe_fd[1]); |  | ||||||
|  |  | ||||||
| 		null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); | 		null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); | ||||||
| 		if (dup2(null_fd, STDOUT_FILENO) == -1) | 		if (out) { | ||||||
| 			_exit(1); | 			if (dup2(pipe_fd[1], STDIN_FILENO) == -1) | ||||||
|  | 				_exit(1); | ||||||
|  | 		} else { | ||||||
|  | 			if (dup2(null_fd, STDIN_FILENO) == -1) | ||||||
|  | 				_exit(1); | ||||||
|  | 		} | ||||||
|  | 		if (in) { | ||||||
|  | 			if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) | ||||||
|  | 				_exit(1); | ||||||
|  | 			if (pipe_fd[1] != STDOUT_FILENO) | ||||||
|  | 				close(pipe_fd[1]); | ||||||
|  | 		} else { | ||||||
|  | 			if (dup2(null_fd, STDOUT_FILENO) == -1) | ||||||
|  | 				_exit(1); | ||||||
|  | 		} | ||||||
| 		if (dup2(null_fd, STDERR_FILENO) == -1) | 		if (dup2(null_fd, STDERR_FILENO) == -1) | ||||||
| 			_exit(1); | 			_exit(1); | ||||||
| 		if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO) |  | ||||||
| 			close(null_fd); |  | ||||||
|  |  | ||||||
| 		closefrom(STDERR_FILENO + 1); | 		closefrom(STDERR_FILENO + 1); | ||||||
|  |  | ||||||
| 		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); | 		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); | ||||||
| @@ -143,24 +159,46 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		wp->pipe_fd = pipe_fd[0]; | 		wp->pipe_fd = pipe_fd[0]; | ||||||
| 		wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); | 		wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); | ||||||
|  |  | ||||||
| 		wp->pipe_event = bufferevent_new(wp->pipe_fd, NULL, |  | ||||||
| 		    cmd_pipe_pane_write_callback, cmd_pipe_pane_error_callback, |  | ||||||
| 		    wp); |  | ||||||
| 		bufferevent_enable(wp->pipe_event, EV_WRITE); |  | ||||||
|  |  | ||||||
| 		setblocking(wp->pipe_fd, 0); | 		setblocking(wp->pipe_fd, 0); | ||||||
|  | 		wp->pipe_event = bufferevent_new(wp->pipe_fd, | ||||||
|  | 		    cmd_pipe_pane_read_callback, | ||||||
|  | 		    cmd_pipe_pane_write_callback, | ||||||
|  | 		    cmd_pipe_pane_error_callback, | ||||||
|  | 		    wp); | ||||||
|  | 		if (out) | ||||||
|  | 			bufferevent_enable(wp->pipe_event, EV_WRITE); | ||||||
|  | 		if (in) | ||||||
|  | 			bufferevent_enable(wp->pipe_event, EV_READ); | ||||||
|  |  | ||||||
| 		free(cmd); | 		free(cmd); | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | cmd_pipe_pane_read_callback(__unused struct bufferevent *bufev, void *data) | ||||||
|  | { | ||||||
|  | 	struct window_pane	*wp = data; | ||||||
|  | 	struct evbuffer		*evb = wp->pipe_event->input; | ||||||
|  | 	size_t			 available; | ||||||
|  |  | ||||||
|  | 	available = EVBUFFER_LENGTH(evb); | ||||||
|  | 	log_debug("%%%u pipe read %zu", wp->id, available); | ||||||
|  |  | ||||||
|  | 	bufferevent_write(wp->event, EVBUFFER_DATA(evb), available); | ||||||
|  | 	evbuffer_drain(evb, available); | ||||||
|  |  | ||||||
|  | 	if (window_pane_destroy_ready(wp)) | ||||||
|  | 		server_destroy_pane(wp, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| cmd_pipe_pane_write_callback(__unused struct bufferevent *bufev, void *data) | cmd_pipe_pane_write_callback(__unused struct bufferevent *bufev, void *data) | ||||||
| { | { | ||||||
| 	struct window_pane	*wp = data; | 	struct window_pane	*wp = data; | ||||||
|  |  | ||||||
| 	log_debug("%%%u pipe empty", wp->id); | 	log_debug("%%%u pipe empty", wp->id); | ||||||
|  |  | ||||||
| 	if (window_pane_destroy_ready(wp)) | 	if (window_pane_destroy_ready(wp)) | ||||||
| 		server_destroy_pane(wp, 1); | 		server_destroy_pane(wp, 1); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										122
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								input.c
									
									
									
									
									
								
							| @@ -85,6 +85,7 @@ struct input_ctx { | |||||||
| 	u_int			param_list_len; | 	u_int			param_list_len; | ||||||
|  |  | ||||||
| 	struct utf8_data	utf8data; | 	struct utf8_data	utf8data; | ||||||
|  | 	int			utf8started; | ||||||
|  |  | ||||||
| 	int			ch; | 	int			ch; | ||||||
| 	int			last; | 	int			last; | ||||||
| @@ -146,9 +147,7 @@ static void	input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *); | |||||||
| static void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); | 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_utf8_open(struct input_ctx *); | static int	input_top_bit_set(struct input_ctx *); | ||||||
| static int	input_utf8_add(struct input_ctx *); |  | ||||||
| static int	input_utf8_close(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 *); | ||||||
| @@ -314,9 +313,6 @@ static const struct input_transition input_state_osc_string_table[]; | |||||||
| static const struct input_transition input_state_apc_string_table[]; | static const struct input_transition input_state_apc_string_table[]; | ||||||
| static const struct input_transition input_state_rename_string_table[]; | static const struct input_transition input_state_rename_string_table[]; | ||||||
| static const struct input_transition input_state_consume_st_table[]; | static const struct input_transition input_state_consume_st_table[]; | ||||||
| static const struct input_transition input_state_utf8_three_table[]; |  | ||||||
| static const struct input_transition input_state_utf8_two_table[]; |  | ||||||
| static const struct input_transition input_state_utf8_one_table[]; |  | ||||||
|  |  | ||||||
| /* ground state definition. */ | /* ground state definition. */ | ||||||
| static const struct input_state input_state_ground = { | static const struct input_state input_state_ground = { | ||||||
| @@ -437,27 +433,6 @@ static const struct input_state input_state_consume_st = { | |||||||
| 	input_state_consume_st_table | 	input_state_consume_st_table | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* utf8_three state definition. */ |  | ||||||
| static const struct input_state input_state_utf8_three = { |  | ||||||
| 	"utf8_three", |  | ||||||
| 	NULL, NULL, |  | ||||||
| 	input_state_utf8_three_table |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* utf8_two state definition. */ |  | ||||||
| static const struct input_state input_state_utf8_two = { |  | ||||||
| 	"utf8_two", |  | ||||||
| 	NULL, NULL, |  | ||||||
| 	input_state_utf8_two_table |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* utf8_one state definition. */ |  | ||||||
| static const struct input_state input_state_utf8_one = { |  | ||||||
| 	"utf8_one", |  | ||||||
| 	NULL, NULL, |  | ||||||
| 	input_state_utf8_one_table |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* ground state table. */ | /* ground state table. */ | ||||||
| static const struct input_transition input_state_ground_table[] = { | static const struct input_transition input_state_ground_table[] = { | ||||||
| 	INPUT_STATE_ANYWHERE, | 	INPUT_STATE_ANYWHERE, | ||||||
| @@ -467,11 +442,7 @@ static const struct input_transition input_state_ground_table[] = { | |||||||
| 	{ 0x1c, 0x1f, input_c0_dispatch, NULL }, | 	{ 0x1c, 0x1f, input_c0_dispatch, NULL }, | ||||||
| 	{ 0x20, 0x7e, input_print,	 NULL }, | 	{ 0x20, 0x7e, input_print,	 NULL }, | ||||||
| 	{ 0x7f, 0x7f, NULL,		 NULL }, | 	{ 0x7f, 0x7f, NULL,		 NULL }, | ||||||
| 	{ 0x80, 0xc1, NULL,		 NULL }, | 	{ 0x80, 0xff, input_top_bit_set, NULL }, | ||||||
| 	{ 0xc2, 0xdf, input_utf8_open,	 &input_state_utf8_one }, |  | ||||||
| 	{ 0xe0, 0xef, input_utf8_open,	 &input_state_utf8_two }, |  | ||||||
| 	{ 0xf0, 0xf4, input_utf8_open,	 &input_state_utf8_three }, |  | ||||||
| 	{ 0xf5, 0xff, NULL,		 NULL }, |  | ||||||
|  |  | ||||||
| 	{ -1, -1, NULL, NULL } | 	{ -1, -1, NULL, NULL } | ||||||
| }; | }; | ||||||
| @@ -717,39 +688,6 @@ static const struct input_transition input_state_consume_st_table[] = { | |||||||
| 	{ -1, -1, NULL, NULL } | 	{ -1, -1, NULL, NULL } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* utf8_three state table. */ |  | ||||||
| static const struct input_transition input_state_utf8_three_table[] = { |  | ||||||
| 	/* No INPUT_STATE_ANYWHERE */ |  | ||||||
|  |  | ||||||
| 	{ 0x00, 0x7f, NULL,		&input_state_ground }, |  | ||||||
| 	{ 0x80, 0xbf, input_utf8_add,	&input_state_utf8_two }, |  | ||||||
| 	{ 0xc0, 0xff, NULL,		&input_state_ground }, |  | ||||||
|  |  | ||||||
| 	{ -1, -1, NULL, NULL } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* utf8_two state table. */ |  | ||||||
| static const struct input_transition input_state_utf8_two_table[] = { |  | ||||||
| 	/* No INPUT_STATE_ANYWHERE */ |  | ||||||
|  |  | ||||||
| 	{ 0x00, 0x7f, NULL,	      &input_state_ground }, |  | ||||||
| 	{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_one }, |  | ||||||
| 	{ 0xc0, 0xff, NULL,	      &input_state_ground }, |  | ||||||
|  |  | ||||||
| 	{ -1, -1, NULL, NULL } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* utf8_one state table. */ |  | ||||||
| static const struct input_transition input_state_utf8_one_table[] = { |  | ||||||
| 	/* No INPUT_STATE_ANYWHERE */ |  | ||||||
|  |  | ||||||
| 	{ 0x00, 0x7f, NULL,		&input_state_ground }, |  | ||||||
| 	{ 0x80, 0xbf, input_utf8_close, &input_state_ground }, |  | ||||||
| 	{ 0xc0, 0xff, NULL,		&input_state_ground }, |  | ||||||
|  |  | ||||||
| 	{ -1, -1, NULL, NULL } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* Input table compare. */ | /* Input table compare. */ | ||||||
| static int | static int | ||||||
| input_table_compare(const void *key, const void *value) | input_table_compare(const void *key, const void *value) | ||||||
| @@ -1059,6 +997,8 @@ input_print(struct input_ctx *ictx) | |||||||
| { | { | ||||||
| 	int	set; | 	int	set; | ||||||
|  |  | ||||||
|  | 	ictx->utf8started = 0; /* can't be valid UTF-8 */ | ||||||
|  |  | ||||||
| 	set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; | 	set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; | ||||||
| 	if (set == 1) | 	if (set == 1) | ||||||
| 		ictx->cell.cell.attr |= GRID_ATTR_CHARSET; | 		ictx->cell.cell.attr |= GRID_ATTR_CHARSET; | ||||||
| @@ -1132,6 +1072,8 @@ input_c0_dispatch(struct input_ctx *ictx) | |||||||
| 	struct window_pane	*wp = ictx->wp; | 	struct window_pane	*wp = ictx->wp; | ||||||
| 	struct screen		*s = sctx->s; | 	struct screen		*s = sctx->s; | ||||||
|  |  | ||||||
|  | 	ictx->utf8started = 0; /* can't be valid UTF-8 */ | ||||||
|  |  | ||||||
| 	log_debug("%s: '%c'", __func__, ictx->ch); | 	log_debug("%s: '%c'", __func__, ictx->ch); | ||||||
|  |  | ||||||
| 	switch (ictx->ch) { | 	switch (ictx->ch) { | ||||||
| @@ -2064,48 +2006,30 @@ input_exit_rename(struct input_ctx *ictx) | |||||||
|  |  | ||||||
| /* Open UTF-8 character. */ | /* Open UTF-8 character. */ | ||||||
| static int | static int | ||||||
| input_utf8_open(struct input_ctx *ictx) | input_top_bit_set(struct input_ctx *ictx) | ||||||
| { | { | ||||||
| 	struct utf8_data	*ud = &ictx->utf8data; | 	struct utf8_data	*ud = &ictx->utf8data; | ||||||
|  |  | ||||||
| 	if (utf8_open(ud, ictx->ch) != UTF8_MORE) |  | ||||||
| 		fatalx("UTF-8 open invalid %#x", ictx->ch); |  | ||||||
|  |  | ||||||
| 	log_debug("%s %hhu", __func__, ud->size); |  | ||||||
| 	ictx->last = -1; | 	ictx->last = -1; | ||||||
|  |  | ||||||
| 	return (0); | 	if (!ictx->utf8started) { | ||||||
| } | 		if (utf8_open(ud, ictx->ch) != UTF8_MORE) | ||||||
|  | 			return (0); | ||||||
| /* Append to UTF-8 character. */ | 		ictx->utf8started = 1; | ||||||
| static int |  | ||||||
| input_utf8_add(struct input_ctx *ictx) |  | ||||||
| { |  | ||||||
| 	struct utf8_data	*ud = &ictx->utf8data; |  | ||||||
|  |  | ||||||
| 	if (utf8_append(ud, ictx->ch) != UTF8_MORE) |  | ||||||
| 		fatalx("UTF-8 add invalid %#x", ictx->ch); |  | ||||||
|  |  | ||||||
| 	log_debug("%s", __func__); |  | ||||||
|  |  | ||||||
| 	return (0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Close UTF-8 string. */ |  | ||||||
| static int |  | ||||||
| input_utf8_close(struct input_ctx *ictx) |  | ||||||
| { |  | ||||||
| 	struct utf8_data	*ud = &ictx->utf8data; |  | ||||||
|  |  | ||||||
| 	if (utf8_append(ud, ictx->ch) != UTF8_DONE) { |  | ||||||
| 		/* |  | ||||||
| 		 * An error here could be invalid UTF-8 or it could be a |  | ||||||
| 		 * nonprintable character for which we can't get the |  | ||||||
| 		 * width. Drop it. |  | ||||||
| 		 */ |  | ||||||
| 		return (0); | 		return (0); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	switch (utf8_append(ud, ictx->ch)) { | ||||||
|  | 	case UTF8_MORE: | ||||||
|  | 		return (0); | ||||||
|  | 	case UTF8_ERROR: | ||||||
|  | 		ictx->utf8started = 0; | ||||||
|  | 		return (0); | ||||||
|  | 	case UTF8_DONE: | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	ictx->utf8started = 0; | ||||||
|  |  | ||||||
| 	log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, | 	log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, | ||||||
| 	    (int)ud->size, ud->data, ud->width); | 	    (int)ud->size, ud->data, ud->width); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								layout.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								layout.c
									
									
									
									
									
								
							| @@ -97,9 +97,24 @@ void | |||||||
| layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n) | layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n) | ||||||
| { | { | ||||||
| 	struct layout_cell	*lcchild; | 	struct layout_cell	*lcchild; | ||||||
|  | 	const char		*type; | ||||||
|  |  | ||||||
| 	log_debug("%s:%*s%p type %u [parent %p] wp=%p [%u,%u %ux%u]", hdr, n, | 	switch (lc->type) { | ||||||
| 	    " ", lc, lc->type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx, | 	case LAYOUT_LEFTRIGHT: | ||||||
|  | 		type = "LEFTRIGHT"; | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_TOPBOTTOM: | ||||||
|  | 		type = "TOPBOTTOM"; | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_WINDOWPANE: | ||||||
|  | 		type = "WINDOWPANE"; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		type = "UNKNOWN"; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	log_debug("%s:%*s%p type %s [parent %p] wp=%p [%u,%u %ux%u]", hdr, n, | ||||||
|  | 	    " ", lc, type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx, | ||||||
| 	    lc->sy); | 	    lc->sy); | ||||||
| 	switch (lc->type) { | 	switch (lc->type) { | ||||||
| 	case LAYOUT_LEFTRIGHT: | 	case LAYOUT_LEFTRIGHT: | ||||||
|   | |||||||
| @@ -1297,10 +1297,12 @@ screen_write_collect_end(struct screen_write_ctx *ctx) | |||||||
| 			grid_view_get_cell(s->grid, xx, s->cy, &gc); | 			grid_view_get_cell(s->grid, xx, s->cy, &gc); | ||||||
| 			if (~gc.flags & GRID_FLAG_PADDING) | 			if (~gc.flags & GRID_FLAG_PADDING) | ||||||
| 				break; | 				break; | ||||||
| 			grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell); | 			grid_view_set_cell(s->grid, xx, s->cy, | ||||||
|  | 			    &grid_default_cell); | ||||||
| 		} | 		} | ||||||
| 		if (gc.data.width > 1) | 		if (gc.data.width > 1) | ||||||
| 			grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell); | 			grid_view_set_cell(s->grid, xx, s->cy, | ||||||
|  | 			    &grid_default_cell); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	memcpy(&gc, &ci->gc, sizeof gc); | 	memcpy(&gc, &ci->gc, sizeof gc); | ||||||
| @@ -1333,7 +1335,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx, | |||||||
| 	 */ | 	 */ | ||||||
|  |  | ||||||
| 	collect = 1; | 	collect = 1; | ||||||
| 	if (gc->data.width != 1 || gc->data.size != 1) | 	if (gc->data.width != 1 || gc->data.size != 1 || *gc->data.data >= 0x7f) | ||||||
| 		collect = 0; | 		collect = 0; | ||||||
| 	else if (gc->attr & GRID_ATTR_CHARSET) | 	else if (gc->attr & GRID_ATTR_CHARSET) | ||||||
| 		collect = 0; | 		collect = 0; | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -1804,15 +1804,15 @@ If | |||||||
| .Fl a | .Fl a | ||||||
| is used, move to the next window with an alert. | is used, move to the next window with an alert. | ||||||
| .It Xo Ic pipe-pane | .It Xo Ic pipe-pane | ||||||
| .Op Fl o | .Op Fl IOo | ||||||
| .Op Fl t Ar target-pane | .Op Fl t Ar target-pane | ||||||
| .Op Ar shell-command | .Op Ar shell-command | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic pipep ) | .D1 (alias: Ic pipep ) | ||||||
| Pipe any output sent by the program in | Pipe output sent by the program in | ||||||
| .Ar target-pane | .Ar target-pane | ||||||
| to a shell command. | to a shell command or vice versa. | ||||||
| A pane may only be piped to one command at a time, any existing pipe is | A pane may only be connected to one command at a time, any existing pipe is | ||||||
| closed before | closed before | ||||||
| .Ar shell-command | .Ar shell-command | ||||||
| is executed. | is executed. | ||||||
| @@ -1825,6 +1825,25 @@ If no | |||||||
| .Ar shell-command | .Ar shell-command | ||||||
| is given, the current pipe (if any) is closed. | is given, the current pipe (if any) is closed. | ||||||
| .Pp | .Pp | ||||||
|  | .Fl I | ||||||
|  | and | ||||||
|  | .Fl O | ||||||
|  | specify which of the | ||||||
|  | .Ar shell-command | ||||||
|  | output streams are connected to the pane: | ||||||
|  | with | ||||||
|  | .Fl I | ||||||
|  | stdout is connected (so anything | ||||||
|  | .Ar shell-command | ||||||
|  | prints is written to the pane as if it were typed); | ||||||
|  | with | ||||||
|  | .Fl O | ||||||
|  | stdin is connected (so any output in the pane is piped to | ||||||
|  | .Ar shell-command ) . | ||||||
|  | Both may be used together and if neither are specified, | ||||||
|  | .Fl O | ||||||
|  | is used. | ||||||
|  | .Pp | ||||||
| The | The | ||||||
| .Fl o | .Fl o | ||||||
| option only opens a new pipe if no previous pipe exists, allowing a pipe to | option only opens a new pipe if no previous pipe exists, allowing a pipe to | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								tmux.c
									
									
									
									
									
								
							| @@ -44,7 +44,7 @@ int		 ptm_fd = -1; | |||||||
| const char	*shell_command; | const char	*shell_command; | ||||||
|  |  | ||||||
| static __dead void	 usage(void); | static __dead void	 usage(void); | ||||||
| static char		*make_label(const char *); | static char		*make_label(const char *, char **); | ||||||
|  |  | ||||||
| static const char	*getshell(void); | static const char	*getshell(void); | ||||||
| static int		 checkshell(const char *); | static int		 checkshell(const char *); | ||||||
| @@ -106,12 +106,13 @@ areshell(const char *shell) | |||||||
| } | } | ||||||
|  |  | ||||||
| static char * | static char * | ||||||
| make_label(const char *label) | make_label(const char *label, char **cause) | ||||||
| { | { | ||||||
| 	char		*base, resolved[PATH_MAX], *path, *s; | 	char		*base, resolved[PATH_MAX], *path, *s; | ||||||
| 	struct stat	 sb; | 	struct stat	 sb; | ||||||
| 	uid_t		 uid; | 	uid_t		 uid; | ||||||
| 	int		 saved_errno; |  | ||||||
|  | 	*cause = NULL; | ||||||
|  |  | ||||||
| 	if (label == NULL) | 	if (label == NULL) | ||||||
| 		label = "default"; | 		label = "default"; | ||||||
| @@ -121,11 +122,16 @@ make_label(const char *label) | |||||||
| 		xasprintf(&base, "%s/tmux-%ld", s, (long)uid); | 		xasprintf(&base, "%s/tmux-%ld", s, (long)uid); | ||||||
| 	else | 	else | ||||||
| 		xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid); | 		xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid); | ||||||
|  | 	if (realpath(base, resolved) == NULL && | ||||||
| 	if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST) | 	    strlcpy(resolved, base, sizeof resolved) >= sizeof resolved) { | ||||||
|  | 		errno = ERANGE; | ||||||
|  | 		free(base); | ||||||
| 		goto fail; | 		goto fail; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (lstat(base, &sb) != 0) | 	if (mkdir(resolved, S_IRWXU) != 0 && errno != EEXIST) | ||||||
|  | 		goto fail; | ||||||
|  | 	if (lstat(resolved, &sb) != 0) | ||||||
| 		goto fail; | 		goto fail; | ||||||
| 	if (!S_ISDIR(sb.st_mode)) { | 	if (!S_ISDIR(sb.st_mode)) { | ||||||
| 		errno = ENOTDIR; | 		errno = ENOTDIR; | ||||||
| @@ -135,18 +141,11 @@ make_label(const char *label) | |||||||
| 		errno = EACCES; | 		errno = EACCES; | ||||||
| 		goto fail; | 		goto fail; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (realpath(base, resolved) == NULL) |  | ||||||
| 		strlcpy(resolved, base, sizeof resolved); |  | ||||||
| 	xasprintf(&path, "%s/%s", resolved, label); | 	xasprintf(&path, "%s/%s", resolved, label); | ||||||
|  |  | ||||||
| 	free(base); |  | ||||||
| 	return (path); | 	return (path); | ||||||
|  |  | ||||||
| fail: | fail: | ||||||
| 	saved_errno = errno; | 	xasprintf(cause, "error creating %s (%s)", resolved, strerror(errno)); | ||||||
| 	free(base); |  | ||||||
| 	errno = saved_errno; |  | ||||||
| 	return (NULL); | 	return (NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -188,7 +187,7 @@ find_home(void) | |||||||
| int | int | ||||||
| main(int argc, char **argv) | main(int argc, char **argv) | ||||||
| { | { | ||||||
| 	char					*path, *label, **var; | 	char					*path, *label, *cause, **var; | ||||||
| 	char					 tmp[PATH_MAX]; | 	char					 tmp[PATH_MAX]; | ||||||
| 	const char				*s, *shell, *cwd; | 	const char				*s, *shell, *cwd; | ||||||
| 	int					 opt, flags, keys; | 	int					 opt, flags, keys; | ||||||
| @@ -341,8 +340,11 @@ main(int argc, char **argv) | |||||||
| 			path[strcspn(path, ",")] = '\0'; | 			path[strcspn(path, ",")] = '\0'; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (path == NULL && (path = make_label(label)) == NULL) { | 	if (path == NULL && (path = make_label(label, &cause)) == NULL) { | ||||||
| 		fprintf(stderr, "can't create socket: %s\n", strerror(errno)); | 		if (cause != NULL) { | ||||||
|  | 			fprintf(stderr, "%s\n", cause); | ||||||
|  | 			free(cause); | ||||||
|  | 		} | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| 	socket_path = path; | 	socket_path = path; | ||||||
|   | |||||||
							
								
								
									
										94
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								tty.c
									
									
									
									
									
								
							| @@ -878,12 +878,37 @@ tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox, | |||||||
| 	tty_draw_line(tty, wp, wp->screen, py, ox, oy); | 	tty_draw_line(tty, wp, wp->screen, py, ox, oy); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static const struct grid_cell * | ||||||
|  | tty_check_codeset(struct tty *tty, const struct grid_cell *gc) | ||||||
|  | { | ||||||
|  | 	static struct grid_cell	new; | ||||||
|  | 	u_int			n; | ||||||
|  |  | ||||||
|  | 	/* Characters less than 0x7f are always fine, no matter what. */ | ||||||
|  | 	if (gc->data.size == 1 && *gc->data.data < 0x7f) | ||||||
|  | 		return (gc); | ||||||
|  |  | ||||||
|  | 	/* UTF-8 terminal and a UTF-8 character - fine. */ | ||||||
|  | 	if (tty->flags & TTY_UTF8) | ||||||
|  | 		return (gc); | ||||||
|  |  | ||||||
|  | 	/* Replace by the right number of underscores. */ | ||||||
|  | 	n = gc->data.width; | ||||||
|  | 	if (n > UTF8_SIZE) | ||||||
|  | 		n = UTF8_SIZE; | ||||||
|  | 	memcpy(&new, gc, sizeof new); | ||||||
|  | 	new.data.size = n; | ||||||
|  | 	memset(new.data.data, '_', n); | ||||||
|  | 	return (&new); | ||||||
|  | } | ||||||
|  |  | ||||||
| void | void | ||||||
| tty_draw_line(struct tty *tty, const struct window_pane *wp, | tty_draw_line(struct tty *tty, const struct window_pane *wp, | ||||||
|     struct screen *s, u_int py, u_int ox, u_int oy) |     struct screen *s, u_int py, u_int ox, u_int oy) | ||||||
| { | { | ||||||
| 	struct grid		*gd = s->grid; | 	struct grid		*gd = s->grid; | ||||||
| 	struct grid_cell	 gc, last; | 	struct grid_cell	 gc, last; | ||||||
|  | 	const struct grid_cell	*gcp; | ||||||
| 	u_int			 i, j, ux, sx, nx, width; | 	u_int			 i, j, ux, sx, nx, width; | ||||||
| 	int			 flags, cleared = 0; | 	int			 flags, cleared = 0; | ||||||
| 	char			 buf[512]; | 	char			 buf[512]; | ||||||
| @@ -934,18 +959,15 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, | |||||||
|  |  | ||||||
| 	for (i = 0; i < sx; i++) { | 	for (i = 0; i < sx; i++) { | ||||||
| 		grid_view_get_cell(gd, i, py, &gc); | 		grid_view_get_cell(gd, i, py, &gc); | ||||||
|  | 		gcp = tty_check_codeset(tty, &gc); | ||||||
| 		if (len != 0 && | 		if (len != 0 && | ||||||
| 		    (((~tty->flags & TTY_UTF8) && | 		    ((gcp->attr & GRID_ATTR_CHARSET) || | ||||||
| 		    (gc.data.size != 1 || | 		    gcp->flags != last.flags || | ||||||
| 		    *gc.data.data >= 0x7f || | 		    gcp->attr != last.attr || | ||||||
| 		    gc.data.width != 1)) || | 		    gcp->fg != last.fg || | ||||||
| 		    (gc.attr & GRID_ATTR_CHARSET) || | 		    gcp->bg != last.bg || | ||||||
| 		    gc.flags != last.flags || | 		    ux + width + gcp->data.width >= screen_size_x(s) || | ||||||
| 		    gc.attr != last.attr || | 		    (sizeof buf) - len < gcp->data.size)) { | ||||||
| 		    gc.fg != last.fg || |  | ||||||
| 		    gc.bg != last.bg || |  | ||||||
| 		    ux + width + gc.data.width >= screen_size_x(s) || |  | ||||||
| 		    (sizeof buf) - len < gc.data.size)) { |  | ||||||
| 			tty_attributes(tty, &last, wp); | 			tty_attributes(tty, &last, wp); | ||||||
| 			tty_putn(tty, buf, len, width); | 			tty_putn(tty, buf, len, width); | ||||||
| 			ux += width; | 			ux += width; | ||||||
| @@ -954,35 +976,27 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, | |||||||
| 			width = 0; | 			width = 0; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (gc.flags & GRID_FLAG_SELECTED) | 		if (gcp->flags & GRID_FLAG_SELECTED) | ||||||
| 			screen_select_cell(s, &last, &gc); | 			screen_select_cell(s, &last, gcp); | ||||||
| 		else | 		else | ||||||
| 			memcpy(&last, &gc, sizeof last); | 			memcpy(&last, gcp, sizeof last); | ||||||
| 		if (ux + gc.data.width > screen_size_x(s)) | 		if (ux + gcp->data.width > screen_size_x(s)) { | ||||||
| 			for (j = 0; j < gc.data.width; j++) { | 			tty_attributes(tty, &last, wp); | ||||||
|  | 			for (j = 0; j < gcp->data.width; j++) { | ||||||
| 				if (ux + j > screen_size_x(s)) | 				if (ux + j > screen_size_x(s)) | ||||||
| 					break; | 					break; | ||||||
| 				tty_putc(tty, ' '); | 				tty_putc(tty, ' '); | ||||||
| 				ux++; | 				ux++; | ||||||
| 			} | 			} | ||||||
| 		else if (((~tty->flags & TTY_UTF8) && | 		} else if (gcp->attr & GRID_ATTR_CHARSET) { | ||||||
| 		    (gc.data.size != 1 || |  | ||||||
| 		    *gc.data.data >= 0x7f || |  | ||||||
| 		    gc.data.width != 1)) || |  | ||||||
| 		    (gc.attr & GRID_ATTR_CHARSET)) { |  | ||||||
| 			tty_attributes(tty, &last, wp); | 			tty_attributes(tty, &last, wp); | ||||||
| 			if (~tty->flags & TTY_UTF8) { | 			for (j = 0; j < gcp->data.size; j++) | ||||||
| 				for (j = 0; j < gc.data.width; j++) | 				tty_putc(tty, gcp->data.data[j]); | ||||||
| 					tty_putc(tty, '_'); |  | ||||||
| 			} else { |  | ||||||
| 				for (j = 0; j < gc.data.size; j++) |  | ||||||
| 					tty_putc(tty, gc.data.data[j]); |  | ||||||
| 			} |  | ||||||
| 			ux += gc.data.width; | 			ux += gc.data.width; | ||||||
| 		} else { | 		} else { | ||||||
| 			memcpy(buf + len, gc.data.data, gc.data.size); | 			memcpy(buf + len, gcp->data.data, gcp->data.size); | ||||||
| 			len += gc.data.size; | 			len += gcp->data.size; | ||||||
| 			width += gc.data.width; | 			width += gcp->data.width; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (len != 0) { | 	if (len != 0) { | ||||||
| @@ -1409,7 +1423,7 @@ static void | |||||||
| tty_cell(struct tty *tty, const struct grid_cell *gc, | tty_cell(struct tty *tty, const struct grid_cell *gc, | ||||||
|     const struct window_pane *wp) |     const struct window_pane *wp) | ||||||
| { | { | ||||||
| 	u_int	i; | 	const struct grid_cell	*gcp; | ||||||
|  |  | ||||||
| 	/* Skip last character if terminal is stupid. */ | 	/* Skip last character if terminal is stupid. */ | ||||||
| 	if ((tty->term->flags & TERM_EARLYWRAP) && | 	if ((tty->term->flags & TERM_EARLYWRAP) && | ||||||
| @@ -1425,22 +1439,16 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, | |||||||
| 	tty_attributes(tty, gc, wp); | 	tty_attributes(tty, gc, wp); | ||||||
|  |  | ||||||
| 	/* Get the cell and if ASCII write with putc to do ACS translation. */ | 	/* Get the cell and if ASCII write with putc to do ACS translation. */ | ||||||
| 	if (gc->data.size == 1) { | 	gcp = tty_check_codeset(tty, gc); | ||||||
| 		if (*gc->data.data < 0x20 || *gc->data.data == 0x7f) | 	if (gcp->data.size == 1) { | ||||||
|  | 		if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f) | ||||||
| 			return; | 			return; | ||||||
| 		tty_putc(tty, *gc->data.data); | 		tty_putc(tty, *gcp->data.data); | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* If not UTF-8, write _. */ |  | ||||||
| 	if (!(tty->flags & TTY_UTF8)) { |  | ||||||
| 		for (i = 0; i < gc->data.width; i++) |  | ||||||
| 			tty_putc(tty, '_'); |  | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Write the data. */ | 	/* Write the data. */ | ||||||
| 	tty_putn(tty, gc->data.data, gc->data.size, gc->data.width); | 	tty_putn(tty, gcp->data.data, gcp->data.size, gcp->data.width); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Thomas Adam
					Thomas Adam