mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
Conflicts: format.c window.c
This commit is contained in:
		| @@ -38,7 +38,7 @@ char		*cmd_capture_pane_history(struct args *, struct cmd_q *, | |||||||
| const struct cmd_entry cmd_capture_pane_entry = { | const struct cmd_entry cmd_capture_pane_entry = { | ||||||
| 	"capture-pane", "capturep", | 	"capture-pane", "capturep", | ||||||
| 	"ab:CeE:JpPqS:t:", 0, 0, | 	"ab:CeE:JpPqS:t:", 0, 0, | ||||||
| 	"[-aCeJpPq] [-b buffer-index] [-E end-line] [-S start-line]" | 	"[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]" | ||||||
| 	CMD_TARGET_PANE_USAGE, | 	CMD_TARGET_PANE_USAGE, | ||||||
| 	0, | 	0, | ||||||
| 	NULL, | 	NULL, | ||||||
| @@ -165,8 +165,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct client		*c; | 	struct client		*c; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	char			*buf, *cause; | 	char			*buf, *cause; | ||||||
| 	int			 buffer; | 	const char		*bufname; | ||||||
| 	u_int			 limit; |  | ||||||
| 	size_t			 len; | 	size_t			 len; | ||||||
|  |  | ||||||
| 	if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) | 	if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) | ||||||
| @@ -192,25 +191,17 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 		    evbuffer_add(c->stdout_data, "\n", 1); | 		    evbuffer_add(c->stdout_data, "\n", 1); | ||||||
| 		server_push_stdout(c); | 		server_push_stdout(c); | ||||||
| 	} else { | 	} else { | ||||||
| 		limit = options_get_number(&global_options, "buffer-limit"); |  | ||||||
| 		if (!args_has(args, 'b')) { |  | ||||||
| 			paste_add(buf, len, limit); |  | ||||||
| 			return (CMD_RETURN_NORMAL); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); | 		bufname = NULL; | ||||||
| 		if (cause != NULL) { | 		if (args_has(args, 'b')) | ||||||
| 			cmdq_error(cmdq, "buffer %s", cause); | 			bufname = args_get(args, 'b'); | ||||||
|  |  | ||||||
|  | 		if (paste_set(buf, len, bufname, &cause) != 0) { | ||||||
|  | 			cmdq_error(cmdq, "%s", cause); | ||||||
| 			free(buf); | 			free(buf); | ||||||
| 			free(cause); | 			free(cause); | ||||||
| 			return (CMD_RETURN_ERROR); | 			return (CMD_RETURN_ERROR); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (paste_replace(buffer, buf, len) != 0) { |  | ||||||
| 			cmdq_error(cmdq, "no buffer %d", buffer); |  | ||||||
| 			free(buf); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return (CMD_RETURN_NORMAL); | 	return (CMD_RETURN_NORMAL); | ||||||
|   | |||||||
| @@ -75,19 +75,20 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 		action = xstrdup("paste-buffer -b '%%'"); | 		action = xstrdup("paste-buffer -b '%%'"); | ||||||
|  |  | ||||||
| 	idx = 0; | 	idx = 0; | ||||||
| 	while ((pb = paste_walk_stack(&idx)) != NULL) { | 	pb = NULL; | ||||||
|  | 	while ((pb = paste_walk(pb)) != NULL) { | ||||||
| 		cdata = window_choose_data_create(TREE_OTHER, c, c->session); | 		cdata = window_choose_data_create(TREE_OTHER, c, c->session); | ||||||
| 		cdata->idx = idx - 1; | 		cdata->idx = idx; | ||||||
|  |  | ||||||
| 		cdata->ft_template = xstrdup(template); | 		cdata->ft_template = xstrdup(template); | ||||||
| 		format_add(cdata->ft, "line", "%u", idx - 1); |  | ||||||
| 		format_paste_buffer(cdata->ft, pb, utf8flag); | 		format_paste_buffer(cdata->ft, pb, utf8flag); | ||||||
|  |  | ||||||
| 		xasprintf(&action_data, "%u", idx - 1); | 		xasprintf(&action_data, "%s", pb->name); | ||||||
| 		cdata->command = cmd_template_replace(action, action_data, 1); | 		cdata->command = cmd_template_replace(action, action_data, 1); | ||||||
| 		free(action_data); | 		free(action_data); | ||||||
|  |  | ||||||
| 		window_choose_add(wl->window->active, cdata); | 		window_choose_add(wl->window->active, cdata); | ||||||
|  | 		idx++; | ||||||
| 	} | 	} | ||||||
| 	free(action); | 	free(action); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -41,23 +41,16 @@ enum cmd_retval | |||||||
| cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | ||||||
| { | { | ||||||
| 	struct args	*args = self->args; | 	struct args	*args = self->args; | ||||||
| 	char		*cause; | 	const char 	*bufname; | ||||||
| 	int		 buffer; |  | ||||||
|  |  | ||||||
| 	if (!args_has(args, 'b')) { | 	if (!args_has(args, 'b')) { | ||||||
| 		paste_free_top(); | 		paste_free_top(); | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
| 	} | 	} | ||||||
|  | 	bufname = args_get(args, 'b'); | ||||||
|  |  | ||||||
| 	buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); | 	if (paste_free_name(bufname) != 0) { | ||||||
| 	if (cause != NULL) { | 		cmdq_error(cmdq, "no buffer %s", bufname); | ||||||
| 		cmdq_error(cmdq, "buffer %s", cause); |  | ||||||
| 		free(cause); |  | ||||||
| 		return (CMD_RETURN_ERROR); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (paste_free_index(buffer) != 0) { |  | ||||||
| 		cmdq_error(cmdq, "no buffer %d", buffer); |  | ||||||
| 		return (CMD_RETURN_ERROR); | 		return (CMD_RETURN_ERROR); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -200,6 +200,8 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	window_choose_ready(wl->window->active, 0, cmd_find_window_callback); | 	window_choose_ready(wl->window->active, 0, cmd_find_window_callback); | ||||||
|  |  | ||||||
| out: | out: | ||||||
|  | 	for (i = 0; i < ARRAY_LENGTH(&find_list); i++) | ||||||
|  | 		free(ARRAY_ITEM(&find_list, i).list_ctx); | ||||||
| 	ARRAY_FREE(&find_list); | 	ARRAY_FREE(&find_list); | ||||||
| 	return (CMD_RETURN_NORMAL); | 	return (CMD_RETURN_NORMAL); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -44,17 +44,15 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct args		*args = self->args; | 	struct args		*args = self->args; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
| 	struct format_tree	*ft; | 	struct format_tree	*ft; | ||||||
| 	u_int			 idx; |  | ||||||
| 	char			*line; | 	char			*line; | ||||||
| 	const char		*template; | 	const char		*template; | ||||||
|  |  | ||||||
| 	if ((template = args_get(args, 'F')) == NULL) | 	if ((template = args_get(args, 'F')) == NULL) | ||||||
| 		template = LIST_BUFFERS_TEMPLATE; | 		template = LIST_BUFFERS_TEMPLATE; | ||||||
|  |  | ||||||
| 	idx = 0; | 	pb = NULL; | ||||||
| 	while ((pb = paste_walk_stack(&idx)) != NULL) { | 	while ((pb = paste_walk(pb)) != NULL) { | ||||||
| 		ft = format_create(); | 		ft = format_create(); | ||||||
| 		format_add(ft, "line", "%u", idx - 1); |  | ||||||
| 		format_paste_buffer(ft, pb, 0); | 		format_paste_buffer(ft, pb, 0); | ||||||
|  |  | ||||||
| 		line = format_expand(ft, template); | 		line = format_expand(ft, template); | ||||||
|   | |||||||
| @@ -50,30 +50,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct client	*c = cmdq->client; | 	struct client	*c = cmdq->client; | ||||||
| 	struct session  *s; | 	struct session  *s; | ||||||
| 	FILE		*f; | 	FILE		*f; | ||||||
| 	const char	*path; | 	const char	*path, *bufname; | ||||||
| 	char		*pdata, *new_pdata, *cause; | 	char		*pdata, *new_pdata, *cause; | ||||||
| 	size_t		 psize; | 	size_t		 psize; | ||||||
| 	u_int		 limit; | 	int		 ch, error, cwd, fd; | ||||||
| 	int		 ch, error, buffer, *buffer_ptr, cwd, fd; |  | ||||||
|  |  | ||||||
| 	if (!args_has(args, 'b')) | 	bufname = NULL; | ||||||
| 		buffer = -1; | 	if (args_has(args, 'b')) | ||||||
| 	else { | 		bufname = args_get(args, 'b'); | ||||||
| 		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); |  | ||||||
| 		if (cause != NULL) { |  | ||||||
| 			cmdq_error(cmdq, "buffer %s", cause); |  | ||||||
| 			free(cause); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	path = args->argv[0]; | 	path = args->argv[0]; | ||||||
| 	if (strcmp(path, "-") == 0) { | 	if (strcmp(path, "-") == 0) { | ||||||
| 		buffer_ptr = xmalloc(sizeof *buffer_ptr); |  | ||||||
| 		*buffer_ptr = buffer; |  | ||||||
|  |  | ||||||
| 		error = server_set_stdin_callback(c, cmd_load_buffer_callback, | 		error = server_set_stdin_callback(c, cmd_load_buffer_callback, | ||||||
| 		    buffer_ptr, &cause); | 		    (void*)bufname, &cause); | ||||||
| 		if (error != 0) { | 		if (error != 0) { | ||||||
| 			cmdq_error(cmdq, "%s: %s", path, cause); | 			cmdq_error(cmdq, "%s: %s", path, cause); | ||||||
| 			free(cause); | 			free(cause); | ||||||
| @@ -117,14 +106,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
|  |  | ||||||
| 	fclose(f); | 	fclose(f); | ||||||
|  |  | ||||||
| 	limit = options_get_number(&global_options, "buffer-limit"); | 	if (paste_set(pdata, psize, bufname, &cause) != 0) { | ||||||
| 	if (buffer == -1) { | 		cmdq_error(cmdq, "%s", cause); | ||||||
| 		paste_add(pdata, psize, limit); |  | ||||||
| 		return (CMD_RETURN_NORMAL); |  | ||||||
| 	} |  | ||||||
| 	if (paste_replace(buffer, pdata, psize) != 0) { |  | ||||||
| 		cmdq_error(cmdq, "no buffer %d", buffer); |  | ||||||
| 		free(pdata); | 		free(pdata); | ||||||
|  | 		free(cause); | ||||||
| 		return (CMD_RETURN_ERROR); | 		return (CMD_RETURN_ERROR); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -140,10 +125,9 @@ error: | |||||||
| void | void | ||||||
| cmd_load_buffer_callback(struct client *c, int closed, void *data) | cmd_load_buffer_callback(struct client *c, int closed, void *data) | ||||||
| { | { | ||||||
| 	int	*buffer = data; | 	const char	*bufname = data; | ||||||
| 	char	*pdata; | 	char		*pdata, *cause; | ||||||
| 	size_t	 psize; | 	size_t		 psize; | ||||||
| 	u_int	 limit; |  | ||||||
|  |  | ||||||
| 	if (!closed) | 	if (!closed) | ||||||
| 		return; | 		return; | ||||||
| @@ -154,26 +138,21 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) | |||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	psize = EVBUFFER_LENGTH(c->stdin_data); | 	psize = EVBUFFER_LENGTH(c->stdin_data); | ||||||
| 	if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) { | 	if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) | ||||||
| 		free(data); |  | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} |  | ||||||
| 	memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize); | 	memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize); | ||||||
| 	pdata[psize] = '\0'; | 	pdata[psize] = '\0'; | ||||||
| 	evbuffer_drain(c->stdin_data, psize); | 	evbuffer_drain(c->stdin_data, psize); | ||||||
|  |  | ||||||
| 	limit = options_get_number(&global_options, "buffer-limit"); | 	if (paste_set(pdata, psize, bufname, &cause) != 0) { | ||||||
| 	if (*buffer == -1) |  | ||||||
| 		paste_add(pdata, psize, limit); |  | ||||||
| 	else if (paste_replace(*buffer, pdata, psize) != 0) { |  | ||||||
| 		/* No context so can't use server_client_msg_error. */ | 		/* No context so can't use server_client_msg_error. */ | ||||||
| 		evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer); | 		evbuffer_add_printf(c->stderr_data, "%s", cause); | ||||||
| 		server_push_stderr(c); | 		server_push_stderr(c); | ||||||
| 		free(pdata); | 		free(pdata); | ||||||
|  | 		free(cause); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free(data); |  | ||||||
|  |  | ||||||
| out: | out: | ||||||
| 	cmdq_continue(c->cmdq); | 	cmdq_continue(c->cmdq); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,10 +35,10 @@ enum cmd_retval	 cmd_new_session_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_new_session_entry = { | const struct cmd_entry cmd_new_session_entry = { | ||||||
| 	"new-session", "new", | 	"new-session", "new", | ||||||
| 	"Ac:dDF:n:Ps:t:x:y:", 0, 1, | 	"Ac:dDF:n:Ps:t:x:y:", 0, -1, | ||||||
| 	"[-AdDP] [-c start-directory] [-F format] [-n window-name] " | 	"[-AdDP] [-c start-directory] [-F format] [-n window-name] " | ||||||
| 	"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] " | 	"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] " | ||||||
| 	"[command]", | 	"[-y height] [command]", | ||||||
| 	CMD_STARTSERVER|CMD_CANTNEST, | 	CMD_STARTSERVER|CMD_CANTNEST, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	cmd_new_session_exec | 	cmd_new_session_exec | ||||||
| @@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct termios		 tio, *tiop; | 	struct termios		 tio, *tiop; | ||||||
| 	const char		*newname, *target, *update, *errstr, *template; | 	const char		*newname, *target, *update, *errstr, *template; | ||||||
| 	const char		*path; | 	const char		*path; | ||||||
| 	char			*cmd, *cause, *cp; | 	char		       **argv, *cmd, *cause, *cp; | ||||||
| 	int			 detached, already_attached, idx, cwd, fd = -1; | 	int			 detached, already_attached, idx, cwd, fd = -1; | ||||||
|  | 	int			 argc; | ||||||
| 	u_int			 sx, sy; | 	u_int			 sx, sy; | ||||||
| 	struct format_tree	*ft; | 	struct format_tree	*ft; | ||||||
| 	struct environ_entry	*envent; | 	struct environ_entry	*envent; | ||||||
| @@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 		sy = 1; | 		sy = 1; | ||||||
|  |  | ||||||
| 	/* Figure out the command for the new window. */ | 	/* Figure out the command for the new window. */ | ||||||
| 	if (target != NULL) | 	argc = -1; | ||||||
| 		cmd = NULL; | 	argv = NULL; | ||||||
| 	else if (args->argc != 0) | 	if (target == NULL && args->argc != 0) { | ||||||
| 		cmd = args->argv[0]; | 		argc = args->argc; | ||||||
| 	else | 		argv = args->argv; | ||||||
|  | 	} else if (target == NULL) { | ||||||
| 		cmd = options_get_string(&global_s_options, "default-command"); | 		cmd = options_get_string(&global_s_options, "default-command"); | ||||||
|  | 		if (cmd != NULL && *cmd != '\0') { | ||||||
|  | 			argc = 1; | ||||||
|  | 			argv = &cmd; | ||||||
|  | 		} else { | ||||||
|  | 			argc = 0; | ||||||
|  | 			argv = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	path = NULL; | 	path = NULL; | ||||||
| 	if (c != NULL && c->session == NULL) | 	if (c != NULL && c->session == NULL) | ||||||
| @@ -206,8 +216,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
|  |  | ||||||
| 	/* Create the new session. */ | 	/* Create the new session. */ | ||||||
| 	idx = -1 - options_get_number(&global_s_options, "base-index"); | 	idx = -1 - options_get_number(&global_s_options, "base-index"); | ||||||
| 	s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy, | 	s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx, | ||||||
| 	    &cause); | 	    sy, &cause); | ||||||
| 	if (s == NULL) { | 	if (s == NULL) { | ||||||
| 		cmdq_error(cmdq, "create session failed: %s", cause); | 		cmdq_error(cmdq, "create session failed: %s", cause); | ||||||
| 		free(cause); | 		free(cause); | ||||||
| @@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	environ_free(&env); | 	environ_free(&env); | ||||||
|  |  | ||||||
| 	/* Set the initial window name if one given. */ | 	/* Set the initial window name if one given. */ | ||||||
| 	if (cmd != NULL && args_has(args, 'n')) { | 	if (argc >= 0 && args_has(args, 'n')) { | ||||||
| 		w = s->curw->window; | 		w = s->curw->window; | ||||||
| 		window_set_name(w, args_get(args, 'n')); | 		window_set_name(w, args_get(args, 'n')); | ||||||
| 		options_set_number(&w->options, "automatic-rename", 0); | 		options_set_number(&w->options, "automatic-rename", 0); | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ enum cmd_retval	cmd_new_window_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_new_window_entry = { | const struct cmd_entry cmd_new_window_entry = { | ||||||
| 	"new-window", "neww", | 	"new-window", "neww", | ||||||
| 	"ac:dF:kn:Pt:", 0, 1, | 	"ac:dF:kn:Pt:", 0, -1, | ||||||
| 	"[-adkP] [-c start-directory] [-F format] [-n window-name] " | 	"[-adkP] [-c start-directory] [-F format] [-n window-name] " | ||||||
| 	CMD_TARGET_WINDOW_USAGE " [command]", | 	CMD_TARGET_WINDOW_USAGE " [command]", | ||||||
| 	0, | 	0, | ||||||
| @@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct winlink		*wl; | 	struct winlink		*wl; | ||||||
| 	struct client		*c; | 	struct client		*c; | ||||||
| 	const char		*cmd, *path, *template; | 	const char		*cmd, *path, *template; | ||||||
| 	char			*cause, *cp; | 	char		       **argv, *cause, *cp; | ||||||
| 	int			 idx, last, detached, cwd, fd = -1; | 	int			 argc, idx, last, detached, cwd, fd = -1; | ||||||
| 	struct format_tree	*ft; | 	struct format_tree	*ft; | ||||||
| 	struct environ_entry	*envent; | 	struct environ_entry	*envent; | ||||||
|  |  | ||||||
| @@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	} | 	} | ||||||
| 	detached = args_has(args, 'd'); | 	detached = args_has(args, 'd'); | ||||||
|  |  | ||||||
| 	if (args->argc == 0) | 	if (args->argc == 0) { | ||||||
| 		cmd = options_get_string(&s->options, "default-command"); | 		cmd = options_get_string(&s->options, "default-command"); | ||||||
| 	else | 		if (cmd != NULL && *cmd != '\0') { | ||||||
| 		cmd = args->argv[0]; | 			argc = 1; | ||||||
|  | 			argv = (char**)&cmd; | ||||||
|  | 		} else { | ||||||
|  | 			argc = 0; | ||||||
|  | 			argv = NULL; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		argc = args->argc; | ||||||
|  | 		argv = args->argv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	path = NULL; | 	path = NULL; | ||||||
| 	if (cmdq->client != NULL && cmdq->client->session == NULL) | 	if (cmdq->client != NULL && cmdq->client->session == NULL) | ||||||
| @@ -145,7 +154,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
|  |  | ||||||
| 	if (idx == -1) | 	if (idx == -1) | ||||||
| 		idx = -1 - options_get_number(&s->options, "base-index"); | 		idx = -1 - options_get_number(&s->options, "base-index"); | ||||||
| 	wl = session_new(s, args_get(args, 'n'), cmd, path, cwd, idx, &cause); | 	wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx, | ||||||
|  | 		&cause); | ||||||
| 	if (wl == NULL) { | 	if (wl == NULL) { | ||||||
| 		cmdq_error(cmdq, "create window failed: %s", cause); | 		cmdq_error(cmdq, "create window failed: %s", cause); | ||||||
| 		free(cause); | 		free(cause); | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ void	cmd_paste_buffer_filter(struct window_pane *, | |||||||
| const struct cmd_entry cmd_paste_buffer_entry = { | const struct cmd_entry cmd_paste_buffer_entry = { | ||||||
| 	"paste-buffer", "pasteb", | 	"paste-buffer", "pasteb", | ||||||
| 	"db:prs:t:", 0, 0, | 	"db:prs:t:", 0, 0, | ||||||
| 	"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE, | 	"[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE, | ||||||
| 	0, | 	0, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	cmd_paste_buffer_exec | 	cmd_paste_buffer_exec | ||||||
| @@ -48,31 +48,22 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	struct session		*s; | 	struct session		*s; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
| 	const char		*sepstr; | 	const char		*sepstr, *bufname; | ||||||
| 	char			*cause; |  | ||||||
| 	int			 buffer; |  | ||||||
| 	int			 pflag; | 	int			 pflag; | ||||||
|  |  | ||||||
| 	if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) | 	if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) | ||||||
| 		return (CMD_RETURN_ERROR); | 		return (CMD_RETURN_ERROR); | ||||||
|  |  | ||||||
| 	if (!args_has(args, 'b')) | 	bufname = NULL; | ||||||
| 		buffer = -1; | 	if (args_has(args, 'b')) | ||||||
| 	else { | 		bufname = args_get(args, 'b'); | ||||||
| 		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); |  | ||||||
| 		if (cause != NULL) { |  | ||||||
| 			cmdq_error(cmdq, "buffer %s", cause); |  | ||||||
| 			free(cause); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (buffer == -1) | 	if (bufname == NULL) | ||||||
| 		pb = paste_get_top(); | 		pb = paste_get_top(); | ||||||
| 	else { | 	else { | ||||||
| 		pb = paste_get_index(buffer); | 		pb = paste_get_name(bufname); | ||||||
| 		if (pb == NULL) { | 		if (pb == NULL) { | ||||||
| 			cmdq_error(cmdq, "no buffer %d", buffer); | 			cmdq_error(cmdq, "no buffer %s", bufname); | ||||||
| 			return (CMD_RETURN_ERROR); | 			return (CMD_RETURN_ERROR); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -91,10 +82,10 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
|  |  | ||||||
| 	/* Delete the buffer if -d. */ | 	/* Delete the buffer if -d. */ | ||||||
| 	if (args_has(args, 'd')) { | 	if (args_has(args, 'd')) { | ||||||
| 		if (buffer == -1) | 		if (bufname == NULL) | ||||||
| 			paste_free_top(); | 			paste_free_top(); | ||||||
| 		else | 		else | ||||||
| 			paste_free_index(buffer); | 			paste_free_name(bufname); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return (CMD_RETURN_NORMAL); | 	return (CMD_RETURN_NORMAL); | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ enum cmd_retval	 cmd_respawn_pane_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_respawn_pane_entry = { | const struct cmd_entry cmd_respawn_pane_entry = { | ||||||
| 	"respawn-pane", "respawnp", | 	"respawn-pane", "respawnp", | ||||||
| 	"kt:", 0, 1, | 	"kt:", 0, -1, | ||||||
| 	"[-k] " CMD_TARGET_PANE_USAGE " [command]", | 	"[-k] " CMD_TARGET_PANE_USAGE " [command]", | ||||||
| 	0, | 	0, | ||||||
| 	NULL, | 	NULL, | ||||||
| @@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	struct session		*s; | 	struct session		*s; | ||||||
| 	struct environ		 env; | 	struct environ		 env; | ||||||
| 	const char		*cmd, *path; | 	const char		*path; | ||||||
| 	char			*cause; | 	char			*cause; | ||||||
| 	u_int			 idx; | 	u_int			 idx; | ||||||
| 	struct environ_entry	*envent; | 	struct environ_entry	*envent; | ||||||
| @@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	screen_reinit(&wp->base); | 	screen_reinit(&wp->base); | ||||||
| 	input_init(wp); | 	input_init(wp); | ||||||
|  |  | ||||||
| 	if (args->argc != 0) |  | ||||||
| 		cmd = args->argv[0]; |  | ||||||
| 	else |  | ||||||
| 		cmd = NULL; |  | ||||||
|  |  | ||||||
| 	path = NULL; | 	path = NULL; | ||||||
| 	if (cmdq->client != NULL && cmdq->client->session == NULL) | 	if (cmdq->client != NULL && cmdq->client->session == NULL) | ||||||
| 		envent = environ_find(&cmdq->client->environ, "PATH"); | 		envent = environ_find(&cmdq->client->environ, "PATH"); | ||||||
| @@ -87,8 +82,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	if (envent != NULL) | 	if (envent != NULL) | ||||||
| 		path = envent->value; | 		path = envent->value; | ||||||
|  |  | ||||||
| 	if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio, | 	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env, | ||||||
| 	    &cause) != 0) { | 	    s->tio, &cause) != 0) { | ||||||
| 		cmdq_error(cmdq, "respawn pane failed: %s", cause); | 		cmdq_error(cmdq, "respawn pane failed: %s", cause); | ||||||
| 		free(cause); | 		free(cause); | ||||||
| 		environ_free(&env); | 		environ_free(&env); | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ enum cmd_retval	 cmd_respawn_window_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_respawn_window_entry = { | const struct cmd_entry cmd_respawn_window_entry = { | ||||||
| 	"respawn-window", "respawnw", | 	"respawn-window", "respawnw", | ||||||
| 	"kt:", 0, 1, | 	"kt:", 0, -1, | ||||||
| 	"[-k] " CMD_TARGET_WINDOW_USAGE " [command]", | 	"[-k] " CMD_TARGET_WINDOW_USAGE " [command]", | ||||||
| 	0, | 	0, | ||||||
| 	NULL, | 	NULL, | ||||||
| @@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	struct session		*s; | 	struct session		*s; | ||||||
| 	struct environ		 env; | 	struct environ		 env; | ||||||
| 	const char		*cmd, *path; | 	const char		*path; | ||||||
| 	char		 	*cause; | 	char		 	*cause; | ||||||
| 	struct environ_entry	*envent; | 	struct environ_entry	*envent; | ||||||
|  |  | ||||||
| @@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	window_destroy_panes(w); | 	window_destroy_panes(w); | ||||||
| 	TAILQ_INSERT_HEAD(&w->panes, wp, entry); | 	TAILQ_INSERT_HEAD(&w->panes, wp, entry); | ||||||
| 	window_pane_resize(wp, w->sx, w->sy); | 	window_pane_resize(wp, w->sx, w->sy); | ||||||
| 	if (args->argc != 0) |  | ||||||
| 		cmd = args->argv[0]; |  | ||||||
| 	else |  | ||||||
| 		cmd = NULL; |  | ||||||
|  |  | ||||||
| 	path = NULL; | 	path = NULL; | ||||||
| 	if (cmdq->client != NULL && cmdq->client->session == NULL) | 	if (cmdq->client != NULL && cmdq->client->session == NULL) | ||||||
| @@ -89,8 +85,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	if (envent != NULL) | 	if (envent != NULL) | ||||||
| 		path = envent->value; | 		path = envent->value; | ||||||
|  |  | ||||||
| 	if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio, | 	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env, | ||||||
| 	    &cause) != 0) { | 	    s->tio, &cause) != 0) { | ||||||
| 		cmdq_error(cmdq, "respawn window failed: %s", cause); | 		cmdq_error(cmdq, "respawn window failed: %s", cause); | ||||||
| 		free(cause); | 		free(cause); | ||||||
| 		environ_free(&env); | 		environ_free(&env); | ||||||
|   | |||||||
| @@ -58,10 +58,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct client		*c = cmdq->client; | 	struct client		*c = cmdq->client; | ||||||
| 	struct session          *s; | 	struct session          *s; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
| 	const char		*path; | 	const char		*path, *bufname; | ||||||
| 	char			*cause, *start, *end, *msg; | 	char			*start, *end, *msg; | ||||||
| 	size_t			 size, used, msglen; | 	size_t			 size, used, msglen; | ||||||
| 	int			 cwd, fd, buffer; | 	int			 cwd, fd; | ||||||
| 	FILE			*f; | 	FILE			*f; | ||||||
|  |  | ||||||
| 	if (!args_has(args, 'b')) { | 	if (!args_has(args, 'b')) { | ||||||
| @@ -70,16 +70,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 			return (CMD_RETURN_ERROR); | 			return (CMD_RETURN_ERROR); | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); | 		bufname = args_get(args, 'b'); | ||||||
| 		if (cause != NULL) { | 		pb = paste_get_name(bufname); | ||||||
| 			cmdq_error(cmdq, "buffer %s", cause); |  | ||||||
| 			free(cause); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		pb = paste_get_index(buffer); |  | ||||||
| 		if (pb == NULL) { | 		if (pb == NULL) { | ||||||
| 			cmdq_error(cmdq, "no buffer %d", buffer); | 			cmdq_error(cmdq, "no buffer %s", bufname); | ||||||
| 			return (CMD_RETURN_ERROR); | 			return (CMD_RETURN_ERROR); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -31,8 +31,8 @@ enum cmd_retval	 cmd_set_buffer_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_set_buffer_entry = { | const struct cmd_entry cmd_set_buffer_entry = { | ||||||
| 	"set-buffer", "setb", | 	"set-buffer", "setb", | ||||||
| 	"ab:", 1, 1, | 	"ab:n:", 0, 1, | ||||||
| 	"[-a] " CMD_BUFFER_USAGE " data", | 	"[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data", | ||||||
| 	0, | 	0, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	cmd_set_buffer_exec | 	cmd_set_buffer_exec | ||||||
| @@ -43,38 +43,59 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| { | { | ||||||
| 	struct args		*args = self->args; | 	struct args		*args = self->args; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
| 	u_int			 limit; |  | ||||||
| 	char			*pdata, *cause; | 	char			*pdata, *cause; | ||||||
|  | 	const char		*bufname; | ||||||
| 	size_t			 psize, newsize; | 	size_t			 psize, newsize; | ||||||
| 	int			 buffer; |  | ||||||
|  |  | ||||||
| 	limit = options_get_number(&global_options, "buffer-limit"); | 	bufname = NULL; | ||||||
|  |  | ||||||
|  | 	if (args_has(args, 'n')) { | ||||||
|  | 		if (args->argc > 0) { | ||||||
|  | 			cmdq_error(cmdq, "don't provide data with n flag"); | ||||||
|  | 			return (CMD_RETURN_ERROR); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (args_has(args, 'b')) | ||||||
|  | 			bufname = args_get(args, 'b'); | ||||||
|  |  | ||||||
|  | 		if (bufname == NULL) { | ||||||
|  | 			pb = paste_get_top(); | ||||||
|  | 			if (pb == NULL) { | ||||||
|  | 				cmdq_error(cmdq, "no buffer"); | ||||||
|  | 				return (CMD_RETURN_ERROR); | ||||||
|  | 			} | ||||||
|  | 			bufname = pb->name; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) { | ||||||
|  | 			cmdq_error(cmdq, "%s", cause); | ||||||
|  | 			free(cause); | ||||||
|  | 			return (CMD_RETURN_ERROR); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return (CMD_RETURN_NORMAL); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (args->argc != 1) { | ||||||
|  | 		cmdq_error(cmdq, "no data specified"); | ||||||
|  | 		return (CMD_RETURN_ERROR); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	psize = 0; | 	psize = 0; | ||||||
| 	pdata = NULL; | 	pdata = NULL; | ||||||
|  |  | ||||||
| 	pb = NULL; | 	pb = NULL; | ||||||
| 	buffer = -1; |  | ||||||
|  |  | ||||||
| 	if ((newsize = strlen(args->argv[0])) == 0) | 	if ((newsize = strlen(args->argv[0])) == 0) | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
|  |  | ||||||
| 	if (args_has(args, 'b')) { | 	if (args_has(args, 'b')) { | ||||||
| 		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); | 		bufname = args_get(args, 'b'); | ||||||
| 		if (cause != NULL) { | 		pb = paste_get_name(bufname); | ||||||
| 			cmdq_error(cmdq, "buffer %s", cause); |  | ||||||
| 			free(cause); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
| 		pb = paste_get_index(buffer); |  | ||||||
| 		if (pb == NULL) { |  | ||||||
| 			cmdq_error(cmdq, "no buffer %d", buffer); |  | ||||||
| 			return (CMD_RETURN_ERROR); |  | ||||||
| 		} |  | ||||||
| 	} else if (args_has(args, 'a')) { | 	} else if (args_has(args, 'a')) { | ||||||
| 		pb = paste_get_top(); | 		pb = paste_get_top(); | ||||||
| 		if (pb != NULL) | 		if (pb != NULL) | ||||||
| 			buffer = 0; | 			bufname = pb->name; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (args_has(args, 'a') && pb != NULL) { | 	if (args_has(args, 'a') && pb != NULL) { | ||||||
| @@ -87,10 +108,12 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	memcpy(pdata + psize, args->argv[0], newsize); | 	memcpy(pdata + psize, args->argv[0], newsize); | ||||||
| 	psize += newsize; | 	psize += newsize; | ||||||
|  |  | ||||||
| 	if (buffer == -1) | 	if (paste_set(pdata, psize, bufname, &cause) != 0) { | ||||||
| 		paste_add(pdata, psize, limit); | 		cmdq_error(cmdq, "%s", cause); | ||||||
| 	else | 		free(pdata); | ||||||
| 		paste_replace(buffer, pdata, psize); | 		free(cause); | ||||||
|  | 		return (CMD_RETURN_ERROR); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return (CMD_RETURN_NORMAL); | 	return (CMD_RETURN_NORMAL); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ enum cmd_retval	 cmd_split_window_exec(struct cmd *, struct cmd_q *); | |||||||
|  |  | ||||||
| const struct cmd_entry cmd_split_window_entry = { | const struct cmd_entry cmd_split_window_entry = { | ||||||
| 	"split-window", "splitw", | 	"split-window", "splitw", | ||||||
| 	"c:dF:l:hp:Pt:v", 0, 1, | 	"c:dF:l:hp:Pt:v", 0, -1, | ||||||
| 	"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] " | 	"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] " | ||||||
| 	CMD_TARGET_PANE_USAGE " [command]", | 	CMD_TARGET_PANE_USAGE " [command]", | ||||||
| 	0, | 	0, | ||||||
| @@ -61,9 +61,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	struct window_pane	*wp, *new_wp = NULL; | 	struct window_pane	*wp, *new_wp = NULL; | ||||||
| 	struct environ		 env; | 	struct environ		 env; | ||||||
| 	const char		*cmd, *path, *shell, *template; | 	const char		*cmd, *path, *shell, *template; | ||||||
| 	char			*cause, *new_cause, *cp; | 	char		       **argv, *cause, *new_cause, *cp; | ||||||
| 	u_int			 hlimit; | 	u_int			 hlimit; | ||||||
| 	int			 size, percentage, cwd, fd = -1; | 	int			 argc, size, percentage, cwd, fd = -1; | ||||||
| 	enum layout_type	 type; | 	enum layout_type	 type; | ||||||
| 	struct layout_cell	*lc; | 	struct layout_cell	*lc; | ||||||
| 	struct client		*c; | 	struct client		*c; | ||||||
| @@ -80,10 +80,19 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	environ_copy(&s->environ, &env); | 	environ_copy(&s->environ, &env); | ||||||
| 	server_fill_environ(s, &env); | 	server_fill_environ(s, &env); | ||||||
|  |  | ||||||
| 	if (args->argc == 0) | 	if (args->argc == 0) { | ||||||
| 		cmd = options_get_string(&s->options, "default-command"); | 		cmd = options_get_string(&s->options, "default-command"); | ||||||
| 	else | 		if (cmd != NULL && *cmd != '\0') { | ||||||
| 		cmd = args->argv[0]; | 			argc = 1; | ||||||
|  | 			argv = (char**)&cmd; | ||||||
|  | 		} else { | ||||||
|  | 			argc = 0; | ||||||
|  | 			argv = NULL; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		argc = args->argc; | ||||||
|  | 		argv = args->argv; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (args_has(args, 'c')) { | 	if (args_has(args, 'c')) { | ||||||
| 		ft = format_create(); | 		ft = format_create(); | ||||||
| @@ -157,8 +166,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) | |||||||
| 	if (envent != NULL) | 	if (envent != NULL) | ||||||
| 		path = envent->value; | 		path = envent->value; | ||||||
|  |  | ||||||
| 	if (window_pane_spawn( | 	if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env, | ||||||
| 	    new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0) | 	    s->tio, &cause) != 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 	layout_assign_pane(lc, new_wp); | 	layout_assign_pane(lc, new_wp); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								cmd.c
									
									
									
									
									
								
							| @@ -179,14 +179,14 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv) | |||||||
| } | } | ||||||
|  |  | ||||||
| char ** | char ** | ||||||
| cmd_copy_argv(int argc, char *const *argv) | cmd_copy_argv(int argc, char **argv) | ||||||
| { | { | ||||||
| 	char	**new_argv; | 	char	**new_argv; | ||||||
| 	int	  i; | 	int	  i; | ||||||
|  |  | ||||||
| 	if (argc == 0) | 	if (argc == 0) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
| 	new_argv = xcalloc(argc, sizeof *new_argv); | 	new_argv = xcalloc(argc + 1, sizeof *new_argv); | ||||||
| 	for (i = 0; i < argc; i++) { | 	for (i = 0; i < argc; i++) { | ||||||
| 		if (argv[i] != NULL) | 		if (argv[i] != NULL) | ||||||
| 			new_argv[i] = xstrdup(argv[i]); | 			new_argv[i] = xstrdup(argv[i]); | ||||||
| @@ -206,6 +206,32 @@ cmd_free_argv(int argc, char **argv) | |||||||
| 	free(argv); | 	free(argv); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | char * | ||||||
|  | cmd_stringify_argv(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char	*buf; | ||||||
|  | 	int	 i; | ||||||
|  | 	size_t	 len; | ||||||
|  |  | ||||||
|  | 	if (argc == 0) | ||||||
|  | 		return (xstrdup("")); | ||||||
|  |  | ||||||
|  | 	len = 0; | ||||||
|  | 	buf = NULL; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < argc; i++) { | ||||||
|  | 		len += strlen(argv[i]) + 1; | ||||||
|  | 		buf = xrealloc(buf, 1, len); | ||||||
|  |  | ||||||
|  | 		if (i == 0) | ||||||
|  | 			*buf = '\0'; | ||||||
|  | 		else | ||||||
|  | 			strlcat(buf, " ", len); | ||||||
|  | 		strlcat(buf, argv[i], len); | ||||||
|  | 	} | ||||||
|  | 	return (buf); | ||||||
|  | } | ||||||
|  |  | ||||||
| struct cmd * | struct cmd * | ||||||
| cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) | cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								format.c
									
									
									
									
									
								
							| @@ -368,7 +368,7 @@ format_get_command(struct window_pane *wp) | |||||||
| 	cmd = osdep_get_name(wp->fd, wp->tty); | 	cmd = osdep_get_name(wp->fd, wp->tty); | ||||||
| 	if (cmd == NULL || *cmd == '\0') { | 	if (cmd == NULL || *cmd == '\0') { | ||||||
| 		free(cmd); | 		free(cmd); | ||||||
| 		cmd = xstrdup(wp->cmd); | 		cmd = cmd_stringify_argv(wp->argc, wp->argv); | ||||||
| 		if (cmd == NULL || *cmd == '\0') { | 		if (cmd == NULL || *cmd == '\0') { | ||||||
| 			free(cmd); | 			free(cmd); | ||||||
| 			cmd = xstrdup(wp->shell); | 			cmd = xstrdup(wp->shell); | ||||||
| @@ -559,10 +559,12 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp) | |||||||
| 	if (wp->tty != NULL) | 	if (wp->tty != NULL) | ||||||
| 		format_add(ft, "pane_tty", "%s", wp->tty); | 		format_add(ft, "pane_tty", "%s", wp->tty); | ||||||
| 	format_add(ft, "pane_pid", "%ld", (long) wp->pid); | 	format_add(ft, "pane_pid", "%ld", (long) wp->pid); | ||||||
| 	if (wp->cmd != NULL) |  | ||||||
| 		format_add(ft, "pane_start_command", "%s", wp->cmd); |  | ||||||
| 	if ((cwd = osdep_get_cwd(wp->fd)) != NULL) | 	if ((cwd = osdep_get_cwd(wp->fd)) != NULL) | ||||||
| 		format_add(ft, "pane_current_path", "%s", cwd); | 		format_add(ft, "pane_current_path", "%s", cwd); | ||||||
|  | 	if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) { | ||||||
|  | 		format_add(ft, "pane_start_command", "%s", cmd); | ||||||
|  | 		free(cmd); | ||||||
|  | 	} | ||||||
| 	if ((cmd = format_get_command(wp)) != NULL) { | 	if ((cmd = format_get_command(wp)) != NULL) { | ||||||
| 		format_add(ft, "pane_current_command", "%s", cmd); | 		format_add(ft, "pane_current_command", "%s", cmd); | ||||||
| 		free(cmd); | 		free(cmd); | ||||||
| @@ -610,6 +612,7 @@ format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb, | |||||||
| 	char	*s; | 	char	*s; | ||||||
|  |  | ||||||
| 	format_add(ft, "buffer_size", "%zu", pb->size); | 	format_add(ft, "buffer_size", "%zu", pb->size); | ||||||
|  | 	format_add(ft, "buffer_name", "%s", pb->name); | ||||||
|  |  | ||||||
| 	s = paste_make_sample(pb, utf8flag); | 	s = paste_make_sample(pb, utf8flag); | ||||||
| 	format_add(ft, "buffer_sample", "%s", s); | 	format_add(ft, "buffer_sample", "%s", s); | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								input-keys.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								input-keys.c
									
									
									
									
									
								
							| @@ -204,6 +204,21 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m) | |||||||
| 	char			 buf[40]; | 	char			 buf[40]; | ||||||
| 	size_t			 len; | 	size_t			 len; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
|  | 	u_int			 i; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * If the alternate screen is active and hasn't enabled the mouse, send | ||||||
|  | 	 * up and down key presses for the mouse wheel. | ||||||
|  | 	 */ | ||||||
|  | 	if (wp->saved_grid != NULL && !(wp->screen->mode & ALL_MOUSE_MODES)) { | ||||||
|  | 		for (i = 0; i < m->scroll; i++) { | ||||||
|  | 			if (m->wheel == MOUSE_WHEEL_UP) | ||||||
|  | 				input_key(wp, KEYC_UP); | ||||||
|  | 			else | ||||||
|  | 				input_key(wp, KEYC_DOWN); | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (wp->screen->mode & ALL_MOUSE_MODES) { | 	if (wp->screen->mode & ALL_MOUSE_MODES) { | ||||||
| 		/* | 		/* | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								layout.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								layout.c
									
									
									
									
									
								
							| @@ -53,7 +53,6 @@ layout_create_cell(struct layout_cell *lcparent) | |||||||
| 	lc->yoff = UINT_MAX; | 	lc->yoff = UINT_MAX; | ||||||
|  |  | ||||||
| 	lc->wp = NULL; | 	lc->wp = NULL; | ||||||
| 	lc->lastwp = NULL; |  | ||||||
|  |  | ||||||
| 	return (lc); | 	return (lc); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -141,6 +141,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = { | |||||||
| 	{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" }, | 	{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" }, | ||||||
| 	{ MODEKEYCOPY_SEARCHUP, "search-backward" }, | 	{ MODEKEYCOPY_SEARCHUP, "search-backward" }, | ||||||
| 	{ MODEKEYCOPY_SELECTLINE, "select-line" }, | 	{ MODEKEYCOPY_SELECTLINE, "select-line" }, | ||||||
|  | 	{ MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" }, | ||||||
| 	{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" }, | 	{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" }, | ||||||
| 	{ MODEKEYCOPY_STARTOFLINE, "start-of-line" }, | 	{ MODEKEYCOPY_STARTOFLINE, "start-of-line" }, | ||||||
| 	{ MODEKEYCOPY_STARTSELECTION, "begin-selection" }, | 	{ MODEKEYCOPY_STARTSELECTION, "begin-selection" }, | ||||||
| @@ -257,6 +258,7 @@ struct mode_key_tree mode_key_tree_vi_choice; | |||||||
| /* vi copy mode keys. */ | /* vi copy mode keys. */ | ||||||
| const struct mode_key_entry mode_key_vi_copy[] = { | const struct mode_key_entry mode_key_vi_copy[] = { | ||||||
| 	{ ' ',			    0, MODEKEYCOPY_STARTSELECTION }, | 	{ ' ',			    0, MODEKEYCOPY_STARTSELECTION }, | ||||||
|  | 	{ '"',			    0, MODEKEYCOPY_STARTNAMEDBUFFER }, | ||||||
| 	{ '$',			    0, MODEKEYCOPY_ENDOFLINE }, | 	{ '$',			    0, MODEKEYCOPY_ENDOFLINE }, | ||||||
| 	{ ',',			    0, MODEKEYCOPY_JUMPREVERSE }, | 	{ ',',			    0, MODEKEYCOPY_JUMPREVERSE }, | ||||||
| 	{ ';',			    0, MODEKEYCOPY_JUMPAGAIN }, | 	{ ';',			    0, MODEKEYCOPY_JUMPAGAIN }, | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								names.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								names.c
									
									
									
									
									
								
							| @@ -68,9 +68,15 @@ window_name_callback(unused int fd, unused short events, void *data) | |||||||
| char * | char * | ||||||
| default_window_name(struct window *w) | default_window_name(struct window *w) | ||||||
| { | { | ||||||
| 	if (w->active->cmd != NULL && *w->active->cmd != '\0') | 	char    *cmd, *s; | ||||||
| 		return (parse_window_name(w->active->cmd)); |  | ||||||
| 	return (parse_window_name(w->active->shell)); | 	cmd = cmd_stringify_argv(w->active->argc, w->active->argv); | ||||||
|  | 	if (cmd != NULL && *cmd != '\0') | ||||||
|  | 		s = parse_window_name(cmd); | ||||||
|  | 	else | ||||||
|  | 		s = parse_window_name(w->active->shell); | ||||||
|  | 	free(cmd); | ||||||
|  | 	return (s); | ||||||
| } | } | ||||||
|  |  | ||||||
| char * | char * | ||||||
|   | |||||||
							
								
								
									
										218
									
								
								paste.c
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								paste.c
									
									
									
									
									
								
							| @@ -25,127 +25,237 @@ | |||||||
| #include "tmux.h" | #include "tmux.h" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Stack of paste buffers. Note that paste buffer data is not necessarily a C |  * Set of paste buffers. Note that paste buffer data is not necessarily a C | ||||||
|  * string! |  * string! | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| ARRAY_DECL(, struct paste_buffer *) paste_buffers =  ARRAY_INITIALIZER; | u_int	paste_next_index; | ||||||
|  | u_int	paste_next_order; | ||||||
|  | u_int	paste_num_automatic; | ||||||
|  | RB_HEAD(paste_name_tree, paste_buffer) paste_by_name; | ||||||
|  | RB_HEAD(paste_time_tree, paste_buffer) paste_by_time; | ||||||
|  |  | ||||||
| /* Return each item of the stack in turn. */ | int paste_cmp_names(const struct paste_buffer *, const struct paste_buffer *); | ||||||
| struct paste_buffer * | RB_PROTOTYPE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names); | ||||||
| paste_walk_stack(u_int *idx) | RB_GENERATE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names); | ||||||
|  |  | ||||||
|  | int paste_cmp_times(const struct paste_buffer *, const struct paste_buffer *); | ||||||
|  | RB_PROTOTYPE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times); | ||||||
|  | RB_GENERATE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times); | ||||||
|  |  | ||||||
|  | int | ||||||
|  | paste_cmp_names(const struct paste_buffer *a, const struct paste_buffer *b) | ||||||
| { | { | ||||||
| 	struct paste_buffer	*pb; | 	return (strcmp(a->name, b->name)); | ||||||
|  |  | ||||||
| 	pb = paste_get_index(*idx); |  | ||||||
| 	(*idx)++; |  | ||||||
| 	return (pb); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get the top item on the stack. */ | int | ||||||
|  | paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b) | ||||||
|  | { | ||||||
|  | 	if (a->order > b->order) | ||||||
|  | 		return (-1); | ||||||
|  | 	if (a->order < b->order) | ||||||
|  | 		return (1); | ||||||
|  | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Walk paste buffers by name. */ | ||||||
|  | struct paste_buffer * | ||||||
|  | paste_walk(struct paste_buffer *pb) | ||||||
|  | { | ||||||
|  | 	if (pb == NULL) | ||||||
|  | 		return (RB_MIN(paste_time_tree, &paste_by_time)); | ||||||
|  | 	return (RB_NEXT(paste_time_tree, &paste_by_time, pb)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Get the most recent automatic buffer */ | ||||||
| struct paste_buffer * | struct paste_buffer * | ||||||
| paste_get_top(void) | paste_get_top(void) | ||||||
| { | { | ||||||
| 	if (ARRAY_LENGTH(&paste_buffers) == 0) | 	struct paste_buffer	*pb; | ||||||
|  |  | ||||||
|  | 	pb = RB_MIN(paste_time_tree, &paste_by_time); | ||||||
|  | 	if (pb == NULL) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
| 	return (ARRAY_FIRST(&paste_buffers)); | 	return (pb); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get an item by its index. */ | /* Free the most recent buffer */ | ||||||
| struct paste_buffer * |  | ||||||
| paste_get_index(u_int idx) |  | ||||||
| { |  | ||||||
| 	if (idx >= ARRAY_LENGTH(&paste_buffers)) |  | ||||||
| 		return (NULL); |  | ||||||
| 	return (ARRAY_ITEM(&paste_buffers, idx)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Free the top item on the stack. */ |  | ||||||
| int | int | ||||||
| paste_free_top(void) | paste_free_top(void) | ||||||
| { | { | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
|  |  | ||||||
| 	if (ARRAY_LENGTH(&paste_buffers) == 0) | 	pb = paste_get_top(); | ||||||
|  | 	if (pb == NULL) | ||||||
| 		return (-1); | 		return (-1); | ||||||
|  | 	return (paste_free_name(pb->name)); | ||||||
| 	pb = ARRAY_FIRST(&paste_buffers); |  | ||||||
| 	ARRAY_REMOVE(&paste_buffers, 0); |  | ||||||
|  |  | ||||||
| 	free(pb->data); |  | ||||||
| 	free(pb); |  | ||||||
|  |  | ||||||
| 	return (0); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Free an item by index. */ | /* Get a paste buffer by name. */ | ||||||
| int | struct paste_buffer * | ||||||
| paste_free_index(u_int idx) | paste_get_name(const char *name) | ||||||
| { | { | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	pbfind; | ||||||
|  |  | ||||||
| 	if (idx >= ARRAY_LENGTH(&paste_buffers)) | 	if (name == NULL || *name == '\0') | ||||||
|  | 		return (NULL); | ||||||
|  |  | ||||||
|  | 	pbfind.name = (char*)name; | ||||||
|  | 	return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Free a paste buffer by name. */ | ||||||
|  | int | ||||||
|  | paste_free_name(const char *name) | ||||||
|  | { | ||||||
|  | 	struct paste_buffer	*pb, pbfind; | ||||||
|  |  | ||||||
|  | 	if (name == NULL || *name == '\0') | ||||||
| 		return (-1); | 		return (-1); | ||||||
|  |  | ||||||
| 	pb = ARRAY_ITEM(&paste_buffers, idx); | 	pbfind.name = (char*)name; | ||||||
| 	ARRAY_REMOVE(&paste_buffers, idx); | 	pb = RB_FIND(paste_name_tree, &paste_by_name, &pbfind); | ||||||
|  | 	if (pb == NULL) | ||||||
|  | 		return (-1); | ||||||
|  |  | ||||||
|  | 	RB_REMOVE(paste_name_tree, &paste_by_name, pb); | ||||||
|  | 	RB_REMOVE(paste_time_tree, &paste_by_time, pb); | ||||||
|  | 	if (pb->automatic) | ||||||
|  | 		paste_num_automatic--; | ||||||
|  |  | ||||||
| 	free(pb->data); | 	free(pb->data); | ||||||
|  | 	free(pb->name); | ||||||
| 	free(pb); | 	free(pb); | ||||||
|  |  | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Add an item onto the top of the stack, freeing the bottom if at limit. Note |  * Add an automatic buffer, freeing the oldest automatic item if at limit. Note | ||||||
|  * that the caller is responsible for allocating data. |  * that the caller is responsible for allocating data. | ||||||
|  */ |  */ | ||||||
| void | void | ||||||
| paste_add(char *data, size_t size, u_int limit) | paste_add(char *data, size_t size) | ||||||
| { | { | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb, *pb1; | ||||||
|  | 	u_int			 limit; | ||||||
|  |  | ||||||
| 	if (size == 0) | 	if (size == 0) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	while (ARRAY_LENGTH(&paste_buffers) >= limit) { | 	limit = options_get_number(&global_options, "buffer-limit"); | ||||||
| 		pb = ARRAY_LAST(&paste_buffers); | 	RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) { | ||||||
| 		free(pb->data); | 		if (paste_num_automatic < limit) | ||||||
| 		free(pb); | 			break; | ||||||
| 		ARRAY_TRUNC(&paste_buffers, 1); | 		if (pb->automatic) | ||||||
|  | 			paste_free_name(pb->name); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pb = xmalloc(sizeof *pb); | 	pb = xmalloc(sizeof *pb); | ||||||
| 	ARRAY_INSERT(&paste_buffers, 0, pb); |  | ||||||
|  | 	pb->name = NULL; | ||||||
|  | 	do { | ||||||
|  | 		free(pb->name); | ||||||
|  | 		xasprintf(&pb->name, "buffer%04u", paste_next_index); | ||||||
|  | 		paste_next_index++; | ||||||
|  | 	} while (paste_get_name(pb->name) != NULL); | ||||||
|  |  | ||||||
| 	pb->data = data; | 	pb->data = data; | ||||||
| 	pb->size = size; | 	pb->size = size; | ||||||
|  |  | ||||||
|  | 	pb->automatic = 1; | ||||||
|  | 	paste_num_automatic++; | ||||||
|  |  | ||||||
|  | 	pb->order = paste_next_order++; | ||||||
|  | 	RB_INSERT(paste_name_tree, &paste_by_name, pb); | ||||||
|  | 	RB_INSERT(paste_time_tree, &paste_by_time, pb); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Rename a paste buffer. */ | ||||||
|  | int | ||||||
|  | paste_rename(const char *oldname, const char *newname, char **cause) | ||||||
|  | { | ||||||
|  | 	struct paste_buffer	*pb; | ||||||
|  |  | ||||||
|  | 	if (cause != NULL) | ||||||
|  | 		*cause = NULL; | ||||||
|  |  | ||||||
|  | 	if (oldname == NULL || *oldname == '\0') { | ||||||
|  | 		if (cause != NULL) | ||||||
|  | 			*cause = xstrdup("no buffer"); | ||||||
|  | 		return (-1); | ||||||
|  | 	} | ||||||
|  | 	if (newname == NULL || *newname == '\0') { | ||||||
|  | 		if (cause != NULL) | ||||||
|  | 			*cause = xstrdup("new name is empty"); | ||||||
|  | 		return (-1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pb = paste_get_name(oldname); | ||||||
|  | 	if (pb == NULL) { | ||||||
|  | 		if (cause != NULL) | ||||||
|  | 		    xasprintf(cause, "no buffer %s", oldname); | ||||||
|  | 		return (-1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	RB_REMOVE(paste_name_tree, &paste_by_name, pb); | ||||||
|  |  | ||||||
|  | 	free(pb->name); | ||||||
|  | 	pb->name = xstrdup(newname); | ||||||
|  |  | ||||||
|  | 	if (pb->automatic) | ||||||
|  | 		paste_num_automatic--; | ||||||
|  | 	pb->automatic = 0; | ||||||
|  |  | ||||||
|  | 	RB_INSERT(paste_name_tree, &paste_by_name, pb); | ||||||
|  |  | ||||||
|  | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Replace an item on the stack. Note that the caller is responsible for |  * Add or replace an item in the store. Note that the caller is responsible for | ||||||
|  * allocating data. |  * allocating data. | ||||||
|  */ |  */ | ||||||
| int | int | ||||||
| paste_replace(u_int idx, char *data, size_t size) | paste_set(char *data, size_t size, const char *name, char **cause) | ||||||
| { | { | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer	*pb; | ||||||
|  |  | ||||||
|  | 	if (cause != NULL) | ||||||
|  | 		*cause = NULL; | ||||||
|  |  | ||||||
| 	if (size == 0) { | 	if (size == 0) { | ||||||
| 		free(data); | 		free(data); | ||||||
| 		return (0); | 		return (0); | ||||||
| 	} | 	} | ||||||
|  | 	if (name == NULL) { | ||||||
|  | 		paste_add(data, size); | ||||||
|  | 		return (0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (idx >= ARRAY_LENGTH(&paste_buffers)) | 	if (*name == '\0') { | ||||||
|  | 		if (cause != NULL) | ||||||
|  | 			*cause = xstrdup("empty buffer name"); | ||||||
| 		return (-1); | 		return (-1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	pb = ARRAY_ITEM(&paste_buffers, idx); | 	pb = paste_get_name(name); | ||||||
| 	free(pb->data); | 	if (pb != NULL) | ||||||
|  | 		paste_free_name(name); | ||||||
|  |  | ||||||
|  | 	pb = xmalloc(sizeof *pb); | ||||||
|  |  | ||||||
|  | 	pb->name = xstrdup(name); | ||||||
|  |  | ||||||
| 	pb->data = data; | 	pb->data = data; | ||||||
| 	pb->size = size; | 	pb->size = size; | ||||||
|  |  | ||||||
|  | 	pb->automatic = 0; | ||||||
|  | 	pb->order = paste_next_order++; | ||||||
|  |  | ||||||
|  | 	RB_INSERT(paste_name_tree, &paste_by_name, pb); | ||||||
|  | 	RB_INSERT(paste_time_tree, &paste_by_time, pb); | ||||||
|  |  | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								session.c
									
									
									
									
									
								
							| @@ -84,11 +84,12 @@ session_find_by_id(u_int id) | |||||||
|  |  | ||||||
| /* Create a new session. */ | /* Create a new session. */ | ||||||
| struct session * | struct session * | ||||||
| session_create(const char *name, const char *cmd, const char *path, int cwd, | session_create(const char *name, int argc, char **argv, const char *path, | ||||||
|     struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy, |     int cwd, struct environ *env, struct termios *tio, int idx, u_int sx, | ||||||
|     char **cause) |     u_int sy, char **cause) | ||||||
| { | { | ||||||
| 	struct session	*s; | 	struct session	*s; | ||||||
|  | 	struct winlink	*wl; | ||||||
|  |  | ||||||
| 	s = xmalloc(sizeof *s); | 	s = xmalloc(sizeof *s); | ||||||
| 	s->references = 0; | 	s->references = 0; | ||||||
| @@ -131,8 +132,9 @@ session_create(const char *name, const char *cmd, const char *path, int cwd, | |||||||
| 	} | 	} | ||||||
| 	RB_INSERT(sessions, &sessions, s); | 	RB_INSERT(sessions, &sessions, s); | ||||||
|  |  | ||||||
| 	if (cmd != NULL) { | 	if (argc >= 0) { | ||||||
| 		if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) { | 		wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause); | ||||||
|  | 		if (wl == NULL) { | ||||||
| 			session_destroy(s); | 			session_destroy(s); | ||||||
| 			return (NULL); | 			return (NULL); | ||||||
| 		} | 		} | ||||||
| @@ -226,7 +228,7 @@ session_previous_session(struct session *s) | |||||||
|  |  | ||||||
| /* Create a new window on a session. */ | /* Create a new window on a session. */ | ||||||
| struct winlink * | struct winlink * | ||||||
| session_new(struct session *s, const char *name, const char *cmd, | session_new(struct session *s, const char *name, int argc, char **argv, | ||||||
|     const char *path, int cwd, int idx, char **cause) |     const char *path, int cwd, int idx, char **cause) | ||||||
| { | { | ||||||
| 	struct window	*w; | 	struct window	*w; | ||||||
| @@ -250,8 +252,8 @@ session_new(struct session *s, const char *name, const char *cmd, | |||||||
| 		shell = _PATH_BSHELL; | 		shell = _PATH_BSHELL; | ||||||
|  |  | ||||||
| 	hlimit = options_get_number(&s->options, "history-limit"); | 	hlimit = options_get_number(&s->options, "history-limit"); | ||||||
| 	w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx, | 	w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio, | ||||||
| 	    s->sy, hlimit, cause); | 	    s->sx, s->sy, hlimit, cause); | ||||||
| 	if (w == NULL) { | 	if (w == NULL) { | ||||||
| 		winlink_remove(&s->windows, wl); | 		winlink_remove(&s->windows, wl); | ||||||
| 		environ_free(&env); | 		environ_free(&env); | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								style.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								style.c
									
									
									
									
									
								
							| @@ -117,7 +117,7 @@ style_tostring(struct grid_cell *gc) | |||||||
|  |  | ||||||
| 	*s = '\0'; | 	*s = '\0'; | ||||||
|  |  | ||||||
| 	if (gc->fg != 8) { | 	if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) { | ||||||
| 		if (gc->flags & GRID_FLAG_FG256) | 		if (gc->flags & GRID_FLAG_FG256) | ||||||
| 			c = gc->fg | 0x100; | 			c = gc->fg | 0x100; | ||||||
| 		else | 		else | ||||||
| @@ -126,7 +126,7 @@ style_tostring(struct grid_cell *gc) | |||||||
| 		comma = 1; | 		comma = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (gc->bg != 8) { | 	if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) { | ||||||
| 		if (gc->flags & GRID_FLAG_BG256) | 		if (gc->flags & GRID_FLAG_BG256) | ||||||
| 			c = gc->bg | 0x100; | 			c = gc->bg | 0x100; | ||||||
| 		else | 		else | ||||||
| @@ -221,13 +221,13 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name) | |||||||
| 	struct grid_cell	*gcp; | 	struct grid_cell	*gcp; | ||||||
|  |  | ||||||
| 	gcp = options_get_style(oo, name); | 	gcp = options_get_style(oo, name); | ||||||
| 	if (gcp->fg != 8) { | 	if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) { | ||||||
| 		if (gcp->flags & GRID_FLAG_FG256) | 		if (gcp->flags & GRID_FLAG_FG256) | ||||||
| 			colour_set_fg(gc, gcp->fg | 0x100); | 			colour_set_fg(gc, gcp->fg | 0x100); | ||||||
| 		else | 		else | ||||||
| 			colour_set_fg(gc, gcp->fg); | 			colour_set_fg(gc, gcp->fg); | ||||||
| 	} | 	} | ||||||
| 	if (gcp->bg != 8) { | 	if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) { | ||||||
| 		if (gcp->flags & GRID_FLAG_BG256) | 		if (gcp->flags & GRID_FLAG_BG256) | ||||||
| 			colour_set_bg(gc, gcp->bg | 0x100); | 			colour_set_bg(gc, gcp->bg | 0x100); | ||||||
| 		else | 		else | ||||||
|   | |||||||
							
								
								
									
										93
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -482,12 +482,37 @@ It may be used alone to target a pane or the window containing it. | |||||||
| arguments are | arguments are | ||||||
| .Xr sh 1 | .Xr sh 1 | ||||||
| commands. | commands. | ||||||
| These must be passed as a single item, which typically means quoting them, for | This may be a single argument passed to the shell, for example: | ||||||
| example: |  | ||||||
| .Bd -literal -offset indent | .Bd -literal -offset indent | ||||||
| new-window 'vi /etc/passwd' | new-window 'vi /etc/passwd' | ||||||
| .Ed | .Ed | ||||||
| .Pp | .Pp | ||||||
|  | Will run: | ||||||
|  | .Bd -literal -offset indent | ||||||
|  | /bin/sh -c 'vi /etc/passwd' | ||||||
|  | .Ed | ||||||
|  | .Pp | ||||||
|  | Additionally, the | ||||||
|  | .Ic new-window , | ||||||
|  | .Ic new-session , | ||||||
|  | .Ic split-window , | ||||||
|  | .Ic respawn-window | ||||||
|  | and | ||||||
|  | .Ic respawn-pane | ||||||
|  | commands allow | ||||||
|  | .Ar shell-command | ||||||
|  | to be given as multiple arguments and executed directly (without | ||||||
|  | .Ql sh -c ) . | ||||||
|  | This can avoid issues with shell quoting. | ||||||
|  | For example: | ||||||
|  | .Bd -literal -offset indent | ||||||
|  | $ tmux new-window vi /etc/passwd | ||||||
|  | .Ed | ||||||
|  | .Pp | ||||||
|  | Will run | ||||||
|  | .Xr vi 1 | ||||||
|  | directly without invoking the shell. | ||||||
|  | .Pp | ||||||
| .Ar command | .Ar command | ||||||
| .Op Ar arguments | .Op Ar arguments | ||||||
| refers to a | refers to a | ||||||
| @@ -853,6 +878,7 @@ The following keys are supported as appropriate for the mode: | |||||||
| .It Sy "Function" Ta Sy "vi" Ta Sy "emacs" | .It Sy "Function" Ta Sy "vi" Ta Sy "emacs" | ||||||
| .It Li "Append selection" Ta "A" Ta "" | .It Li "Append selection" Ta "A" Ta "" | ||||||
| .It Li "Back to indentation" Ta "^" Ta "M-m" | .It Li "Back to indentation" Ta "^" Ta "M-m" | ||||||
|  | .It Li "Copy to named buffer" Ta \&" Ta "" | ||||||
| .It Li "Bottom of history" Ta "G" Ta "M-<" | .It Li "Bottom of history" Ta "G" Ta "M-<" | ||||||
| .It Li "Clear selection" Ta "Escape" Ta "C-g" | .It Li "Clear selection" Ta "Escape" Ta "C-g" | ||||||
| .It Li "Copy selection" Ta "Enter" Ta "M-w" | .It Li "Copy selection" Ta "Enter" Ta "M-w" | ||||||
| @@ -934,9 +960,6 @@ in emacs mode, and | |||||||
| .Ql 10w | .Ql 10w | ||||||
| in vi. | in vi. | ||||||
| .Pp | .Pp | ||||||
| When copying the selection, the repeat count indicates the buffer index to |  | ||||||
| replace, if used. |  | ||||||
| .Pp |  | ||||||
| Mode key bindings are defined in a set of named tables: | Mode key bindings are defined in a set of named tables: | ||||||
| .Em vi-edit | .Em vi-edit | ||||||
| and | and | ||||||
| @@ -1094,7 +1117,7 @@ but a different format may be specified with | |||||||
| .Fl F . | .Fl F . | ||||||
| .It Xo Ic capture-pane | .It Xo Ic capture-pane | ||||||
| .Op Fl aepPq | .Op Fl aepPq | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
| .Op Fl E Ar end-line | .Op Fl E Ar end-line | ||||||
| .Op Fl S Ar start-line | .Op Fl S Ar start-line | ||||||
| .Op Fl t Ar target-pane | .Op Fl t Ar target-pane | ||||||
| @@ -3371,19 +3394,40 @@ is given, otherwise the active pane for the session attached to | |||||||
| .El | .El | ||||||
| .Sh BUFFERS | .Sh BUFFERS | ||||||
| .Nm | .Nm | ||||||
| maintains a stack of | maintains a set of named | ||||||
| .Em paste buffers . | .Em paste buffers . | ||||||
| Up to the value of the | Each buffer may be either explicitly or automatically named. | ||||||
|  | Explicitly named buffers are named when created with the | ||||||
|  | .Ic set-buffer | ||||||
|  | or | ||||||
|  | .Ic load-buffer | ||||||
|  | commands, or by renaming an automatically named buffer with | ||||||
|  | .Ic set-buffer | ||||||
|  | .Fl n . | ||||||
|  | Automatically named buffers are given a name such as | ||||||
|  | .Ql buffer0001 , | ||||||
|  | .Ql buffer0002 | ||||||
|  | and so on. | ||||||
|  | When the | ||||||
| .Ic buffer-limit | .Ic buffer-limit | ||||||
| option are kept; when a new buffer is added, the buffer at the bottom of the | option is reached, the oldest automatically named buffer is deleted. | ||||||
| stack is removed. | Explicitly named are not subject to | ||||||
|  | .Ic buffer-limit | ||||||
|  | and may be deleted with | ||||||
|  | .Ic delete-buffer | ||||||
|  | command. | ||||||
|  | .Pp | ||||||
| Buffers may be added using | Buffers may be added using | ||||||
| .Ic copy-mode | .Ic copy-mode | ||||||
| or the | or the | ||||||
| .Ic set-buffer | .Ic set-buffer | ||||||
| command, and pasted into a window using the | and | ||||||
|  | .Ic load-buffer | ||||||
|  | commands, and pasted into a window using the | ||||||
| .Ic paste-buffer | .Ic paste-buffer | ||||||
| command. | command. | ||||||
|  | If a buffer command is used and no buffer is specified, the most | ||||||
|  | recently added automatically named buffer is assumed. | ||||||
| .Pp | .Pp | ||||||
| A configurable history buffer is also maintained for each window. | A configurable history buffer is also maintained for each window. | ||||||
| By default, up to 2000 lines are kept; this can be altered with the | By default, up to 2000 lines are kept; this can be altered with the | ||||||
| @@ -3404,7 +3448,7 @@ Put a window into buffer choice mode, where a buffer may be chosen | |||||||
| interactively from a list. | interactively from a list. | ||||||
| After a buffer is selected, | After a buffer is selected, | ||||||
| .Ql %% | .Ql %% | ||||||
| is replaced by the buffer index in | is replaced by the buffer name in | ||||||
| .Ar template | .Ar template | ||||||
| and the result executed as a command. | and the result executed as a command. | ||||||
| If | If | ||||||
| @@ -3419,11 +3463,11 @@ This command works only if at least one client is attached. | |||||||
| .It Ic clear-history Op Fl t Ar target-pane | .It Ic clear-history Op Fl t Ar target-pane | ||||||
| .D1 (alias: Ic clearhist ) | .D1 (alias: Ic clearhist ) | ||||||
| Remove and free the history for the specified pane. | Remove and free the history for the specified pane. | ||||||
| .It Ic delete-buffer Op Fl b Ar buffer-index | .It Ic delete-buffer Op Fl b Ar buffer-name | ||||||
| .D1 (alias: Ic deleteb ) | .D1 (alias: Ic deleteb ) | ||||||
| Delete the buffer at | Delete the buffer named | ||||||
| .Ar buffer-index , | .Ar buffer-name , | ||||||
| or the top buffer if not specified. | or the most recently added automatically named buffer if not specified. | ||||||
| .It Xo Ic list-buffers | .It Xo Ic list-buffers | ||||||
| .Op Fl F Ar format | .Op Fl F Ar format | ||||||
| .Xc | .Xc | ||||||
| @@ -3435,7 +3479,7 @@ flag, see the | |||||||
| .Sx FORMATS | .Sx FORMATS | ||||||
| section. | section. | ||||||
| .It Xo Ic load-buffer | .It Xo Ic load-buffer | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
| .Ar path | .Ar path | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic loadb ) | .D1 (alias: Ic loadb ) | ||||||
| @@ -3443,7 +3487,7 @@ Load the contents of the specified paste buffer from | |||||||
| .Ar path . | .Ar path . | ||||||
| .It Xo Ic paste-buffer | .It Xo Ic paste-buffer | ||||||
| .Op Fl dpr | .Op Fl dpr | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
| .Op Fl s Ar separator | .Op Fl s Ar separator | ||||||
| .Op Fl t Ar target-pane | .Op Fl t Ar target-pane | ||||||
| .Xc | .Xc | ||||||
| @@ -3452,7 +3496,7 @@ Insert the contents of a paste buffer into the specified pane. | |||||||
| If not specified, paste into the current one. | If not specified, paste into the current one. | ||||||
| With | With | ||||||
| .Fl d , | .Fl d , | ||||||
| also delete the paste buffer from the stack. | also delete the paste buffer. | ||||||
| When output, any linefeed (LF) characters in the paste buffer are replaced with | When output, any linefeed (LF) characters in the paste buffer are replaced with | ||||||
| a separator, by default carriage return (CR). | a separator, by default carriage return (CR). | ||||||
| A custom separator may be specified using the | A custom separator may be specified using the | ||||||
| @@ -3467,7 +3511,7 @@ is specified, paste bracket control codes are inserted around the | |||||||
| buffer if the application has requested bracketed paste mode. | buffer if the application has requested bracketed paste mode. | ||||||
| .It Xo Ic save-buffer | .It Xo Ic save-buffer | ||||||
| .Op Fl a | .Op Fl a | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
| .Ar path | .Ar path | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic saveb ) | .D1 (alias: Ic saveb ) | ||||||
| @@ -3478,7 +3522,8 @@ The | |||||||
| option appends to rather than overwriting the file. | option appends to rather than overwriting the file. | ||||||
| .It Xo Ic set-buffer | .It Xo Ic set-buffer | ||||||
| .Op Fl a | .Op Fl a | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
|  | .Op Fl n Ar new-buffer-name | ||||||
| .Ar data | .Ar data | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic setb ) | .D1 (alias: Ic setb ) | ||||||
| @@ -3487,8 +3532,12 @@ Set the contents of the specified buffer to | |||||||
| The | The | ||||||
| .Fl a | .Fl a | ||||||
| option appends to rather than overwriting the buffer. | option appends to rather than overwriting the buffer. | ||||||
|  | The | ||||||
|  | .Fl n | ||||||
|  | option renames the buffer to | ||||||
|  | .Ar new-buffer-name . | ||||||
| .It Xo Ic show-buffer | .It Xo Ic show-buffer | ||||||
| .Op Fl b Ar buffer-index | .Op Fl b Ar buffer-name | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic showb ) | .D1 (alias: Ic showb ) | ||||||
| Display the contents of the specified buffer. | Display the contents of the specified buffer. | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -82,7 +82,7 @@ extern char   **environ; | |||||||
|  |  | ||||||
| /* Default template for choose-buffer. */ | /* Default template for choose-buffer. */ | ||||||
| #define CHOOSE_BUFFER_TEMPLATE					\ | #define CHOOSE_BUFFER_TEMPLATE					\ | ||||||
| 	"#{line}: #{buffer_size} bytes: #{buffer_sample}" | 	"#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}" | ||||||
|  |  | ||||||
| /* Default template for choose-client. */ | /* Default template for choose-client. */ | ||||||
| #define CHOOSE_CLIENT_TEMPLATE					\ | #define CHOOSE_CLIENT_TEMPLATE					\ | ||||||
| @@ -115,7 +115,8 @@ extern char   **environ; | |||||||
|  |  | ||||||
| /* Default template for list-buffers. */ | /* Default template for list-buffers. */ | ||||||
| #define LIST_BUFFERS_TEMPLATE					\ | #define LIST_BUFFERS_TEMPLATE					\ | ||||||
| 	"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\"" | 	"#{buffer_name}: #{buffer_size} bytes: "		\ | ||||||
|  | 	"\"#{buffer_sample}\"" | ||||||
|  |  | ||||||
| /* Default template for list-clients. */ | /* Default template for list-clients. */ | ||||||
| #define LIST_CLIENTS_TEMPLATE					\ | #define LIST_CLIENTS_TEMPLATE					\ | ||||||
| @@ -579,6 +580,7 @@ enum mode_key_cmd { | |||||||
| 	MODEKEYCOPY_SEARCHREVERSE, | 	MODEKEYCOPY_SEARCHREVERSE, | ||||||
| 	MODEKEYCOPY_SEARCHUP, | 	MODEKEYCOPY_SEARCHUP, | ||||||
| 	MODEKEYCOPY_SELECTLINE, | 	MODEKEYCOPY_SELECTLINE, | ||||||
|  | 	MODEKEYCOPY_STARTNAMEDBUFFER, | ||||||
| 	MODEKEYCOPY_STARTNUMBERPREFIX, | 	MODEKEYCOPY_STARTNUMBERPREFIX, | ||||||
| 	MODEKEYCOPY_STARTOFLINE, | 	MODEKEYCOPY_STARTOFLINE, | ||||||
| 	MODEKEYCOPY_STARTSELECTION, | 	MODEKEYCOPY_STARTSELECTION, | ||||||
| @@ -889,6 +891,7 @@ struct window_choose_mode_item { | |||||||
| /* Child window structure. */ | /* Child window structure. */ | ||||||
| struct window_pane { | struct window_pane { | ||||||
| 	u_int		 id; | 	u_int		 id; | ||||||
|  | 	u_int		 active_point; | ||||||
|  |  | ||||||
| 	struct window	*window; | 	struct window	*window; | ||||||
|  |  | ||||||
| @@ -908,7 +911,8 @@ struct window_pane { | |||||||
| #define PANE_RESIZE 0x8 | #define PANE_RESIZE 0x8 | ||||||
| #define PANE_FOCUSPUSH 0x10 | #define PANE_FOCUSPUSH 0x10 | ||||||
|  |  | ||||||
| 	char		*cmd; | 	int		 argc; | ||||||
|  | 	char	       **argv; | ||||||
| 	char		*shell; | 	char		*shell; | ||||||
| 	int		 cwd; | 	int		 cwd; | ||||||
|  |  | ||||||
| @@ -945,6 +949,7 @@ struct window_pane { | |||||||
| }; | }; | ||||||
| TAILQ_HEAD(window_panes, window_pane); | TAILQ_HEAD(window_panes, window_pane); | ||||||
| RB_HEAD(window_pane_tree, window_pane); | RB_HEAD(window_pane_tree, window_pane); | ||||||
|  | ARRAY_DECL(window_pane_list, struct window_pane *); | ||||||
|  |  | ||||||
| /* Window structure. */ | /* Window structure. */ | ||||||
| struct window { | struct window { | ||||||
| @@ -1022,8 +1027,6 @@ struct layout_cell { | |||||||
| 	u_int		 yoff; | 	u_int		 yoff; | ||||||
|  |  | ||||||
| 	struct window_pane *wp; | 	struct window_pane *wp; | ||||||
| 	struct window_pane *lastwp; |  | ||||||
|  |  | ||||||
| 	struct layout_cells cells; | 	struct layout_cells cells; | ||||||
|  |  | ||||||
| 	TAILQ_ENTRY(layout_cell) entry; | 	TAILQ_ENTRY(layout_cell) entry; | ||||||
| @@ -1033,6 +1036,13 @@ struct layout_cell { | |||||||
| struct paste_buffer { | struct paste_buffer { | ||||||
| 	char		*data; | 	char		*data; | ||||||
| 	size_t		 size; | 	size_t		 size; | ||||||
|  |  | ||||||
|  | 	char		*name; | ||||||
|  | 	int		 automatic; | ||||||
|  | 	u_int		 order; | ||||||
|  |  | ||||||
|  | 	RB_ENTRY(paste_buffer) name_entry; | ||||||
|  | 	RB_ENTRY(paste_buffer) time_entry; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Environment variable. */ | /* Environment variable. */ | ||||||
| @@ -1127,6 +1137,9 @@ LIST_HEAD(tty_terms, tty_term); | |||||||
| #define MOUSE_WHEEL_UP 0 | #define MOUSE_WHEEL_UP 0 | ||||||
| #define MOUSE_WHEEL_DOWN 1 | #define MOUSE_WHEEL_DOWN 1 | ||||||
|  |  | ||||||
|  | /* Mouse wheel multipler. */ | ||||||
|  | #define MOUSE_WHEEL_SCALE 3 | ||||||
|  |  | ||||||
| /* Mouse event bits. */ | /* Mouse event bits. */ | ||||||
| #define MOUSE_EVENT_DOWN 0x1 | #define MOUSE_EVENT_DOWN 0x1 | ||||||
| #define MOUSE_EVENT_DRAG 0x2 | #define MOUSE_EVENT_DRAG 0x2 | ||||||
| @@ -1493,7 +1506,7 @@ RB_HEAD(format_tree, format_entry); | |||||||
| #define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]" | #define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]" | ||||||
| #define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]" | #define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]" | ||||||
| #define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]" | #define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]" | ||||||
| #define CMD_BUFFER_USAGE "[-b buffer-index]" | #define CMD_BUFFER_USAGE "[-b buffer-name]" | ||||||
|  |  | ||||||
| /* tmux.c */ | /* tmux.c */ | ||||||
| extern struct options global_options; | extern struct options global_options; | ||||||
| @@ -1705,13 +1718,14 @@ void	tty_keys_free(struct tty *); | |||||||
| int	tty_keys_next(struct tty *); | int	tty_keys_next(struct tty *); | ||||||
|  |  | ||||||
| /* paste.c */ | /* paste.c */ | ||||||
| struct paste_buffer *paste_walk_stack(u_int *); | struct paste_buffer *paste_walk(struct paste_buffer *); | ||||||
| struct paste_buffer *paste_get_top(void); | struct paste_buffer *paste_get_top(void); | ||||||
| struct paste_buffer *paste_get_index(u_int); | struct paste_buffer *paste_get_name(const char *); | ||||||
| int		 paste_free_top(void); | int		 paste_free_top(void); | ||||||
| int		 paste_free_index(u_int); | int		 paste_free_name(const char *); | ||||||
| void		 paste_add(char *, size_t, u_int); | void		 paste_add(char *, size_t); | ||||||
| int		 paste_replace(u_int, char *, size_t); | int		 paste_rename(const char *, const char *, char **); | ||||||
|  | int		 paste_set(char *, size_t, const char *, char **); | ||||||
| char		*paste_make_sample(struct paste_buffer *, int); | char		*paste_make_sample(struct paste_buffer *, int); | ||||||
| void		 paste_send_pane(struct paste_buffer *, struct window_pane *, | void		 paste_send_pane(struct paste_buffer *, struct window_pane *, | ||||||
| 		     const char *, int); | 		     const char *, int); | ||||||
| @@ -1732,8 +1746,9 @@ long long	 args_strtonum( | |||||||
| /* cmd.c */ | /* cmd.c */ | ||||||
| int		 cmd_pack_argv(int, char **, char *, size_t); | int		 cmd_pack_argv(int, char **, char *, size_t); | ||||||
| int		 cmd_unpack_argv(char *, size_t, int, char ***); | int		 cmd_unpack_argv(char *, size_t, int, char ***); | ||||||
| char	       **cmd_copy_argv(int, char *const *); | char	       **cmd_copy_argv(int, char **); | ||||||
| void		 cmd_free_argv(int, char **); | void		 cmd_free_argv(int, char **); | ||||||
|  | char		*cmd_stringify_argv(int, char **); | ||||||
| struct cmd	*cmd_parse(int, char **, const char *, u_int, char **); | struct cmd	*cmd_parse(int, char **, const char *, u_int, char **); | ||||||
| size_t		 cmd_print(struct cmd *, char *, size_t); | size_t		 cmd_print(struct cmd *, char *, size_t); | ||||||
| struct session	*cmd_current_session(struct cmd_q *, int); | struct session	*cmd_current_session(struct cmd_q *, int); | ||||||
| @@ -2124,7 +2139,7 @@ void		 winlink_stack_remove(struct winlink_stack *, struct winlink *); | |||||||
| int		 window_index(struct window *, u_int *); | int		 window_index(struct window *, u_int *); | ||||||
| struct window	*window_find_by_id(u_int); | struct window	*window_find_by_id(u_int); | ||||||
| struct window	*window_create1(u_int, u_int); | struct window	*window_create1(u_int, u_int); | ||||||
| struct window	*window_create(const char *, const char *, const char *, | struct window	*window_create(const char *, int, char **, const char *, | ||||||
| 		     const char *, int, struct environ *, struct termios *, | 		     const char *, int, struct environ *, struct termios *, | ||||||
| 		     u_int, u_int, u_int, char **); | 		     u_int, u_int, u_int, char **); | ||||||
| void		 window_destroy(struct window *); | void		 window_destroy(struct window *); | ||||||
| @@ -2150,7 +2165,7 @@ struct window_pane *window_pane_find_by_id(u_int); | |||||||
| struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); | struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); | ||||||
| void		 window_pane_destroy(struct window_pane *); | void		 window_pane_destroy(struct window_pane *); | ||||||
| void		 window_pane_timer_start(struct window_pane *); | void		 window_pane_timer_start(struct window_pane *); | ||||||
| int		 window_pane_spawn(struct window_pane *, const char *, | int		 window_pane_spawn(struct window_pane *, int, char **, | ||||||
| 		     const char *, const char *, int, struct environ *, | 		     const char *, const char *, int, struct environ *, | ||||||
| 		     struct termios *, char **); | 		     struct termios *, char **); | ||||||
| void		 window_pane_resize(struct window_pane *, u_int, u_int); | void		 window_pane_resize(struct window_pane *, u_int, u_int); | ||||||
| @@ -2288,18 +2303,18 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp); | |||||||
| int		 session_alive(struct session *); | int		 session_alive(struct session *); | ||||||
| struct session	*session_find(const char *); | struct session	*session_find(const char *); | ||||||
| struct session	*session_find_by_id(u_int); | struct session	*session_find_by_id(u_int); | ||||||
| struct session	*session_create(const char *, const char *, const char *, int, | struct session	*session_create(const char *, int, char **, const char *, | ||||||
| 		     struct environ *, struct termios *, int, u_int, u_int, | 		     int, struct environ *, struct termios *, int, u_int, | ||||||
| 		     char **); | 		     u_int, char **); | ||||||
| void		 session_destroy(struct session *); | void		 session_destroy(struct session *); | ||||||
| int		 session_check_name(const char *); | int		 session_check_name(const char *); | ||||||
| void		 session_update_activity(struct session *); | void		 session_update_activity(struct session *); | ||||||
| struct session	*session_next_session(struct session *); | struct session	*session_next_session(struct session *); | ||||||
| struct session	*session_previous_session(struct session *); | struct session	*session_previous_session(struct session *); | ||||||
| struct winlink	*session_new(struct session *, const char *, const char *, | struct winlink	*session_new(struct session *, const char *, int, char **, | ||||||
| 		     const char *, int, int, char **); | 		     const char *, int, int, char **); | ||||||
| struct winlink	*session_attach( | struct winlink	*session_attach(struct session *, struct window *, int, | ||||||
| 		     struct session *, struct window *, int, char **); | 		     char **); | ||||||
| int		 session_detach(struct session *, struct winlink *); | int		 session_detach(struct session *, struct winlink *); | ||||||
| struct winlink	*session_has(struct session *, struct window *); | struct winlink	*session_has(struct session *, struct window *); | ||||||
| int		 session_next(struct session *, int); | int		 session_next(struct session *, int); | ||||||
|   | |||||||
| @@ -752,11 +752,11 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) | |||||||
| 		if (b & MOUSE_MASK_SHIFT) | 		if (b & MOUSE_MASK_SHIFT) | ||||||
| 			m->scroll = 1; | 			m->scroll = 1; | ||||||
| 		else | 		else | ||||||
| 			m->scroll = 3; | 			m->scroll = MOUSE_WHEEL_SCALE; | ||||||
| 		if (b & MOUSE_MASK_META) | 		if (b & MOUSE_MASK_META) | ||||||
| 			m->scroll *= 3; | 			m->scroll *= MOUSE_WHEEL_SCALE; | ||||||
| 		if (b & MOUSE_MASK_CTRL) | 		if (b & MOUSE_MASK_CTRL) | ||||||
| 			m->scroll *= 3; | 			m->scroll *= MOUSE_WHEEL_SCALE; | ||||||
|  |  | ||||||
| 		b &= MOUSE_MASK_BUTTONS; | 		b &= MOUSE_MASK_BUTTONS; | ||||||
| 		if (b == 0) | 		if (b == 0) | ||||||
|   | |||||||
| @@ -721,17 +721,22 @@ window_choose_mouse(struct window_pane *wp, struct session *sess, | |||||||
| 	struct window_choose_mode_data	*data = wp->modedata; | 	struct window_choose_mode_data	*data = wp->modedata; | ||||||
| 	struct screen			*s = &data->screen; | 	struct screen			*s = &data->screen; | ||||||
| 	struct window_choose_mode_item	*item; | 	struct window_choose_mode_item	*item; | ||||||
| 	u_int				 idx; | 	u_int				 idx, i, n; | ||||||
|  |  | ||||||
| 	if (m->event == MOUSE_EVENT_WHEEL) { | 	if (m->event == MOUSE_EVENT_WHEEL) { | ||||||
| 		/* | 		/* | ||||||
| 		 * Don't use m->scroll and just move line-by-line or it's | 		 * Multiple line scrolling by default is annoying, so scale | ||||||
| 		 * annoying. | 		 * m->scroll back down. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (m->wheel == MOUSE_WHEEL_UP) | 		n = m->scroll; | ||||||
| 			window_choose_key(wp, sess, KEYC_UP); | 		if (n >= MOUSE_WHEEL_SCALE) | ||||||
| 		else | 			n /= MOUSE_WHEEL_SCALE; | ||||||
| 			window_choose_key(wp, sess, KEYC_DOWN); | 		for (i = 0; i < n; i++) { | ||||||
|  | 			if (m->wheel == MOUSE_WHEEL_UP) | ||||||
|  | 				window_choose_key(wp, sess, KEYC_UP); | ||||||
|  | 			else | ||||||
|  | 				window_choose_key(wp, sess, KEYC_DOWN); | ||||||
|  | 		} | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,14 +54,15 @@ void	window_copy_update_cursor(struct window_pane *, u_int, u_int); | |||||||
| void	window_copy_start_selection(struct window_pane *); | void	window_copy_start_selection(struct window_pane *); | ||||||
| int	window_copy_update_selection(struct window_pane *, int); | int	window_copy_update_selection(struct window_pane *, int); | ||||||
| void   *window_copy_get_selection(struct window_pane *, size_t *); | void   *window_copy_get_selection(struct window_pane *, size_t *); | ||||||
| void	window_copy_copy_buffer(struct window_pane *, int, void *, size_t); | void	window_copy_copy_buffer(struct window_pane *, const char *, void *, | ||||||
| void	window_copy_copy_pipe( | 	    size_t); | ||||||
| 	    struct window_pane *, struct session *, int, const char *); | void	window_copy_copy_pipe(struct window_pane *, struct session *, | ||||||
| void	window_copy_copy_selection(struct window_pane *, int); | 	    const char *, const char *); | ||||||
| void	window_copy_append_selection(struct window_pane *, int); | void	window_copy_copy_selection(struct window_pane *, const char *); | ||||||
|  | void	window_copy_append_selection(struct window_pane *, const char *); | ||||||
| void	window_copy_clear_selection(struct window_pane *); | void	window_copy_clear_selection(struct window_pane *); | ||||||
| void	window_copy_copy_line( | void	window_copy_copy_line(struct window_pane *, char **, size_t *, u_int, | ||||||
| 	    struct window_pane *, char **, size_t *, u_int, u_int, u_int); | 	    u_int, u_int); | ||||||
| int	window_copy_in_set(struct window_pane *, u_int, u_int, const char *); | int	window_copy_in_set(struct window_pane *, u_int, u_int, const char *); | ||||||
| u_int	window_copy_find_length(struct window_pane *, u_int); | u_int	window_copy_find_length(struct window_pane *, u_int); | ||||||
| void	window_copy_cursor_start_of_line(struct window_pane *); | void	window_copy_cursor_start_of_line(struct window_pane *); | ||||||
| @@ -94,6 +95,7 @@ const struct window_mode window_copy_mode = { | |||||||
|  |  | ||||||
| enum window_copy_input_type { | enum window_copy_input_type { | ||||||
| 	WINDOW_COPY_OFF, | 	WINDOW_COPY_OFF, | ||||||
|  | 	WINDOW_COPY_NAMEDBUFFER, | ||||||
| 	WINDOW_COPY_NUMERICPREFIX, | 	WINDOW_COPY_NUMERICPREFIX, | ||||||
| 	WINDOW_COPY_SEARCHUP, | 	WINDOW_COPY_SEARCHUP, | ||||||
| 	WINDOW_COPY_SEARCHDOWN, | 	WINDOW_COPY_SEARCHDOWN, | ||||||
| @@ -417,7 +419,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) | |||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 	case MODEKEYCOPY_APPENDSELECTION: | 	case MODEKEYCOPY_APPENDSELECTION: | ||||||
| 		if (sess != NULL) { | 		if (sess != NULL) { | ||||||
| 			window_copy_append_selection(wp, data->numprefix); | 			window_copy_append_selection(wp, NULL); | ||||||
| 			window_pane_reset_mode(wp); | 			window_pane_reset_mode(wp); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| @@ -543,7 +545,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) | |||||||
| 		if (sess != NULL && | 		if (sess != NULL && | ||||||
| 		    (cmd == MODEKEYCOPY_COPYLINE || | 		    (cmd == MODEKEYCOPY_COPYLINE || | ||||||
| 		    cmd == MODEKEYCOPY_COPYENDOFLINE)) { | 		    cmd == MODEKEYCOPY_COPYENDOFLINE)) { | ||||||
| 			window_copy_copy_selection(wp, -1); | 			window_copy_copy_selection(wp, NULL); | ||||||
| 			window_pane_reset_mode(wp); | 			window_pane_reset_mode(wp); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| @@ -554,14 +556,14 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) | |||||||
| 		break; | 		break; | ||||||
| 	case MODEKEYCOPY_COPYPIPE: | 	case MODEKEYCOPY_COPYPIPE: | ||||||
| 		if (sess != NULL) { | 		if (sess != NULL) { | ||||||
| 			window_copy_copy_pipe(wp, sess, data->numprefix, arg); | 			window_copy_copy_pipe(wp, sess, NULL, arg); | ||||||
| 			window_pane_reset_mode(wp); | 			window_pane_reset_mode(wp); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case MODEKEYCOPY_COPYSELECTION: | 	case MODEKEYCOPY_COPYSELECTION: | ||||||
| 		if (sess != NULL) { | 		if (sess != NULL) { | ||||||
| 			window_copy_copy_selection(wp, data->numprefix); | 			window_copy_copy_selection(wp, NULL); | ||||||
| 			window_pane_reset_mode(wp); | 			window_pane_reset_mode(wp); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| @@ -676,6 +678,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) | |||||||
| 		case WINDOW_COPY_JUMPBACK: | 		case WINDOW_COPY_JUMPBACK: | ||||||
| 		case WINDOW_COPY_JUMPTOFORWARD: | 		case WINDOW_COPY_JUMPTOFORWARD: | ||||||
| 		case WINDOW_COPY_JUMPTOBACK: | 		case WINDOW_COPY_JUMPTOBACK: | ||||||
|  | 		case WINDOW_COPY_NAMEDBUFFER: | ||||||
| 		case WINDOW_COPY_NUMERICPREFIX: | 		case WINDOW_COPY_NUMERICPREFIX: | ||||||
| 			break; | 			break; | ||||||
| 		case WINDOW_COPY_SEARCHUP: | 		case WINDOW_COPY_SEARCHUP: | ||||||
| @@ -711,6 +714,11 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) | |||||||
| 		data->inputprompt = "Goto Line"; | 		data->inputprompt = "Goto Line"; | ||||||
| 		*data->inputstr = '\0'; | 		*data->inputstr = '\0'; | ||||||
| 		goto input_on; | 		goto input_on; | ||||||
|  | 	case MODEKEYCOPY_STARTNAMEDBUFFER: | ||||||
|  | 		data->inputtype = WINDOW_COPY_NAMEDBUFFER; | ||||||
|  | 		data->inputprompt = "Buffer"; | ||||||
|  | 		*data->inputstr = '\0'; | ||||||
|  | 		goto input_on; | ||||||
| 	case MODEKEYCOPY_STARTNUMBERPREFIX: | 	case MODEKEYCOPY_STARTNUMBERPREFIX: | ||||||
| 		key &= KEYC_MASK_KEY; | 		key &= KEYC_MASK_KEY; | ||||||
| 		if (key >= '0' && key <= '9') { | 		if (key >= '0' && key <= '9') { | ||||||
| @@ -814,6 +822,11 @@ window_copy_key_input(struct window_pane *wp, int key) | |||||||
| 			data->searchtype = data->inputtype; | 			data->searchtype = data->inputtype; | ||||||
| 			data->searchstr = xstrdup(data->inputstr); | 			data->searchstr = xstrdup(data->inputstr); | ||||||
| 			break; | 			break; | ||||||
|  | 		case WINDOW_COPY_NAMEDBUFFER: | ||||||
|  | 			window_copy_copy_selection(wp, data->inputstr); | ||||||
|  | 			*data->inputstr = '\0'; | ||||||
|  | 			window_pane_reset_mode(wp); | ||||||
|  | 			return (0); | ||||||
| 		case WINDOW_COPY_GOTOLINE: | 		case WINDOW_COPY_GOTOLINE: | ||||||
| 			window_copy_goto_line(wp, data->inputstr); | 			window_copy_goto_line(wp, data->inputstr); | ||||||
| 			*data->inputstr = '\0'; | 			*data->inputstr = '\0'; | ||||||
| @@ -918,7 +931,7 @@ reset_mode: | |||||||
| 	s->mode &= ~MODE_MOUSE_BUTTON; | 	s->mode &= ~MODE_MOUSE_BUTTON; | ||||||
| 	s->mode |= MODE_MOUSE_STANDARD; | 	s->mode |= MODE_MOUSE_STANDARD; | ||||||
| 	if (sess != NULL) { | 	if (sess != NULL) { | ||||||
| 		window_copy_copy_selection(wp, -1); | 		window_copy_copy_selection(wp, NULL); | ||||||
| 		window_pane_reset_mode(wp); | 		window_pane_reset_mode(wp); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -1452,9 +1465,9 @@ window_copy_get_selection(struct window_pane *wp, size_t *len) | |||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len) | window_copy_copy_buffer(struct window_pane *wp, const char *bufname, void *buf, | ||||||
|  |     size_t len) | ||||||
| { | { | ||||||
| 	u_int			limit; |  | ||||||
| 	struct screen_write_ctx	ctx; | 	struct screen_write_ctx	ctx; | ||||||
|  |  | ||||||
| 	if (options_get_number(&global_options, "set-clipboard")) { | 	if (options_get_number(&global_options, "set-clipboard")) { | ||||||
| @@ -1463,16 +1476,13 @@ window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len) | |||||||
| 		screen_write_stop(&ctx); | 		screen_write_stop(&ctx); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (idx == -1) { | 	if (paste_set(buf, len, bufname, NULL) != 0) | ||||||
| 		limit = options_get_number(&global_options, "buffer-limit"); |  | ||||||
| 		paste_add(buf, len, limit); |  | ||||||
| 	} else if (paste_replace(idx, buf, len) != 0) |  | ||||||
| 		free(buf); | 		free(buf); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| window_copy_copy_pipe( | window_copy_copy_pipe(struct window_pane *wp, struct session *sess, | ||||||
|     struct window_pane *wp, struct session *sess, int idx, const char *arg) |     const char *bufname, const char *arg) | ||||||
| { | { | ||||||
| 	void		*buf; | 	void		*buf; | ||||||
| 	size_t		 len; | 	size_t		 len; | ||||||
| @@ -1486,11 +1496,11 @@ window_copy_copy_pipe( | |||||||
| 	job = job_run(arg, sess, NULL, NULL, NULL); | 	job = job_run(arg, sess, NULL, NULL, NULL); | ||||||
| 	bufferevent_write(job->event, buf, len); | 	bufferevent_write(job->event, buf, len); | ||||||
|  |  | ||||||
| 	window_copy_copy_buffer(wp, idx, buf, len); | 	window_copy_copy_buffer(wp, bufname, buf, len); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| window_copy_copy_selection(struct window_pane *wp, int idx) | window_copy_copy_selection(struct window_pane *wp, const char *bufname) | ||||||
| { | { | ||||||
| 	void*	buf; | 	void*	buf; | ||||||
| 	size_t	len; | 	size_t	len; | ||||||
| @@ -1499,17 +1509,16 @@ window_copy_copy_selection(struct window_pane *wp, int idx) | |||||||
| 	if (buf == NULL) | 	if (buf == NULL) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	window_copy_copy_buffer(wp, idx, buf, len); | 	window_copy_copy_buffer(wp, bufname, buf, len); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| window_copy_append_selection(struct window_pane *wp, int idx) | window_copy_append_selection(struct window_pane *wp, const char *bufname) | ||||||
| { | { | ||||||
| 	char			*buf; | 	char				*buf; | ||||||
| 	struct paste_buffer	*pb; | 	struct paste_buffer		*pb; | ||||||
| 	size_t			 len; | 	size_t				 len; | ||||||
| 	u_int			 limit; | 	struct screen_write_ctx		 ctx; | ||||||
| 	struct screen_write_ctx	 ctx; |  | ||||||
|  |  | ||||||
| 	buf = window_copy_get_selection(wp, &len); | 	buf = window_copy_get_selection(wp, &len); | ||||||
| 	if (buf == NULL) | 	if (buf == NULL) | ||||||
| @@ -1521,24 +1530,19 @@ window_copy_append_selection(struct window_pane *wp, int idx) | |||||||
| 		screen_write_stop(&ctx); | 		screen_write_stop(&ctx); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (idx == -1) | 	if (bufname == NULL || *bufname == '\0') { | ||||||
| 		idx = 0; | 		pb = paste_get_top(); | ||||||
|  | 		if (pb != NULL) | ||||||
| 	if (idx == 0 && paste_get_top() == NULL) { | 			bufname = pb->name; | ||||||
| 		limit = options_get_number(&global_options, "buffer-limit"); | 	} else | ||||||
| 		paste_add(buf, len, limit); | 		pb = paste_get_name(bufname); | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	pb = paste_get_index(idx); |  | ||||||
| 	if (pb != NULL) { | 	if (pb != NULL) { | ||||||
| 		buf = xrealloc(buf, 1, len + pb->size); | 		buf = xrealloc(buf, 1, len + pb->size); | ||||||
| 		memmove(buf + pb->size, buf, len); | 		memmove(buf + pb->size, buf, len); | ||||||
| 		memcpy(buf, pb->data, pb->size); | 		memcpy(buf, pb->data, pb->size); | ||||||
| 		len += pb->size; | 		len += pb->size; | ||||||
| 	} | 	} | ||||||
|  | 	if (paste_set(buf, len, bufname, NULL) != 0) | ||||||
| 	if (paste_replace(idx, buf, len) != 0) |  | ||||||
| 		free(buf); | 		free(buf); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										327
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										327
									
								
								window.c
									
									
									
									
									
								
							| @@ -55,15 +55,14 @@ struct windows windows; | |||||||
| struct window_pane_tree all_window_panes; | struct window_pane_tree all_window_panes; | ||||||
| u_int	next_window_pane_id; | u_int	next_window_pane_id; | ||||||
| u_int	next_window_id; | u_int	next_window_id; | ||||||
|  | u_int	next_active_point; | ||||||
| struct window_pane *window_pane_active_set(struct window_pane *, |  | ||||||
| 	    struct window_pane *); |  | ||||||
| void	window_pane_active_lost(struct window_pane *, struct window_pane *); |  | ||||||
|  |  | ||||||
| void	window_pane_timer_callback(int, short, void *); | void	window_pane_timer_callback(int, short, void *); | ||||||
| void	window_pane_read_callback(struct bufferevent *, void *); | void	window_pane_read_callback(struct bufferevent *, void *); | ||||||
| void	window_pane_error_callback(struct bufferevent *, short, void *); | void	window_pane_error_callback(struct bufferevent *, short, void *); | ||||||
|  |  | ||||||
|  | struct window_pane *window_pane_choose_best(struct window_pane_list *); | ||||||
|  |  | ||||||
| RB_GENERATE(winlinks, winlink, entry, winlink_cmp); | RB_GENERATE(winlinks, winlink, entry, winlink_cmp); | ||||||
|  |  | ||||||
| int | int | ||||||
| @@ -307,7 +306,7 @@ window_create1(u_int sx, u_int sy) | |||||||
| } | } | ||||||
|  |  | ||||||
| struct window * | struct window * | ||||||
| window_create(const char *name, const char *cmd, const char *path, | window_create(const char *name, int argc, char **argv, const char *path, | ||||||
|     const char *shell, int cwd, struct environ *env, struct termios *tio, |     const char *shell, int cwd, struct environ *env, struct termios *tio, | ||||||
|     u_int sx, u_int sy, u_int hlimit, char **cause) |     u_int sx, u_int sy, u_int hlimit, char **cause) | ||||||
| { | { | ||||||
| @@ -318,7 +317,7 @@ window_create(const char *name, const char *cmd, const char *path, | |||||||
| 	wp = window_add_pane(w, hlimit); | 	wp = window_add_pane(w, hlimit); | ||||||
| 	layout_init(w, wp); | 	layout_init(w, wp); | ||||||
|  |  | ||||||
| 	if (window_pane_spawn(wp, cmd, path, shell, cwd, env, tio, | 	if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio, | ||||||
| 	    cause) != 0) { | 	    cause) != 0) { | ||||||
| 		window_destroy(w); | 		window_destroy(w); | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
| @@ -386,64 +385,6 @@ window_resize(struct window *w, u_int sx, u_int sy) | |||||||
| 	w->sy = sy; | 	w->sy = sy; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Restore previously active pane when changing from wp to nextwp. The intended |  | ||||||
|  * pane is in nextwp and it returns the previously focused pane. |  | ||||||
|  */ |  | ||||||
| struct window_pane * |  | ||||||
| window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp) |  | ||||||
| { |  | ||||||
| 	struct layout_cell	*lc; |  | ||||||
| 	struct window_pane	*lastwp; |  | ||||||
|  |  | ||||||
| 	/* Target pane's parent must not be an ancestor of source pane. */ |  | ||||||
| 	for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) { |  | ||||||
| 		if (lc == nextwp->layout_cell->parent) |  | ||||||
| 			return (nextwp); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Previously active pane, if any, must not be the same as the source |  | ||||||
| 	 * pane. |  | ||||||
| 	 */ |  | ||||||
| 	lc = nextwp->layout_cell->parent; |  | ||||||
| 	if (lc != NULL && lc->lastwp != NULL) { |  | ||||||
| 		lastwp = lc->lastwp; |  | ||||||
| 		if (lastwp != wp && window_pane_visible(lastwp)) |  | ||||||
| 			return (lastwp); |  | ||||||
| 	} |  | ||||||
| 	return (nextwp); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Remember previously active pane when changing from wp to nextwp. */ |  | ||||||
| void |  | ||||||
| window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp) |  | ||||||
| { |  | ||||||
| 	struct layout_cell	*lc, *lc2, *lcparent; |  | ||||||
|  |  | ||||||
| 	/* Get the parent cell. */ |  | ||||||
| 	lcparent = nextwp->layout_cell->parent; |  | ||||||
| 	if (lcparent == NULL) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	/* Save the target pane in its parent. */ |  | ||||||
| 	lcparent->lastwp = nextwp; |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Save the source pane in all of its parents up to, but not including, |  | ||||||
| 	 * the common ancestor of itself and the target panes. |  | ||||||
| 	 */ |  | ||||||
| 	if (wp == NULL) |  | ||||||
| 		return; |  | ||||||
| 	for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) { |  | ||||||
| 		for (lc2 = lcparent; lc2 != NULL; lc2 = lc2->parent) { |  | ||||||
| 			if (lc == lc2) |  | ||||||
| 				return; |  | ||||||
| 		} |  | ||||||
| 		lc->lastwp = wp; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void | void | ||||||
| window_set_active_pane(struct window *w, struct window_pane *wp) | window_set_active_pane(struct window *w, struct window_pane *wp) | ||||||
| { | { | ||||||
| @@ -451,7 +392,6 @@ window_set_active_pane(struct window *w, struct window_pane *wp) | |||||||
| 		return; | 		return; | ||||||
| 	w->last = w->active; | 	w->last = w->active; | ||||||
| 	w->active = wp; | 	w->active = wp; | ||||||
| 	window_pane_active_lost(w->last, wp); |  | ||||||
| 	while (!window_pane_visible(w->active)) { | 	while (!window_pane_visible(w->active)) { | ||||||
| 		w->active = TAILQ_PREV(w->active, window_panes, entry); | 		w->active = TAILQ_PREV(w->active, window_panes, entry); | ||||||
| 		if (w->active == NULL) | 		if (w->active == NULL) | ||||||
| @@ -459,6 +399,7 @@ window_set_active_pane(struct window *w, struct window_pane *wp) | |||||||
| 		if (w->active == wp) | 		if (w->active == wp) | ||||||
| 			return; | 			return; | ||||||
| 	} | 	} | ||||||
|  | 	w->active->active_point = next_active_point++; | ||||||
| } | } | ||||||
|  |  | ||||||
| struct window_pane * | struct window_pane * | ||||||
| @@ -736,7 +677,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) | |||||||
| 	wp->id = next_window_pane_id++; | 	wp->id = next_window_pane_id++; | ||||||
| 	RB_INSERT(window_pane_tree, &all_window_panes, wp); | 	RB_INSERT(window_pane_tree, &all_window_panes, wp); | ||||||
|  |  | ||||||
| 	wp->cmd = NULL; | 	wp->argc = 0; | ||||||
|  | 	wp->argv = NULL; | ||||||
| 	wp->shell = NULL; | 	wp->shell = NULL; | ||||||
| 	wp->cwd = -1; | 	wp->cwd = -1; | ||||||
|  |  | ||||||
| @@ -770,16 +712,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) | |||||||
| void | void | ||||||
| window_pane_destroy(struct window_pane *wp) | window_pane_destroy(struct window_pane *wp) | ||||||
| { | { | ||||||
| 	struct window_pane	*wp2; |  | ||||||
|  |  | ||||||
| 	/* Forget removed pane in all layout cells that remember it. */ |  | ||||||
| 	RB_FOREACH(wp2, window_pane_tree, &all_window_panes) { |  | ||||||
| 		if (wp2->layout_cell != NULL && |  | ||||||
| 		    wp2->layout_cell->parent != NULL && |  | ||||||
| 		    wp2->layout_cell->parent->lastwp == wp) |  | ||||||
| 			wp2->layout_cell->parent->lastwp = NULL; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	window_pane_reset_mode(wp); | 	window_pane_reset_mode(wp); | ||||||
|  |  | ||||||
| 	if (event_initialized(&wp->changes_timer)) | 	if (event_initialized(&wp->changes_timer)) | ||||||
| @@ -808,30 +740,32 @@ window_pane_destroy(struct window_pane *wp) | |||||||
|  |  | ||||||
| 	close(wp->cwd); | 	close(wp->cwd); | ||||||
| 	free(wp->shell); | 	free(wp->shell); | ||||||
| 	free(wp->cmd); | 	cmd_free_argv(wp->argc, wp->argv); | ||||||
| 	free(wp); | 	free(wp); | ||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path, | window_pane_spawn(struct window_pane *wp, int argc, char **argv, | ||||||
|     const char *shell, int cwd, struct environ *env, struct termios *tio, |     const char *path, const char *shell, int cwd, struct environ *env, | ||||||
|     char **cause) |     struct termios *tio, char **cause) | ||||||
| { | { | ||||||
| 	struct winsize	 ws; | 	struct winsize	 ws; | ||||||
| 	char		*argv0, paneid[16]; | 	char		*argv0, *cmd, **argvp, paneid[16]; | ||||||
| 	const char	*ptr; | 	const char	*ptr, *first; | ||||||
| 	struct termios	 tio2; | 	struct termios	 tio2; | ||||||
| #ifdef HAVE_UTEMPTER | #ifdef HAVE_UTEMPTER | ||||||
| 	char		 s[32]; | 	char		 s[32]; | ||||||
| #endif | #endif | ||||||
|  | 	int		 i; | ||||||
|  |  | ||||||
| 	if (wp->fd != -1) { | 	if (wp->fd != -1) { | ||||||
| 		bufferevent_free(wp->event); | 		bufferevent_free(wp->event); | ||||||
| 		close(wp->fd); | 		close(wp->fd); | ||||||
| 	} | 	} | ||||||
| 	if (cmd != NULL) { | 	if (argc > 0) { | ||||||
| 		free(wp->cmd); | 		cmd_free_argv(wp->argc, wp->argv); | ||||||
| 		wp->cmd = xstrdup(cmd); | 		wp->argc = argc; | ||||||
|  | 		wp->argv = cmd_copy_argv(argc, argv); | ||||||
| 	} | 	} | ||||||
| 	if (shell != NULL) { | 	if (shell != NULL) { | ||||||
| 		free(wp->shell); | 		free(wp->shell); | ||||||
| @@ -842,7 +776,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path, | |||||||
| 		wp->cwd = dup(cwd); | 		wp->cwd = dup(cwd); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	log_debug("spawn: %s -- %s", wp->shell, wp->cmd); | 	cmd = cmd_stringify_argv(wp->argc, wp->argv); | ||||||
|  | 	log_debug("spawn: %s -- %s", wp->shell, cmd); | ||||||
|  | 	for (i = 0; i < wp->argc; i++) | ||||||
|  | 		log_debug("spawn: argv[%d] = %s", i, wp->argv[i]); | ||||||
|  |  | ||||||
| 	memset(&ws, 0, sizeof ws); | 	memset(&ws, 0, sizeof ws); | ||||||
| 	ws.ws_col = screen_size_x(&wp->base); | 	ws.ws_col = screen_size_x(&wp->base); | ||||||
| @@ -852,6 +789,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path, | |||||||
| 	case -1: | 	case -1: | ||||||
| 		wp->fd = -1; | 		wp->fd = -1; | ||||||
| 		xasprintf(cause, "%s: %s", cmd, strerror(errno)); | 		xasprintf(cause, "%s: %s", cmd, strerror(errno)); | ||||||
|  | 		free(cmd); | ||||||
| 		return (-1); | 		return (-1); | ||||||
| 	case 0: | 	case 0: | ||||||
| 		if (fchdir(wp->cwd) != 0) | 		if (fchdir(wp->cwd) != 0) | ||||||
| @@ -883,22 +821,32 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path, | |||||||
| 		setenv("SHELL", wp->shell, 1); | 		setenv("SHELL", wp->shell, 1); | ||||||
| 		ptr = strrchr(wp->shell, '/'); | 		ptr = strrchr(wp->shell, '/'); | ||||||
|  |  | ||||||
| 		if (*wp->cmd != '\0') { | 		/* | ||||||
| 			/* Use the command. */ | 		 * If given one argument, assume it should be passed to sh -c; | ||||||
|  | 		 * with more than one argument, use execvp(). If there is no | ||||||
|  | 		 * arguments, create a login shell. | ||||||
|  | 		 */ | ||||||
|  | 		if (wp->argc > 0) { | ||||||
|  | 			if (wp->argc != 1) { | ||||||
|  | 				/* Copy to ensure argv ends in NULL. */ | ||||||
|  | 				argvp = cmd_copy_argv(wp->argc, wp->argv); | ||||||
|  | 				execvp(argvp[0], argvp); | ||||||
|  | 				fatal("execvp failed"); | ||||||
|  | 			} | ||||||
|  | 			first = wp->argv[0]; | ||||||
|  |  | ||||||
| 			if (ptr != NULL && *(ptr + 1) != '\0') | 			if (ptr != NULL && *(ptr + 1) != '\0') | ||||||
| 				xasprintf(&argv0, "%s", ptr + 1); | 				xasprintf(&argv0, "%s", ptr + 1); | ||||||
| 			else | 			else | ||||||
| 				xasprintf(&argv0, "%s", wp->shell); | 				xasprintf(&argv0, "%s", wp->shell); | ||||||
| 			execl(wp->shell, argv0, "-c", wp->cmd, (char *) NULL); | 			execl(wp->shell, argv0, "-c", first, (char *)NULL); | ||||||
| 			fatal("execl failed"); | 			fatal("execl failed"); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* No command; fork a login shell. */ |  | ||||||
| 		if (ptr != NULL && *(ptr + 1) != '\0') | 		if (ptr != NULL && *(ptr + 1) != '\0') | ||||||
| 			xasprintf(&argv0, "-%s", ptr + 1); | 			xasprintf(&argv0, "-%s", ptr + 1); | ||||||
| 		else | 		else | ||||||
| 			xasprintf(&argv0, "-%s", wp->shell); | 			xasprintf(&argv0, "-%s", wp->shell); | ||||||
| 		execl(wp->shell, argv0, (char *) NULL); | 		execl(wp->shell, argv0, (char *)NULL); | ||||||
| 		fatal("execl failed"); | 		fatal("execl failed"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -909,10 +857,11 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path, | |||||||
|  |  | ||||||
| 	setblocking(wp->fd, 0); | 	setblocking(wp->fd, 0); | ||||||
|  |  | ||||||
| 	wp->event = bufferevent_new(wp->fd, | 	wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, | ||||||
| 	    window_pane_read_callback, NULL, window_pane_error_callback, wp); | 	    window_pane_error_callback, wp); | ||||||
| 	bufferevent_enable(wp->event, EV_READ|EV_WRITE); | 	bufferevent_enable(wp->event, EV_READ|EV_WRITE); | ||||||
|  |  | ||||||
|  | 	free(cmd); | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1201,114 +1150,198 @@ window_pane_search(struct window_pane *wp, const char *searchstr, | |||||||
| 	return (msg); | 	return (msg); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Find the pane directly above another. */ | /* Get MRU pane from a list. */ | ||||||
|  | struct window_pane * | ||||||
|  | window_pane_choose_best(struct window_pane_list *list) | ||||||
|  | { | ||||||
|  | 	struct window_pane	*next, *best; | ||||||
|  | 	u_int			 i; | ||||||
|  |  | ||||||
|  | 	if (ARRAY_LENGTH(list) == 0) | ||||||
|  | 		return (NULL); | ||||||
|  |  | ||||||
|  | 	best = ARRAY_FIRST(list); | ||||||
|  | 	for (i = 1; i < ARRAY_LENGTH(list); i++) { | ||||||
|  | 		next = ARRAY_ITEM(list, i); | ||||||
|  | 		if (next->active_point > best->active_point) | ||||||
|  | 			best = next; | ||||||
|  | 	} | ||||||
|  | 	return (best); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Find the pane directly above another. We build a list of those adjacent to | ||||||
|  |  * top edge and then choose the best. | ||||||
|  |  */ | ||||||
| struct window_pane * | struct window_pane * | ||||||
| window_pane_find_up(struct window_pane *wp) | window_pane_find_up(struct window_pane *wp) | ||||||
| { | { | ||||||
| 	struct window_pane     *wp2; | 	struct window_pane	*next, *best; | ||||||
| 	u_int			left, top; | 	u_int			 edge, left, right, end; | ||||||
|  | 	struct window_pane_list	 list; | ||||||
|  | 	int			 found; | ||||||
|  |  | ||||||
| 	if (wp == NULL || !window_pane_visible(wp)) | 	if (wp == NULL || !window_pane_visible(wp)) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
|  | 	ARRAY_INIT(&list); | ||||||
|  |  | ||||||
|  | 	edge = wp->yoff; | ||||||
|  | 	if (edge == 0) | ||||||
|  | 		edge = wp->window->sy + 1; | ||||||
|  |  | ||||||
| 	top = wp->yoff; |  | ||||||
| 	if (top == 0) |  | ||||||
| 		top = wp->window->sy + 1; |  | ||||||
| 	left = wp->xoff; | 	left = wp->xoff; | ||||||
|  | 	right = wp->xoff + wp->sx; | ||||||
|  |  | ||||||
| 	TAILQ_FOREACH(wp2, &wp->window->panes, entry) { | 	TAILQ_FOREACH(next, &wp->window->panes, entry) { | ||||||
| 		if (!window_pane_visible(wp2)) | 		if (next == wp || !window_pane_visible(next)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (wp2->yoff + wp2->sy + 1 != top) | 		if (next->yoff + next->sy + 1 != edge) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) | 		end = next->xoff + next->sx - 1; | ||||||
| 			return (window_pane_active_set(wp, wp2)); |  | ||||||
|  | 		found = 0; | ||||||
|  | 		if (next->xoff < left && end > right) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (next->xoff >= left && next->xoff <= right) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (end >= left && end <= right) | ||||||
|  | 			found = 1; | ||||||
|  | 		if (found) | ||||||
|  | 			ARRAY_ADD(&list, next); | ||||||
| 	} | 	} | ||||||
| 	return (NULL); |  | ||||||
|  | 	best = window_pane_choose_best(&list); | ||||||
|  | 	ARRAY_FREE(&list); | ||||||
|  | 	return (best); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Find the pane directly below another. */ | /* Find the pane directly below another. */ | ||||||
| struct window_pane * | struct window_pane * | ||||||
| window_pane_find_down(struct window_pane *wp) | window_pane_find_down(struct window_pane *wp) | ||||||
| { | { | ||||||
| 	struct window_pane     *wp2; | 	struct window_pane	*next, *best; | ||||||
| 	u_int			left, bottom; | 	u_int			 edge, left, right, end; | ||||||
|  | 	struct window_pane_list	 list; | ||||||
|  | 	int			 found; | ||||||
|  |  | ||||||
| 	if (wp == NULL || !window_pane_visible(wp)) | 	if (wp == NULL || !window_pane_visible(wp)) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
|  | 	ARRAY_INIT(&list); | ||||||
|  |  | ||||||
|  | 	edge = wp->yoff + wp->sy + 1; | ||||||
|  | 	if (edge >= wp->window->sy) | ||||||
|  | 		edge = 0; | ||||||
|  |  | ||||||
| 	bottom = wp->yoff + wp->sy + 1; |  | ||||||
| 	if (bottom >= wp->window->sy) |  | ||||||
| 		bottom = 0; |  | ||||||
| 	left = wp->xoff; | 	left = wp->xoff; | ||||||
|  | 	right = wp->xoff + wp->sx; | ||||||
|  |  | ||||||
| 	TAILQ_FOREACH(wp2, &wp->window->panes, entry) { | 	TAILQ_FOREACH(next, &wp->window->panes, entry) { | ||||||
| 		if (!window_pane_visible(wp2)) | 		if (next == wp || !window_pane_visible(next)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (wp2->yoff != bottom) | 		if (next->yoff != edge) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) | 		end = next->xoff + next->sx - 1; | ||||||
| 			return (window_pane_active_set(wp, wp2)); |  | ||||||
|  | 		found = 0; | ||||||
|  | 		if (next->xoff < left && end > right) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (next->xoff >= left && next->xoff <= right) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (end >= left && end <= right) | ||||||
|  | 			found = 1; | ||||||
|  | 		if (found) | ||||||
|  | 			ARRAY_ADD(&list, next); | ||||||
| 	} | 	} | ||||||
| 	return (NULL); |  | ||||||
|  | 	best = window_pane_choose_best(&list); | ||||||
|  | 	ARRAY_FREE(&list); | ||||||
|  | 	return (best); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* Find the pane directly to the left of another. */ | ||||||
|  * Find the pane directly to the left of another, adjacent to the left side and |  | ||||||
|  * containing the top edge. |  | ||||||
|  */ |  | ||||||
| struct window_pane * | struct window_pane * | ||||||
| window_pane_find_left(struct window_pane *wp) | window_pane_find_left(struct window_pane *wp) | ||||||
| { | { | ||||||
| 	struct window_pane     *wp2; | 	struct window_pane	*next, *best; | ||||||
| 	u_int			left, top; | 	u_int			 edge, top, bottom, end; | ||||||
|  | 	struct window_pane_list	 list; | ||||||
|  | 	int			 found; | ||||||
|  |  | ||||||
| 	if (wp == NULL || !window_pane_visible(wp)) | 	if (wp == NULL || !window_pane_visible(wp)) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
|  | 	ARRAY_INIT(&list); | ||||||
|  |  | ||||||
|  | 	edge = wp->xoff; | ||||||
|  | 	if (edge == 0) | ||||||
|  | 		edge = wp->window->sx + 1; | ||||||
|  |  | ||||||
| 	left = wp->xoff; |  | ||||||
| 	if (left == 0) |  | ||||||
| 		left = wp->window->sx + 1; |  | ||||||
| 	top = wp->yoff; | 	top = wp->yoff; | ||||||
|  | 	bottom = wp->yoff + wp->sy; | ||||||
|  |  | ||||||
| 	TAILQ_FOREACH(wp2, &wp->window->panes, entry) { | 	TAILQ_FOREACH(next, &wp->window->panes, entry) { | ||||||
| 		if (!window_pane_visible(wp2)) | 		if (next == wp || !window_pane_visible(next)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (wp2->xoff + wp2->sx + 1 != left) | 		if (next->xoff + next->sx + 1 != edge) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) | 		end = next->yoff + next->sy - 1; | ||||||
| 			return (window_pane_active_set(wp, wp2)); |  | ||||||
|  | 		found = 0; | ||||||
|  | 		if (next->yoff < top && end > bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (next->yoff >= top && next->yoff <= bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (end >= top && end <= bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		if (found) | ||||||
|  | 			ARRAY_ADD(&list, next); | ||||||
| 	} | 	} | ||||||
| 	return (NULL); |  | ||||||
|  | 	best = window_pane_choose_best(&list); | ||||||
|  | 	ARRAY_FREE(&list); | ||||||
|  | 	return (best); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* Find the pane directly to the right of another. */ | ||||||
|  * Find the pane directly to the right of another, that is adjacent to the |  | ||||||
|  * right edge and including the top edge. |  | ||||||
|  */ |  | ||||||
| struct window_pane * | struct window_pane * | ||||||
| window_pane_find_right(struct window_pane *wp) | window_pane_find_right(struct window_pane *wp) | ||||||
| { | { | ||||||
| 	struct window_pane     *wp2; | 	struct window_pane	*next, *best; | ||||||
| 	u_int			right, top; | 	u_int			 edge, top, bottom, end; | ||||||
|  | 	struct window_pane_list	 list; | ||||||
|  | 	int			 found; | ||||||
|  |  | ||||||
| 	if (wp == NULL || !window_pane_visible(wp)) | 	if (wp == NULL || !window_pane_visible(wp)) | ||||||
| 		return (NULL); | 		return (NULL); | ||||||
|  | 	ARRAY_INIT(&list); | ||||||
|  |  | ||||||
|  | 	edge = wp->xoff + wp->sx + 1; | ||||||
|  | 	if (edge >= wp->window->sx) | ||||||
|  | 		edge = 0; | ||||||
|  |  | ||||||
| 	right = wp->xoff + wp->sx + 1; |  | ||||||
| 	if (right >= wp->window->sx) |  | ||||||
| 		right = 0; |  | ||||||
| 	top = wp->yoff; | 	top = wp->yoff; | ||||||
|  | 	bottom = wp->yoff + wp->sy; | ||||||
|  |  | ||||||
| 	TAILQ_FOREACH(wp2, &wp->window->panes, entry) { | 	TAILQ_FOREACH(next, &wp->window->panes, entry) { | ||||||
| 		if (!window_pane_visible(wp2)) | 		if (next == wp || !window_pane_visible(next)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (wp2->xoff != right) | 		if (next->xoff != edge) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) | 		end = next->yoff + next->sy - 1; | ||||||
| 			return (window_pane_active_set(wp, wp2)); |  | ||||||
|  | 		found = 0; | ||||||
|  | 		if (next->yoff < top && end > bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (next->yoff >= top && next->yoff <= bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		else if (end >= top && end <= bottom) | ||||||
|  | 			found = 1; | ||||||
|  | 		if (found) | ||||||
|  | 			ARRAY_ADD(&list, next); | ||||||
| 	} | 	} | ||||||
| 	return (NULL); |  | ||||||
|  | 	best = window_pane_choose_best(&list); | ||||||
|  | 	ARRAY_FREE(&list); | ||||||
|  | 	return (best); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Clear alert flags for a winlink */ | /* Clear alert flags for a winlink */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Thomas Adam
					Thomas Adam