mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code
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 = {
 | 
			
		||||
	"capture-pane", "capturep",
 | 
			
		||||
	"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,
 | 
			
		||||
	0,
 | 
			
		||||
	NULL,
 | 
			
		||||
@@ -165,8 +165,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	char			*buf, *cause;
 | 
			
		||||
	int			 buffer;
 | 
			
		||||
	u_int			 limit;
 | 
			
		||||
	const char		*bufname;
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		server_push_stdout(c);
 | 
			
		||||
	} 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);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "buffer %s", cause);
 | 
			
		||||
		bufname = NULL;
 | 
			
		||||
		if (args_has(args, 'b'))
 | 
			
		||||
			bufname = args_get(args, 'b');
 | 
			
		||||
 | 
			
		||||
		if (paste_set(buf, len, bufname, &cause) != 0) {
 | 
			
		||||
			cmdq_error(cmdq, "%s", cause);
 | 
			
		||||
			free(buf);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			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);
 | 
			
		||||
 
 | 
			
		||||
@@ -75,19 +75,20 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		action = xstrdup("paste-buffer -b '%%'");
 | 
			
		||||
 | 
			
		||||
	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->idx = idx - 1;
 | 
			
		||||
		cdata->idx = idx;
 | 
			
		||||
 | 
			
		||||
		cdata->ft_template = xstrdup(template);
 | 
			
		||||
		format_add(cdata->ft, "line", "%u", idx - 1);
 | 
			
		||||
		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);
 | 
			
		||||
		free(action_data);
 | 
			
		||||
 | 
			
		||||
		window_choose_add(wl->window->active, cdata);
 | 
			
		||||
		idx++;
 | 
			
		||||
	}
 | 
			
		||||
	free(action);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,23 +41,16 @@ enum cmd_retval
 | 
			
		||||
cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
{
 | 
			
		||||
	struct args	*args = self->args;
 | 
			
		||||
	char		*cause;
 | 
			
		||||
	int		 buffer;
 | 
			
		||||
	const char 	*bufname;
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'b')) {
 | 
			
		||||
		paste_free_top();
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	}
 | 
			
		||||
	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 (paste_free_index(buffer) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "no buffer %d", buffer);
 | 
			
		||||
	if (paste_free_name(bufname) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "no buffer %s", bufname);
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&find_list); i++)
 | 
			
		||||
		free(ARRAY_ITEM(&find_list, i).list_ctx);
 | 
			
		||||
	ARRAY_FREE(&find_list);
 | 
			
		||||
	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 paste_buffer	*pb;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	u_int			 idx;
 | 
			
		||||
	char			*line;
 | 
			
		||||
	const char		*template;
 | 
			
		||||
 | 
			
		||||
	if ((template = args_get(args, 'F')) == NULL)
 | 
			
		||||
		template = LIST_BUFFERS_TEMPLATE;
 | 
			
		||||
 | 
			
		||||
	idx = 0;
 | 
			
		||||
	while ((pb = paste_walk_stack(&idx)) != NULL) {
 | 
			
		||||
	pb = NULL;
 | 
			
		||||
	while ((pb = paste_walk(pb)) != NULL) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
		format_add(ft, "line", "%u", idx - 1);
 | 
			
		||||
		format_paste_buffer(ft, pb, 0);
 | 
			
		||||
 | 
			
		||||
		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 session  *s;
 | 
			
		||||
	FILE		*f;
 | 
			
		||||
	const char	*path;
 | 
			
		||||
	const char	*path, *bufname;
 | 
			
		||||
	char		*pdata, *new_pdata, *cause;
 | 
			
		||||
	size_t		 psize;
 | 
			
		||||
	u_int		 limit;
 | 
			
		||||
	int		 ch, error, buffer, *buffer_ptr, cwd, fd;
 | 
			
		||||
	int		 ch, error, cwd, fd;
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'b'))
 | 
			
		||||
		buffer = -1;
 | 
			
		||||
	else {
 | 
			
		||||
		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "buffer %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	bufname = NULL;
 | 
			
		||||
	if (args_has(args, 'b'))
 | 
			
		||||
		bufname = args_get(args, 'b');
 | 
			
		||||
 | 
			
		||||
	path = args->argv[0];
 | 
			
		||||
	if (strcmp(path, "-") == 0) {
 | 
			
		||||
		buffer_ptr = xmalloc(sizeof *buffer_ptr);
 | 
			
		||||
		*buffer_ptr = buffer;
 | 
			
		||||
 | 
			
		||||
		error = server_set_stdin_callback(c, cmd_load_buffer_callback,
 | 
			
		||||
		    buffer_ptr, &cause);
 | 
			
		||||
		    (void*)bufname, &cause);
 | 
			
		||||
		if (error != 0) {
 | 
			
		||||
			cmdq_error(cmdq, "%s: %s", path, cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
@@ -117,14 +106,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
 | 
			
		||||
	fclose(f);
 | 
			
		||||
 | 
			
		||||
	limit = options_get_number(&global_options, "buffer-limit");
 | 
			
		||||
	if (buffer == -1) {
 | 
			
		||||
		paste_add(pdata, psize, limit);
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	}
 | 
			
		||||
	if (paste_replace(buffer, pdata, psize) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "no buffer %d", buffer);
 | 
			
		||||
	if (paste_set(pdata, psize, bufname, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "%s", cause);
 | 
			
		||||
		free(pdata);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -140,10 +125,9 @@ error:
 | 
			
		||||
void
 | 
			
		||||
cmd_load_buffer_callback(struct client *c, int closed, void *data)
 | 
			
		||||
{
 | 
			
		||||
	int	*buffer = data;
 | 
			
		||||
	char	*pdata;
 | 
			
		||||
	size_t	 psize;
 | 
			
		||||
	u_int	 limit;
 | 
			
		||||
	const char	*bufname = data;
 | 
			
		||||
	char		*pdata, *cause;
 | 
			
		||||
	size_t		 psize;
 | 
			
		||||
 | 
			
		||||
	if (!closed)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -154,26 +138,21 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	psize = EVBUFFER_LENGTH(c->stdin_data);
 | 
			
		||||
	if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
 | 
			
		||||
		free(data);
 | 
			
		||||
	if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
 | 
			
		||||
	pdata[psize] = '\0';
 | 
			
		||||
	evbuffer_drain(c->stdin_data, psize);
 | 
			
		||||
 | 
			
		||||
	limit = options_get_number(&global_options, "buffer-limit");
 | 
			
		||||
	if (*buffer == -1)
 | 
			
		||||
		paste_add(pdata, psize, limit);
 | 
			
		||||
	else if (paste_replace(*buffer, pdata, psize) != 0) {
 | 
			
		||||
	if (paste_set(pdata, psize, bufname, &cause) != 0) {
 | 
			
		||||
		/* 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);
 | 
			
		||||
		free(pdata);
 | 
			
		||||
		free(cause);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free(data);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	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 = {
 | 
			
		||||
	"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] "
 | 
			
		||||
	"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
 | 
			
		||||
	"[command]",
 | 
			
		||||
	"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
 | 
			
		||||
	"[-y height] [command]",
 | 
			
		||||
	CMD_STARTSERVER|CMD_CANTNEST,
 | 
			
		||||
	NULL,
 | 
			
		||||
	cmd_new_session_exec
 | 
			
		||||
@@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct termios		 tio, *tiop;
 | 
			
		||||
	const char		*newname, *target, *update, *errstr, *template;
 | 
			
		||||
	const char		*path;
 | 
			
		||||
	char			*cmd, *cause, *cp;
 | 
			
		||||
	char		       **argv, *cmd, *cause, *cp;
 | 
			
		||||
	int			 detached, already_attached, idx, cwd, fd = -1;
 | 
			
		||||
	int			 argc;
 | 
			
		||||
	u_int			 sx, sy;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
@@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
		sy = 1;
 | 
			
		||||
 | 
			
		||||
	/* Figure out the command for the new window. */
 | 
			
		||||
	if (target != NULL)
 | 
			
		||||
		cmd = NULL;
 | 
			
		||||
	else if (args->argc != 0)
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
	else
 | 
			
		||||
	argc = -1;
 | 
			
		||||
	argv = NULL;
 | 
			
		||||
	if (target == NULL && args->argc != 0) {
 | 
			
		||||
		argc = args->argc;
 | 
			
		||||
		argv = args->argv;
 | 
			
		||||
	} else if (target == NULL) {
 | 
			
		||||
		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;
 | 
			
		||||
	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. */
 | 
			
		||||
	idx = -1 - options_get_number(&global_s_options, "base-index");
 | 
			
		||||
	s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy,
 | 
			
		||||
	    &cause);
 | 
			
		||||
	s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
 | 
			
		||||
	    sy, &cause);
 | 
			
		||||
	if (s == NULL) {
 | 
			
		||||
		cmdq_error(cmdq, "create session failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
@@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	environ_free(&env);
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
		window_set_name(w, args_get(args, 'n'));
 | 
			
		||||
		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 = {
 | 
			
		||||
	"new-window", "neww",
 | 
			
		||||
	"ac:dF:kn:Pt:", 0, 1,
 | 
			
		||||
	"ac:dF:kn:Pt:", 0, -1,
 | 
			
		||||
	"[-adkP] [-c start-directory] [-F format] [-n window-name] "
 | 
			
		||||
	CMD_TARGET_WINDOW_USAGE " [command]",
 | 
			
		||||
	0,
 | 
			
		||||
@@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	const char		*cmd, *path, *template;
 | 
			
		||||
	char			*cause, *cp;
 | 
			
		||||
	int			 idx, last, detached, cwd, fd = -1;
 | 
			
		||||
	char		       **argv, *cause, *cp;
 | 
			
		||||
	int			 argc, idx, last, detached, cwd, fd = -1;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
 | 
			
		||||
@@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	}
 | 
			
		||||
	detached = args_has(args, 'd');
 | 
			
		||||
 | 
			
		||||
	if (args->argc == 0)
 | 
			
		||||
	if (args->argc == 0) {
 | 
			
		||||
		cmd = options_get_string(&s->options, "default-command");
 | 
			
		||||
	else
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
		if (cmd != NULL && *cmd != '\0') {
 | 
			
		||||
			argc = 1;
 | 
			
		||||
			argv = (char**)&cmd;
 | 
			
		||||
		} else {
 | 
			
		||||
			argc = 0;
 | 
			
		||||
			argv = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		argc = args->argc;
 | 
			
		||||
		argv = args->argv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	path = 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)
 | 
			
		||||
		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) {
 | 
			
		||||
		cmdq_error(cmdq, "create window failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ void	cmd_paste_buffer_filter(struct window_pane *,
 | 
			
		||||
const struct cmd_entry cmd_paste_buffer_entry = {
 | 
			
		||||
	"paste-buffer", "pasteb",
 | 
			
		||||
	"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,
 | 
			
		||||
	NULL,
 | 
			
		||||
	cmd_paste_buffer_exec
 | 
			
		||||
@@ -48,31 +48,22 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
	const char		*sepstr;
 | 
			
		||||
	char			*cause;
 | 
			
		||||
	int			 buffer;
 | 
			
		||||
	const char		*sepstr, *bufname;
 | 
			
		||||
	int			 pflag;
 | 
			
		||||
 | 
			
		||||
	if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'b'))
 | 
			
		||||
		buffer = -1;
 | 
			
		||||
	else {
 | 
			
		||||
		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "buffer %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	bufname = NULL;
 | 
			
		||||
	if (args_has(args, 'b'))
 | 
			
		||||
		bufname = args_get(args, 'b');
 | 
			
		||||
 | 
			
		||||
	if (buffer == -1)
 | 
			
		||||
	if (bufname == NULL)
 | 
			
		||||
		pb = paste_get_top();
 | 
			
		||||
	else {
 | 
			
		||||
		pb = paste_get_index(buffer);
 | 
			
		||||
		pb = paste_get_name(bufname);
 | 
			
		||||
		if (pb == NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "no buffer %d", buffer);
 | 
			
		||||
			cmdq_error(cmdq, "no buffer %s", bufname);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -91,10 +82,10 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
 | 
			
		||||
	/* Delete the buffer if -d. */
 | 
			
		||||
	if (args_has(args, 'd')) {
 | 
			
		||||
		if (buffer == -1)
 | 
			
		||||
		if (bufname == NULL)
 | 
			
		||||
			paste_free_top();
 | 
			
		||||
		else
 | 
			
		||||
			paste_free_index(buffer);
 | 
			
		||||
			paste_free_name(bufname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 = {
 | 
			
		||||
	"respawn-pane", "respawnp",
 | 
			
		||||
	"kt:", 0, 1,
 | 
			
		||||
	"kt:", 0, -1,
 | 
			
		||||
	"[-k] " CMD_TARGET_PANE_USAGE " [command]",
 | 
			
		||||
	0,
 | 
			
		||||
	NULL,
 | 
			
		||||
@@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct environ		 env;
 | 
			
		||||
	const char		*cmd, *path;
 | 
			
		||||
	const char		*path;
 | 
			
		||||
	char			*cause;
 | 
			
		||||
	u_int			 idx;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
@@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	screen_reinit(&wp->base);
 | 
			
		||||
	input_init(wp);
 | 
			
		||||
 | 
			
		||||
	if (args->argc != 0)
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
	else
 | 
			
		||||
		cmd = NULL;
 | 
			
		||||
 | 
			
		||||
	path = NULL;
 | 
			
		||||
	if (cmdq->client != NULL && cmdq->client->session == NULL)
 | 
			
		||||
		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)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
 | 
			
		||||
	    &cause) != 0) {
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
 | 
			
		||||
	    s->tio, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "respawn pane failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		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 = {
 | 
			
		||||
	"respawn-window", "respawnw",
 | 
			
		||||
	"kt:", 0, 1,
 | 
			
		||||
	"kt:", 0, -1,
 | 
			
		||||
	"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
 | 
			
		||||
	0,
 | 
			
		||||
	NULL,
 | 
			
		||||
@@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct environ		 env;
 | 
			
		||||
	const char		*cmd, *path;
 | 
			
		||||
	const char		*path;
 | 
			
		||||
	char		 	*cause;
 | 
			
		||||
	struct environ_entry	*envent;
 | 
			
		||||
 | 
			
		||||
@@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	window_destroy_panes(w);
 | 
			
		||||
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
			
		||||
	window_pane_resize(wp, w->sx, w->sy);
 | 
			
		||||
	if (args->argc != 0)
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
	else
 | 
			
		||||
		cmd = NULL;
 | 
			
		||||
 | 
			
		||||
	path = 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)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
 | 
			
		||||
	    &cause) != 0) {
 | 
			
		||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
 | 
			
		||||
	    s->tio, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "respawn window failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		environ_free(&env);
 | 
			
		||||
 
 | 
			
		||||
@@ -58,10 +58,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct client		*c = cmdq->client;
 | 
			
		||||
	struct session          *s;
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
	const char		*path;
 | 
			
		||||
	char			*cause, *start, *end, *msg;
 | 
			
		||||
	const char		*path, *bufname;
 | 
			
		||||
	char			*start, *end, *msg;
 | 
			
		||||
	size_t			 size, used, msglen;
 | 
			
		||||
	int			 cwd, fd, buffer;
 | 
			
		||||
	int			 cwd, fd;
 | 
			
		||||
	FILE			*f;
 | 
			
		||||
 | 
			
		||||
	if (!args_has(args, 'b')) {
 | 
			
		||||
@@ -70,16 +70,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "buffer %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pb = paste_get_index(buffer);
 | 
			
		||||
		bufname = args_get(args, 'b');
 | 
			
		||||
		pb = paste_get_name(bufname);
 | 
			
		||||
		if (pb == NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "no buffer %d", buffer);
 | 
			
		||||
			cmdq_error(cmdq, "no buffer %s", bufname);
 | 
			
		||||
			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 = {
 | 
			
		||||
	"set-buffer", "setb",
 | 
			
		||||
	"ab:", 1, 1,
 | 
			
		||||
	"[-a] " CMD_BUFFER_USAGE " data",
 | 
			
		||||
	"ab:n:", 0, 1,
 | 
			
		||||
	"[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
 | 
			
		||||
	0,
 | 
			
		||||
	NULL,
 | 
			
		||||
	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 paste_buffer	*pb;
 | 
			
		||||
	u_int			 limit;
 | 
			
		||||
	char			*pdata, *cause;
 | 
			
		||||
	const char		*bufname;
 | 
			
		||||
	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;
 | 
			
		||||
	pdata = NULL;
 | 
			
		||||
 | 
			
		||||
	pb = NULL;
 | 
			
		||||
	buffer = -1;
 | 
			
		||||
 | 
			
		||||
	if ((newsize = strlen(args->argv[0])) == 0)
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
	if (args_has(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);
 | 
			
		||||
		}
 | 
			
		||||
		pb = paste_get_index(buffer);
 | 
			
		||||
		if (pb == NULL) {
 | 
			
		||||
			cmdq_error(cmdq, "no buffer %d", buffer);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		bufname = args_get(args, 'b');
 | 
			
		||||
		pb = paste_get_name(bufname);
 | 
			
		||||
	} else if (args_has(args, 'a')) {
 | 
			
		||||
		pb = paste_get_top();
 | 
			
		||||
		if (pb != NULL)
 | 
			
		||||
			buffer = 0;
 | 
			
		||||
			bufname = pb->name;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	psize += newsize;
 | 
			
		||||
 | 
			
		||||
	if (buffer == -1)
 | 
			
		||||
		paste_add(pdata, psize, limit);
 | 
			
		||||
	else
 | 
			
		||||
		paste_replace(buffer, pdata, psize);
 | 
			
		||||
	if (paste_set(pdata, psize, bufname, &cause) != 0) {
 | 
			
		||||
		cmdq_error(cmdq, "%s", cause);
 | 
			
		||||
		free(pdata);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 = {
 | 
			
		||||
	"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] "
 | 
			
		||||
	CMD_TARGET_PANE_USAGE " [command]",
 | 
			
		||||
	0,
 | 
			
		||||
@@ -61,9 +61,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	struct window_pane	*wp, *new_wp = NULL;
 | 
			
		||||
	struct environ		 env;
 | 
			
		||||
	const char		*cmd, *path, *shell, *template;
 | 
			
		||||
	char			*cause, *new_cause, *cp;
 | 
			
		||||
	char		       **argv, *cause, *new_cause, *cp;
 | 
			
		||||
	u_int			 hlimit;
 | 
			
		||||
	int			 size, percentage, cwd, fd = -1;
 | 
			
		||||
	int			 argc, size, percentage, cwd, fd = -1;
 | 
			
		||||
	enum layout_type	 type;
 | 
			
		||||
	struct layout_cell	*lc;
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
@@ -80,10 +80,19 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	environ_copy(&s->environ, &env);
 | 
			
		||||
	server_fill_environ(s, &env);
 | 
			
		||||
 | 
			
		||||
	if (args->argc == 0)
 | 
			
		||||
	if (args->argc == 0) {
 | 
			
		||||
		cmd = options_get_string(&s->options, "default-command");
 | 
			
		||||
	else
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
		if (cmd != NULL && *cmd != '\0') {
 | 
			
		||||
			argc = 1;
 | 
			
		||||
			argv = (char**)&cmd;
 | 
			
		||||
		} else {
 | 
			
		||||
			argc = 0;
 | 
			
		||||
			argv = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		argc = args->argc;
 | 
			
		||||
		argv = args->argv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'c')) {
 | 
			
		||||
		ft = format_create();
 | 
			
		||||
@@ -157,8 +166,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (envent != NULL)
 | 
			
		||||
		path = envent->value;
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(
 | 
			
		||||
	    new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0)
 | 
			
		||||
	if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
 | 
			
		||||
	    s->tio, &cause) != 0)
 | 
			
		||||
		goto error;
 | 
			
		||||
	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 **
 | 
			
		||||
cmd_copy_argv(int argc, char *const *argv)
 | 
			
		||||
cmd_copy_argv(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	char	**new_argv;
 | 
			
		||||
	int	  i;
 | 
			
		||||
 | 
			
		||||
	if (argc == 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	new_argv = xcalloc(argc, sizeof *new_argv);
 | 
			
		||||
	new_argv = xcalloc(argc + 1, sizeof *new_argv);
 | 
			
		||||
	for (i = 0; i < argc; i++) {
 | 
			
		||||
		if (argv[i] != NULL)
 | 
			
		||||
			new_argv[i] = xstrdup(argv[i]);
 | 
			
		||||
@@ -206,6 +206,32 @@ cmd_free_argv(int argc, char **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 *
 | 
			
		||||
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);
 | 
			
		||||
	if (cmd == NULL || *cmd == '\0') {
 | 
			
		||||
		free(cmd);
 | 
			
		||||
		cmd = xstrdup(wp->cmd);
 | 
			
		||||
		cmd = cmd_stringify_argv(wp->argc, wp->argv);
 | 
			
		||||
		if (cmd == NULL || *cmd == '\0') {
 | 
			
		||||
			free(cmd);
 | 
			
		||||
			cmd = xstrdup(wp->shell);
 | 
			
		||||
@@ -559,10 +559,12 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
 | 
			
		||||
	if (wp->tty != NULL)
 | 
			
		||||
		format_add(ft, "pane_tty", "%s", wp->tty);
 | 
			
		||||
	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)
 | 
			
		||||
		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) {
 | 
			
		||||
		format_add(ft, "pane_current_command", "%s", cmd);
 | 
			
		||||
		free(cmd);
 | 
			
		||||
@@ -610,6 +612,7 @@ format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
 | 
			
		||||
	char	*s;
 | 
			
		||||
 | 
			
		||||
	format_add(ft, "buffer_size", "%zu", pb->size);
 | 
			
		||||
	format_add(ft, "buffer_name", "%s", pb->name);
 | 
			
		||||
 | 
			
		||||
	s = paste_make_sample(pb, utf8flag);
 | 
			
		||||
	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];
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
	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) {
 | 
			
		||||
		/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								layout.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								layout.c
									
									
									
									
									
								
							@@ -53,7 +53,6 @@ layout_create_cell(struct layout_cell *lcparent)
 | 
			
		||||
	lc->yoff = UINT_MAX;
 | 
			
		||||
 | 
			
		||||
	lc->wp = NULL;
 | 
			
		||||
	lc->lastwp = NULL;
 | 
			
		||||
 | 
			
		||||
	return (lc);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								log.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								log.c
									
									
									
									
									
								
							@@ -17,6 +17,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -141,6 +141,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
 | 
			
		||||
	{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" },
 | 
			
		||||
	{ MODEKEYCOPY_SEARCHUP, "search-backward" },
 | 
			
		||||
	{ MODEKEYCOPY_SELECTLINE, "select-line" },
 | 
			
		||||
	{ MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" },
 | 
			
		||||
	{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" },
 | 
			
		||||
	{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
 | 
			
		||||
	{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
 | 
			
		||||
@@ -257,6 +258,7 @@ struct mode_key_tree mode_key_tree_vi_choice;
 | 
			
		||||
/* vi copy mode keys. */
 | 
			
		||||
const struct mode_key_entry mode_key_vi_copy[] = {
 | 
			
		||||
	{ ' ',			    0, MODEKEYCOPY_STARTSELECTION },
 | 
			
		||||
	{ '"',			    0, MODEKEYCOPY_STARTNAMEDBUFFER },
 | 
			
		||||
	{ '$',			    0, MODEKEYCOPY_ENDOFLINE },
 | 
			
		||||
	{ ',',			    0, MODEKEYCOPY_JUMPREVERSE },
 | 
			
		||||
	{ ';',			    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 *
 | 
			
		||||
default_window_name(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	if (w->active->cmd != NULL && *w->active->cmd != '\0')
 | 
			
		||||
		return (parse_window_name(w->active->cmd));
 | 
			
		||||
	return (parse_window_name(w->active->shell));
 | 
			
		||||
	char    *cmd, *s;
 | 
			
		||||
 | 
			
		||||
	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 *
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										218
									
								
								paste.c
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								paste.c
									
									
									
									
									
								
							@@ -25,127 +25,237 @@
 | 
			
		||||
#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!
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
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. */
 | 
			
		||||
struct paste_buffer *
 | 
			
		||||
paste_walk_stack(u_int *idx)
 | 
			
		||||
int paste_cmp_names(const struct paste_buffer *, const struct paste_buffer *);
 | 
			
		||||
RB_PROTOTYPE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	pb = paste_get_index(*idx);
 | 
			
		||||
	(*idx)++;
 | 
			
		||||
	return (pb);
 | 
			
		||||
	return (strcmp(a->name, b->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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 *
 | 
			
		||||
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 (ARRAY_FIRST(&paste_buffers));
 | 
			
		||||
	return (pb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get an item by its index. */
 | 
			
		||||
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. */
 | 
			
		||||
/* Free the most recent buffer */
 | 
			
		||||
int
 | 
			
		||||
paste_free_top(void)
 | 
			
		||||
{
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
 | 
			
		||||
	if (ARRAY_LENGTH(&paste_buffers) == 0)
 | 
			
		||||
	pb = paste_get_top();
 | 
			
		||||
	if (pb == NULL)
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	pb = ARRAY_FIRST(&paste_buffers);
 | 
			
		||||
	ARRAY_REMOVE(&paste_buffers, 0);
 | 
			
		||||
 | 
			
		||||
	free(pb->data);
 | 
			
		||||
	free(pb);
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
	return (paste_free_name(pb->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Free an item by index. */
 | 
			
		||||
int
 | 
			
		||||
paste_free_index(u_int idx)
 | 
			
		||||
/* Get a paste buffer by name. */
 | 
			
		||||
struct paste_buffer *
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
	pb = ARRAY_ITEM(&paste_buffers, idx);
 | 
			
		||||
	ARRAY_REMOVE(&paste_buffers, idx);
 | 
			
		||||
	pbfind.name = (char*)name;
 | 
			
		||||
	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->name);
 | 
			
		||||
	free(pb);
 | 
			
		||||
 | 
			
		||||
	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.
 | 
			
		||||
 */
 | 
			
		||||
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)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	while (ARRAY_LENGTH(&paste_buffers) >= limit) {
 | 
			
		||||
		pb = ARRAY_LAST(&paste_buffers);
 | 
			
		||||
		free(pb->data);
 | 
			
		||||
		free(pb);
 | 
			
		||||
		ARRAY_TRUNC(&paste_buffers, 1);
 | 
			
		||||
	limit = options_get_number(&global_options, "buffer-limit");
 | 
			
		||||
	RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
 | 
			
		||||
		if (paste_num_automatic < limit)
 | 
			
		||||
			break;
 | 
			
		||||
		if (pb->automatic)
 | 
			
		||||
			paste_free_name(pb->name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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->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.
 | 
			
		||||
 */
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	if (cause != NULL)
 | 
			
		||||
		*cause = NULL;
 | 
			
		||||
 | 
			
		||||
	if (size == 0) {
 | 
			
		||||
		free(data);
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pb = ARRAY_ITEM(&paste_buffers, idx);
 | 
			
		||||
	free(pb->data);
 | 
			
		||||
	pb = paste_get_name(name);
 | 
			
		||||
	if (pb != NULL)
 | 
			
		||||
		paste_free_name(name);
 | 
			
		||||
 | 
			
		||||
	pb = xmalloc(sizeof *pb);
 | 
			
		||||
 | 
			
		||||
	pb->name = xstrdup(name);
 | 
			
		||||
 | 
			
		||||
	pb->data = data;
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								session.c
									
									
									
									
									
								
							@@ -84,11 +84,12 @@ session_find_by_id(u_int id)
 | 
			
		||||
 | 
			
		||||
/* Create a new session. */
 | 
			
		||||
struct session *
 | 
			
		||||
session_create(const char *name, const char *cmd, const char *path, int cwd,
 | 
			
		||||
    struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
 | 
			
		||||
    char **cause)
 | 
			
		||||
session_create(const char *name, int argc, char **argv, const char *path,
 | 
			
		||||
    int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
 | 
			
		||||
    u_int sy, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
 | 
			
		||||
	s = xmalloc(sizeof *s);
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	if (cmd != NULL) {
 | 
			
		||||
		if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) {
 | 
			
		||||
	if (argc >= 0) {
 | 
			
		||||
		wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
 | 
			
		||||
		if (wl == NULL) {
 | 
			
		||||
			session_destroy(s);
 | 
			
		||||
			return (NULL);
 | 
			
		||||
		}
 | 
			
		||||
@@ -226,7 +228,7 @@ session_previous_session(struct session *s)
 | 
			
		||||
 | 
			
		||||
/* Create a new window on a session. */
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
@@ -250,8 +252,8 @@ session_new(struct session *s, const char *name, const char *cmd,
 | 
			
		||||
		shell = _PATH_BSHELL;
 | 
			
		||||
 | 
			
		||||
	hlimit = options_get_number(&s->options, "history-limit");
 | 
			
		||||
	w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx,
 | 
			
		||||
	    s->sy, hlimit, cause);
 | 
			
		||||
	w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
 | 
			
		||||
	    s->sx, s->sy, hlimit, cause);
 | 
			
		||||
	if (w == NULL) {
 | 
			
		||||
		winlink_remove(&s->windows, wl);
 | 
			
		||||
		environ_free(&env);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								style.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								style.c
									
									
									
									
									
								
							@@ -117,7 +117,7 @@ style_tostring(struct grid_cell *gc)
 | 
			
		||||
 | 
			
		||||
	*s = '\0';
 | 
			
		||||
 | 
			
		||||
	if (gc->fg != 8) {
 | 
			
		||||
	if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
 | 
			
		||||
		if (gc->flags & GRID_FLAG_FG256)
 | 
			
		||||
			c = gc->fg | 0x100;
 | 
			
		||||
		else
 | 
			
		||||
@@ -126,7 +126,7 @@ style_tostring(struct grid_cell *gc)
 | 
			
		||||
		comma = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (gc->bg != 8) {
 | 
			
		||||
	if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
 | 
			
		||||
		if (gc->flags & GRID_FLAG_BG256)
 | 
			
		||||
			c = gc->bg | 0x100;
 | 
			
		||||
		else
 | 
			
		||||
@@ -221,13 +221,13 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
 | 
			
		||||
	struct grid_cell	*gcp;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
			colour_set_fg(gc, gcp->fg | 0x100);
 | 
			
		||||
		else
 | 
			
		||||
			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)
 | 
			
		||||
			colour_set_bg(gc, gcp->bg | 0x100);
 | 
			
		||||
		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
 | 
			
		||||
.Xr sh 1
 | 
			
		||||
commands.
 | 
			
		||||
These must be passed as a single item, which typically means quoting them, for
 | 
			
		||||
example:
 | 
			
		||||
This may be a single argument passed to the shell, for example:
 | 
			
		||||
.Bd -literal -offset indent
 | 
			
		||||
new-window 'vi /etc/passwd'
 | 
			
		||||
.Ed
 | 
			
		||||
.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
 | 
			
		||||
.Op Ar arguments
 | 
			
		||||
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 Li "Append selection" Ta "A" Ta ""
 | 
			
		||||
.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 "Clear selection" Ta "Escape" Ta "C-g"
 | 
			
		||||
.It Li "Copy selection" Ta "Enter" Ta "M-w"
 | 
			
		||||
@@ -934,9 +960,6 @@ in emacs mode, and
 | 
			
		||||
.Ql 10w
 | 
			
		||||
in vi.
 | 
			
		||||
.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:
 | 
			
		||||
.Em vi-edit
 | 
			
		||||
and
 | 
			
		||||
@@ -1094,7 +1117,7 @@ but a different format may be specified with
 | 
			
		||||
.Fl F .
 | 
			
		||||
.It Xo Ic capture-pane
 | 
			
		||||
.Op Fl aepPq
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Op Fl E Ar end-line
 | 
			
		||||
.Op Fl S Ar start-line
 | 
			
		||||
.Op Fl t Ar target-pane
 | 
			
		||||
@@ -3371,19 +3394,40 @@ is given, otherwise the active pane for the session attached to
 | 
			
		||||
.El
 | 
			
		||||
.Sh BUFFERS
 | 
			
		||||
.Nm
 | 
			
		||||
maintains a stack of
 | 
			
		||||
maintains a set of named
 | 
			
		||||
.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
 | 
			
		||||
option are kept; when a new buffer is added, the buffer at the bottom of the
 | 
			
		||||
stack is removed.
 | 
			
		||||
option is reached, the oldest automatically named buffer is deleted.
 | 
			
		||||
Explicitly named are not subject to
 | 
			
		||||
.Ic buffer-limit
 | 
			
		||||
and may be deleted with
 | 
			
		||||
.Ic delete-buffer
 | 
			
		||||
command.
 | 
			
		||||
.Pp
 | 
			
		||||
Buffers may be added using
 | 
			
		||||
.Ic copy-mode
 | 
			
		||||
or the
 | 
			
		||||
.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
 | 
			
		||||
command.
 | 
			
		||||
If a buffer command is used and no buffer is specified, the most
 | 
			
		||||
recently added automatically named buffer is assumed.
 | 
			
		||||
.Pp
 | 
			
		||||
A configurable history buffer is also maintained for each window.
 | 
			
		||||
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.
 | 
			
		||||
After a buffer is selected,
 | 
			
		||||
.Ql %%
 | 
			
		||||
is replaced by the buffer index in
 | 
			
		||||
is replaced by the buffer name in
 | 
			
		||||
.Ar template
 | 
			
		||||
and the result executed as a command.
 | 
			
		||||
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
 | 
			
		||||
.D1 (alias: Ic clearhist )
 | 
			
		||||
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 )
 | 
			
		||||
Delete the buffer at
 | 
			
		||||
.Ar buffer-index ,
 | 
			
		||||
or the top buffer if not specified.
 | 
			
		||||
Delete the buffer named
 | 
			
		||||
.Ar buffer-name ,
 | 
			
		||||
or the most recently added automatically named buffer if not specified.
 | 
			
		||||
.It Xo Ic list-buffers
 | 
			
		||||
.Op Fl F Ar format
 | 
			
		||||
.Xc
 | 
			
		||||
@@ -3435,7 +3479,7 @@ flag, see the
 | 
			
		||||
.Sx FORMATS
 | 
			
		||||
section.
 | 
			
		||||
.It Xo Ic load-buffer
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Ar path
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic loadb )
 | 
			
		||||
@@ -3443,7 +3487,7 @@ Load the contents of the specified paste buffer from
 | 
			
		||||
.Ar path .
 | 
			
		||||
.It Xo Ic paste-buffer
 | 
			
		||||
.Op Fl dpr
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Op Fl s Ar separator
 | 
			
		||||
.Op Fl t Ar target-pane
 | 
			
		||||
.Xc
 | 
			
		||||
@@ -3452,7 +3496,7 @@ Insert the contents of a paste buffer into the specified pane.
 | 
			
		||||
If not specified, paste into the current one.
 | 
			
		||||
With
 | 
			
		||||
.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
 | 
			
		||||
a separator, by default carriage return (CR).
 | 
			
		||||
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.
 | 
			
		||||
.It Xo Ic save-buffer
 | 
			
		||||
.Op Fl a
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Ar path
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic saveb )
 | 
			
		||||
@@ -3478,7 +3522,8 @@ The
 | 
			
		||||
option appends to rather than overwriting the file.
 | 
			
		||||
.It Xo Ic set-buffer
 | 
			
		||||
.Op Fl a
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Op Fl n Ar new-buffer-name
 | 
			
		||||
.Ar data
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic setb )
 | 
			
		||||
@@ -3487,8 +3532,12 @@ Set the contents of the specified buffer to
 | 
			
		||||
The
 | 
			
		||||
.Fl a
 | 
			
		||||
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
 | 
			
		||||
.Op Fl b Ar buffer-index
 | 
			
		||||
.Op Fl b Ar buffer-name
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic showb )
 | 
			
		||||
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. */
 | 
			
		||||
#define CHOOSE_BUFFER_TEMPLATE					\
 | 
			
		||||
	"#{line}: #{buffer_size} bytes: #{buffer_sample}"
 | 
			
		||||
	"#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
 | 
			
		||||
 | 
			
		||||
/* Default template for choose-client. */
 | 
			
		||||
#define CHOOSE_CLIENT_TEMPLATE					\
 | 
			
		||||
@@ -115,7 +115,8 @@ extern char   **environ;
 | 
			
		||||
 | 
			
		||||
/* Default template for list-buffers. */
 | 
			
		||||
#define LIST_BUFFERS_TEMPLATE					\
 | 
			
		||||
	"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
 | 
			
		||||
	"#{buffer_name}: #{buffer_size} bytes: "		\
 | 
			
		||||
	"\"#{buffer_sample}\""
 | 
			
		||||
 | 
			
		||||
/* Default template for list-clients. */
 | 
			
		||||
#define LIST_CLIENTS_TEMPLATE					\
 | 
			
		||||
@@ -579,6 +580,7 @@ enum mode_key_cmd {
 | 
			
		||||
	MODEKEYCOPY_SEARCHREVERSE,
 | 
			
		||||
	MODEKEYCOPY_SEARCHUP,
 | 
			
		||||
	MODEKEYCOPY_SELECTLINE,
 | 
			
		||||
	MODEKEYCOPY_STARTNAMEDBUFFER,
 | 
			
		||||
	MODEKEYCOPY_STARTNUMBERPREFIX,
 | 
			
		||||
	MODEKEYCOPY_STARTOFLINE,
 | 
			
		||||
	MODEKEYCOPY_STARTSELECTION,
 | 
			
		||||
@@ -889,6 +891,7 @@ struct window_choose_mode_item {
 | 
			
		||||
/* Child window structure. */
 | 
			
		||||
struct window_pane {
 | 
			
		||||
	u_int		 id;
 | 
			
		||||
	u_int		 active_point;
 | 
			
		||||
 | 
			
		||||
	struct window	*window;
 | 
			
		||||
 | 
			
		||||
@@ -908,7 +911,8 @@ struct window_pane {
 | 
			
		||||
#define PANE_RESIZE 0x8
 | 
			
		||||
#define PANE_FOCUSPUSH 0x10
 | 
			
		||||
 | 
			
		||||
	char		*cmd;
 | 
			
		||||
	int		 argc;
 | 
			
		||||
	char	       **argv;
 | 
			
		||||
	char		*shell;
 | 
			
		||||
	int		 cwd;
 | 
			
		||||
 | 
			
		||||
@@ -945,6 +949,7 @@ struct window_pane {
 | 
			
		||||
};
 | 
			
		||||
TAILQ_HEAD(window_panes, window_pane);
 | 
			
		||||
RB_HEAD(window_pane_tree, window_pane);
 | 
			
		||||
ARRAY_DECL(window_pane_list, struct window_pane *);
 | 
			
		||||
 | 
			
		||||
/* Window structure. */
 | 
			
		||||
struct window {
 | 
			
		||||
@@ -1022,8 +1027,6 @@ struct layout_cell {
 | 
			
		||||
	u_int		 yoff;
 | 
			
		||||
 | 
			
		||||
	struct window_pane *wp;
 | 
			
		||||
	struct window_pane *lastwp;
 | 
			
		||||
 | 
			
		||||
	struct layout_cells cells;
 | 
			
		||||
 | 
			
		||||
	TAILQ_ENTRY(layout_cell) entry;
 | 
			
		||||
@@ -1033,6 +1036,13 @@ struct layout_cell {
 | 
			
		||||
struct paste_buffer {
 | 
			
		||||
	char		*data;
 | 
			
		||||
	size_t		 size;
 | 
			
		||||
 | 
			
		||||
	char		*name;
 | 
			
		||||
	int		 automatic;
 | 
			
		||||
	u_int		 order;
 | 
			
		||||
 | 
			
		||||
	RB_ENTRY(paste_buffer) name_entry;
 | 
			
		||||
	RB_ENTRY(paste_buffer) time_entry;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Environment variable. */
 | 
			
		||||
@@ -1127,6 +1137,9 @@ LIST_HEAD(tty_terms, tty_term);
 | 
			
		||||
#define MOUSE_WHEEL_UP 0
 | 
			
		||||
#define MOUSE_WHEEL_DOWN 1
 | 
			
		||||
 | 
			
		||||
/* Mouse wheel multipler. */
 | 
			
		||||
#define MOUSE_WHEEL_SCALE 3
 | 
			
		||||
 | 
			
		||||
/* Mouse event bits. */
 | 
			
		||||
#define MOUSE_EVENT_DOWN 0x1
 | 
			
		||||
#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_SESSION_USAGE "[-s src-session] [-t dst-session]"
 | 
			
		||||
#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 */
 | 
			
		||||
extern struct options global_options;
 | 
			
		||||
@@ -1705,13 +1718,14 @@ void	tty_keys_free(struct tty *);
 | 
			
		||||
int	tty_keys_next(struct tty *);
 | 
			
		||||
 | 
			
		||||
/* 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_index(u_int);
 | 
			
		||||
struct paste_buffer *paste_get_name(const char *);
 | 
			
		||||
int		 paste_free_top(void);
 | 
			
		||||
int		 paste_free_index(u_int);
 | 
			
		||||
void		 paste_add(char *, size_t, u_int);
 | 
			
		||||
int		 paste_replace(u_int, char *, size_t);
 | 
			
		||||
int		 paste_free_name(const char *);
 | 
			
		||||
void		 paste_add(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);
 | 
			
		||||
void		 paste_send_pane(struct paste_buffer *, struct window_pane *,
 | 
			
		||||
		     const char *, int);
 | 
			
		||||
@@ -1732,8 +1746,9 @@ long long	 args_strtonum(
 | 
			
		||||
/* cmd.c */
 | 
			
		||||
int		 cmd_pack_argv(int, char **, char *, size_t);
 | 
			
		||||
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 **);
 | 
			
		||||
char		*cmd_stringify_argv(int, char **);
 | 
			
		||||
struct cmd	*cmd_parse(int, char **, const char *, u_int, char **);
 | 
			
		||||
size_t		 cmd_print(struct cmd *, char *, size_t);
 | 
			
		||||
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 *);
 | 
			
		||||
struct window	*window_find_by_id(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 *,
 | 
			
		||||
		     u_int, u_int, u_int, char **);
 | 
			
		||||
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);
 | 
			
		||||
void		 window_pane_destroy(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 *,
 | 
			
		||||
		     struct termios *, char **);
 | 
			
		||||
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 *);
 | 
			
		||||
struct session	*session_find(const char *);
 | 
			
		||||
struct session	*session_find_by_id(u_int);
 | 
			
		||||
struct session	*session_create(const char *, const char *, const char *, int,
 | 
			
		||||
		     struct environ *, struct termios *, int, u_int, u_int,
 | 
			
		||||
		     char **);
 | 
			
		||||
struct session	*session_create(const char *, int, char **, const char *,
 | 
			
		||||
		     int, struct environ *, struct termios *, int, u_int,
 | 
			
		||||
		     u_int, char **);
 | 
			
		||||
void		 session_destroy(struct session *);
 | 
			
		||||
int		 session_check_name(const char *);
 | 
			
		||||
void		 session_update_activity(struct session *);
 | 
			
		||||
struct session	*session_next_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 **);
 | 
			
		||||
struct winlink	*session_attach(
 | 
			
		||||
		     struct session *, struct window *, int, char **);
 | 
			
		||||
struct winlink	*session_attach(struct session *, struct window *, int,
 | 
			
		||||
		     char **);
 | 
			
		||||
int		 session_detach(struct session *, struct winlink *);
 | 
			
		||||
struct winlink	*session_has(struct session *, struct window *);
 | 
			
		||||
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)
 | 
			
		||||
			m->scroll = 1;
 | 
			
		||||
		else
 | 
			
		||||
			m->scroll = 3;
 | 
			
		||||
			m->scroll = MOUSE_WHEEL_SCALE;
 | 
			
		||||
		if (b & MOUSE_MASK_META)
 | 
			
		||||
			m->scroll *= 3;
 | 
			
		||||
			m->scroll *= MOUSE_WHEEL_SCALE;
 | 
			
		||||
		if (b & MOUSE_MASK_CTRL)
 | 
			
		||||
			m->scroll *= 3;
 | 
			
		||||
			m->scroll *= MOUSE_WHEEL_SCALE;
 | 
			
		||||
 | 
			
		||||
		b &= MOUSE_MASK_BUTTONS;
 | 
			
		||||
		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 screen			*s = &data->screen;
 | 
			
		||||
	struct window_choose_mode_item	*item;
 | 
			
		||||
	u_int				 idx;
 | 
			
		||||
	u_int				 idx, i, n;
 | 
			
		||||
 | 
			
		||||
	if (m->event == MOUSE_EVENT_WHEEL) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Don't use m->scroll and just move line-by-line or it's
 | 
			
		||||
		 * annoying.
 | 
			
		||||
		 * Multiple line scrolling by default is annoying, so scale
 | 
			
		||||
		 * m->scroll back down.
 | 
			
		||||
		 */
 | 
			
		||||
		if (m->wheel == MOUSE_WHEEL_UP)
 | 
			
		||||
			window_choose_key(wp, sess, KEYC_UP);
 | 
			
		||||
		else
 | 
			
		||||
			window_choose_key(wp, sess, KEYC_DOWN);
 | 
			
		||||
		n = m->scroll;
 | 
			
		||||
		if (n >= MOUSE_WHEEL_SCALE)
 | 
			
		||||
			n /= MOUSE_WHEEL_SCALE;
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,14 +54,15 @@ void	window_copy_update_cursor(struct window_pane *, u_int, u_int);
 | 
			
		||||
void	window_copy_start_selection(struct window_pane *);
 | 
			
		||||
int	window_copy_update_selection(struct window_pane *, int);
 | 
			
		||||
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_pipe(
 | 
			
		||||
	    struct window_pane *, struct session *, int, const char *);
 | 
			
		||||
void	window_copy_copy_selection(struct window_pane *, int);
 | 
			
		||||
void	window_copy_append_selection(struct window_pane *, int);
 | 
			
		||||
void	window_copy_copy_buffer(struct window_pane *, const char *, void *,
 | 
			
		||||
	    size_t);
 | 
			
		||||
void	window_copy_copy_pipe(struct window_pane *, struct session *,
 | 
			
		||||
	    const char *, const char *);
 | 
			
		||||
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_copy_line(
 | 
			
		||||
	    struct window_pane *, char **, size_t *, u_int, u_int, u_int);
 | 
			
		||||
void	window_copy_copy_line(struct window_pane *, char **, size_t *, u_int,
 | 
			
		||||
	    u_int, u_int);
 | 
			
		||||
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);
 | 
			
		||||
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 {
 | 
			
		||||
	WINDOW_COPY_OFF,
 | 
			
		||||
	WINDOW_COPY_NAMEDBUFFER,
 | 
			
		||||
	WINDOW_COPY_NUMERICPREFIX,
 | 
			
		||||
	WINDOW_COPY_SEARCHUP,
 | 
			
		||||
	WINDOW_COPY_SEARCHDOWN,
 | 
			
		||||
@@ -417,7 +419,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case MODEKEYCOPY_APPENDSELECTION:
 | 
			
		||||
		if (sess != NULL) {
 | 
			
		||||
			window_copy_append_selection(wp, data->numprefix);
 | 
			
		||||
			window_copy_append_selection(wp, NULL);
 | 
			
		||||
			window_pane_reset_mode(wp);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@@ -543,7 +545,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
 | 
			
		||||
		if (sess != NULL &&
 | 
			
		||||
		    (cmd == MODEKEYCOPY_COPYLINE ||
 | 
			
		||||
		    cmd == MODEKEYCOPY_COPYENDOFLINE)) {
 | 
			
		||||
			window_copy_copy_selection(wp, -1);
 | 
			
		||||
			window_copy_copy_selection(wp, NULL);
 | 
			
		||||
			window_pane_reset_mode(wp);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@@ -554,14 +556,14 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
 | 
			
		||||
		break;
 | 
			
		||||
	case MODEKEYCOPY_COPYPIPE:
 | 
			
		||||
		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);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case MODEKEYCOPY_COPYSELECTION:
 | 
			
		||||
		if (sess != NULL) {
 | 
			
		||||
			window_copy_copy_selection(wp, data->numprefix);
 | 
			
		||||
			window_copy_copy_selection(wp, NULL);
 | 
			
		||||
			window_pane_reset_mode(wp);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@@ -676,6 +678,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
 | 
			
		||||
		case WINDOW_COPY_JUMPBACK:
 | 
			
		||||
		case WINDOW_COPY_JUMPTOFORWARD:
 | 
			
		||||
		case WINDOW_COPY_JUMPTOBACK:
 | 
			
		||||
		case WINDOW_COPY_NAMEDBUFFER:
 | 
			
		||||
		case WINDOW_COPY_NUMERICPREFIX:
 | 
			
		||||
			break;
 | 
			
		||||
		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->inputstr = '\0';
 | 
			
		||||
		goto input_on;
 | 
			
		||||
	case MODEKEYCOPY_STARTNAMEDBUFFER:
 | 
			
		||||
		data->inputtype = WINDOW_COPY_NAMEDBUFFER;
 | 
			
		||||
		data->inputprompt = "Buffer";
 | 
			
		||||
		*data->inputstr = '\0';
 | 
			
		||||
		goto input_on;
 | 
			
		||||
	case MODEKEYCOPY_STARTNUMBERPREFIX:
 | 
			
		||||
		key &= KEYC_MASK_KEY;
 | 
			
		||||
		if (key >= '0' && key <= '9') {
 | 
			
		||||
@@ -814,6 +822,11 @@ window_copy_key_input(struct window_pane *wp, int key)
 | 
			
		||||
			data->searchtype = data->inputtype;
 | 
			
		||||
			data->searchstr = xstrdup(data->inputstr);
 | 
			
		||||
			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:
 | 
			
		||||
			window_copy_goto_line(wp, data->inputstr);
 | 
			
		||||
			*data->inputstr = '\0';
 | 
			
		||||
@@ -918,7 +931,7 @@ reset_mode:
 | 
			
		||||
	s->mode &= ~MODE_MOUSE_BUTTON;
 | 
			
		||||
	s->mode |= MODE_MOUSE_STANDARD;
 | 
			
		||||
	if (sess != NULL) {
 | 
			
		||||
		window_copy_copy_selection(wp, -1);
 | 
			
		||||
		window_copy_copy_selection(wp, NULL);
 | 
			
		||||
		window_pane_reset_mode(wp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1452,9 +1465,9 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (idx == -1) {
 | 
			
		||||
		limit = options_get_number(&global_options, "buffer-limit");
 | 
			
		||||
		paste_add(buf, len, limit);
 | 
			
		||||
	} else if (paste_replace(idx, buf, len) != 0)
 | 
			
		||||
	if (paste_set(buf, len, bufname, NULL) != 0)
 | 
			
		||||
		free(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_copy_copy_pipe(
 | 
			
		||||
    struct window_pane *wp, struct session *sess, int idx, const char *arg)
 | 
			
		||||
window_copy_copy_pipe(struct window_pane *wp, struct session *sess,
 | 
			
		||||
    const char *bufname, const char *arg)
 | 
			
		||||
{
 | 
			
		||||
	void		*buf;
 | 
			
		||||
	size_t		 len;
 | 
			
		||||
@@ -1486,11 +1496,11 @@ window_copy_copy_pipe(
 | 
			
		||||
	job = job_run(arg, sess, NULL, NULL, NULL);
 | 
			
		||||
	bufferevent_write(job->event, buf, len);
 | 
			
		||||
 | 
			
		||||
	window_copy_copy_buffer(wp, idx, buf, len);
 | 
			
		||||
	window_copy_copy_buffer(wp, bufname, buf, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_copy_copy_selection(struct window_pane *wp, int idx)
 | 
			
		||||
window_copy_copy_selection(struct window_pane *wp, const char *bufname)
 | 
			
		||||
{
 | 
			
		||||
	void*	buf;
 | 
			
		||||
	size_t	len;
 | 
			
		||||
@@ -1499,17 +1509,16 @@ window_copy_copy_selection(struct window_pane *wp, int idx)
 | 
			
		||||
	if (buf == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	window_copy_copy_buffer(wp, idx, buf, len);
 | 
			
		||||
	window_copy_copy_buffer(wp, bufname, buf, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_copy_append_selection(struct window_pane *wp, int idx)
 | 
			
		||||
window_copy_append_selection(struct window_pane *wp, const char *bufname)
 | 
			
		||||
{
 | 
			
		||||
	char			*buf;
 | 
			
		||||
	struct paste_buffer	*pb;
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
	u_int			 limit;
 | 
			
		||||
	struct screen_write_ctx	 ctx;
 | 
			
		||||
	char				*buf;
 | 
			
		||||
	struct paste_buffer		*pb;
 | 
			
		||||
	size_t				 len;
 | 
			
		||||
	struct screen_write_ctx		 ctx;
 | 
			
		||||
 | 
			
		||||
	buf = window_copy_get_selection(wp, &len);
 | 
			
		||||
	if (buf == NULL)
 | 
			
		||||
@@ -1521,24 +1530,19 @@ window_copy_append_selection(struct window_pane *wp, int idx)
 | 
			
		||||
		screen_write_stop(&ctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (idx == -1)
 | 
			
		||||
		idx = 0;
 | 
			
		||||
 | 
			
		||||
	if (idx == 0 && paste_get_top() == NULL) {
 | 
			
		||||
		limit = options_get_number(&global_options, "buffer-limit");
 | 
			
		||||
		paste_add(buf, len, limit);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pb = paste_get_index(idx);
 | 
			
		||||
	if (bufname == NULL || *bufname == '\0') {
 | 
			
		||||
		pb = paste_get_top();
 | 
			
		||||
		if (pb != NULL)
 | 
			
		||||
			bufname = pb->name;
 | 
			
		||||
	} else
 | 
			
		||||
		pb = paste_get_name(bufname);
 | 
			
		||||
	if (pb != NULL) {
 | 
			
		||||
		buf = xrealloc(buf, 1, len + pb->size);
 | 
			
		||||
		memmove(buf + pb->size, buf, len);
 | 
			
		||||
		memcpy(buf, pb->data, pb->size);
 | 
			
		||||
		len += pb->size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (paste_replace(idx, buf, len) != 0)
 | 
			
		||||
	if (paste_set(buf, len, bufname, NULL) != 0)
 | 
			
		||||
		free(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										327
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										327
									
								
								window.c
									
									
									
									
									
								
							@@ -55,15 +55,14 @@ struct windows windows;
 | 
			
		||||
struct window_pane_tree all_window_panes;
 | 
			
		||||
u_int	next_window_pane_id;
 | 
			
		||||
u_int	next_window_id;
 | 
			
		||||
 | 
			
		||||
struct window_pane *window_pane_active_set(struct window_pane *,
 | 
			
		||||
	    struct window_pane *);
 | 
			
		||||
void	window_pane_active_lost(struct window_pane *, struct window_pane *);
 | 
			
		||||
u_int	next_active_point;
 | 
			
		||||
 | 
			
		||||
void	window_pane_timer_callback(int, short, void *);
 | 
			
		||||
void	window_pane_read_callback(struct bufferevent *, 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);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
@@ -307,7 +306,7 @@ window_create1(u_int sx, u_int sy)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
    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);
 | 
			
		||||
	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) {
 | 
			
		||||
		window_destroy(w);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
@@ -386,64 +385,6 @@ window_resize(struct window *w, u_int sx, u_int 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
 | 
			
		||||
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;
 | 
			
		||||
	w->last = w->active;
 | 
			
		||||
	w->active = wp;
 | 
			
		||||
	window_pane_active_lost(w->last, wp);
 | 
			
		||||
	while (!window_pane_visible(w->active)) {
 | 
			
		||||
		w->active = TAILQ_PREV(w->active, window_panes, entry);
 | 
			
		||||
		if (w->active == NULL)
 | 
			
		||||
@@ -459,6 +399,7 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
 | 
			
		||||
		if (w->active == wp)
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
	w->active->active_point = next_active_point++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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++;
 | 
			
		||||
	RB_INSERT(window_pane_tree, &all_window_panes, wp);
 | 
			
		||||
 | 
			
		||||
	wp->cmd = NULL;
 | 
			
		||||
	wp->argc = 0;
 | 
			
		||||
	wp->argv = NULL;
 | 
			
		||||
	wp->shell = NULL;
 | 
			
		||||
	wp->cwd = -1;
 | 
			
		||||
 | 
			
		||||
@@ -770,16 +712,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
void
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
	if (event_initialized(&wp->changes_timer))
 | 
			
		||||
@@ -808,30 +740,32 @@ window_pane_destroy(struct window_pane *wp)
 | 
			
		||||
 | 
			
		||||
	close(wp->cwd);
 | 
			
		||||
	free(wp->shell);
 | 
			
		||||
	free(wp->cmd);
 | 
			
		||||
	cmd_free_argv(wp->argc, wp->argv);
 | 
			
		||||
	free(wp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
 | 
			
		||||
    const char *shell, int cwd, struct environ *env, struct termios *tio,
 | 
			
		||||
    char **cause)
 | 
			
		||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
			
		||||
    const char *path, const char *shell, int cwd, struct environ *env,
 | 
			
		||||
    struct termios *tio, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
	char		*argv0, paneid[16];
 | 
			
		||||
	const char	*ptr;
 | 
			
		||||
	char		*argv0, *cmd, **argvp, paneid[16];
 | 
			
		||||
	const char	*ptr, *first;
 | 
			
		||||
	struct termios	 tio2;
 | 
			
		||||
#ifdef HAVE_UTEMPTER
 | 
			
		||||
	char		 s[32];
 | 
			
		||||
#endif
 | 
			
		||||
	int		 i;
 | 
			
		||||
 | 
			
		||||
	if (wp->fd != -1) {
 | 
			
		||||
		bufferevent_free(wp->event);
 | 
			
		||||
		close(wp->fd);
 | 
			
		||||
	}
 | 
			
		||||
	if (cmd != NULL) {
 | 
			
		||||
		free(wp->cmd);
 | 
			
		||||
		wp->cmd = xstrdup(cmd);
 | 
			
		||||
	if (argc > 0) {
 | 
			
		||||
		cmd_free_argv(wp->argc, wp->argv);
 | 
			
		||||
		wp->argc = argc;
 | 
			
		||||
		wp->argv = cmd_copy_argv(argc, argv);
 | 
			
		||||
	}
 | 
			
		||||
	if (shell != NULL) {
 | 
			
		||||
		free(wp->shell);
 | 
			
		||||
@@ -842,7 +776,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
 | 
			
		||||
		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);
 | 
			
		||||
	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:
 | 
			
		||||
		wp->fd = -1;
 | 
			
		||||
		xasprintf(cause, "%s: %s", cmd, strerror(errno));
 | 
			
		||||
		free(cmd);
 | 
			
		||||
		return (-1);
 | 
			
		||||
	case 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);
 | 
			
		||||
		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')
 | 
			
		||||
				xasprintf(&argv0, "%s", ptr + 1);
 | 
			
		||||
			else
 | 
			
		||||
				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");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* No command; fork a login shell. */
 | 
			
		||||
		if (ptr != NULL && *(ptr + 1) != '\0')
 | 
			
		||||
			xasprintf(&argv0, "-%s", ptr + 1);
 | 
			
		||||
		else
 | 
			
		||||
			xasprintf(&argv0, "-%s", wp->shell);
 | 
			
		||||
		execl(wp->shell, argv0, (char *) NULL);
 | 
			
		||||
		execl(wp->shell, argv0, (char *)NULL);
 | 
			
		||||
		fatal("execl failed");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -909,10 +857,11 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
 | 
			
		||||
 | 
			
		||||
	setblocking(wp->fd, 0);
 | 
			
		||||
 | 
			
		||||
	wp->event = bufferevent_new(wp->fd,
 | 
			
		||||
	    window_pane_read_callback, NULL, window_pane_error_callback, wp);
 | 
			
		||||
	wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
 | 
			
		||||
	    window_pane_error_callback, wp);
 | 
			
		||||
	bufferevent_enable(wp->event, EV_READ|EV_WRITE);
 | 
			
		||||
 | 
			
		||||
	free(cmd);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1201,114 +1150,198 @@ window_pane_search(struct window_pane *wp, const char *searchstr,
 | 
			
		||||
	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 *
 | 
			
		||||
window_pane_find_up(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane     *wp2;
 | 
			
		||||
	u_int			left, top;
 | 
			
		||||
	struct window_pane	*next, *best;
 | 
			
		||||
	u_int			 edge, left, right, end;
 | 
			
		||||
	struct window_pane_list	 list;
 | 
			
		||||
	int			 found;
 | 
			
		||||
 | 
			
		||||
	if (wp == NULL || !window_pane_visible(wp))
 | 
			
		||||
		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;
 | 
			
		||||
	right = wp->xoff + wp->sx;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
 | 
			
		||||
		if (!window_pane_visible(wp2))
 | 
			
		||||
	TAILQ_FOREACH(next, &wp->window->panes, entry) {
 | 
			
		||||
		if (next == wp || !window_pane_visible(next))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (wp2->yoff + wp2->sy + 1 != top)
 | 
			
		||||
		if (next->yoff + next->sy + 1 != edge)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
 | 
			
		||||
			return (window_pane_active_set(wp, wp2));
 | 
			
		||||
		end = next->xoff + next->sx - 1;
 | 
			
		||||
 | 
			
		||||
		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. */
 | 
			
		||||
struct window_pane *
 | 
			
		||||
window_pane_find_down(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane     *wp2;
 | 
			
		||||
	u_int			left, bottom;
 | 
			
		||||
	struct window_pane	*next, *best;
 | 
			
		||||
	u_int			 edge, left, right, end;
 | 
			
		||||
	struct window_pane_list	 list;
 | 
			
		||||
	int			 found;
 | 
			
		||||
 | 
			
		||||
	if (wp == NULL || !window_pane_visible(wp))
 | 
			
		||||
		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;
 | 
			
		||||
	right = wp->xoff + wp->sx;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
 | 
			
		||||
		if (!window_pane_visible(wp2))
 | 
			
		||||
	TAILQ_FOREACH(next, &wp->window->panes, entry) {
 | 
			
		||||
		if (next == wp || !window_pane_visible(next))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (wp2->yoff != bottom)
 | 
			
		||||
		if (next->yoff != edge)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
 | 
			
		||||
			return (window_pane_active_set(wp, wp2));
 | 
			
		||||
		end = next->xoff + next->sx - 1;
 | 
			
		||||
 | 
			
		||||
		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, adjacent to the left side and
 | 
			
		||||
 * containing the top edge.
 | 
			
		||||
 */
 | 
			
		||||
/* Find the pane directly to the left of another. */
 | 
			
		||||
struct window_pane *
 | 
			
		||||
window_pane_find_left(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane     *wp2;
 | 
			
		||||
	u_int			left, top;
 | 
			
		||||
	struct window_pane	*next, *best;
 | 
			
		||||
	u_int			 edge, top, bottom, end;
 | 
			
		||||
	struct window_pane_list	 list;
 | 
			
		||||
	int			 found;
 | 
			
		||||
 | 
			
		||||
	if (wp == NULL || !window_pane_visible(wp))
 | 
			
		||||
		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;
 | 
			
		||||
	bottom = wp->yoff + wp->sy;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
 | 
			
		||||
		if (!window_pane_visible(wp2))
 | 
			
		||||
	TAILQ_FOREACH(next, &wp->window->panes, entry) {
 | 
			
		||||
		if (next == wp || !window_pane_visible(next))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (wp2->xoff + wp2->sx + 1 != left)
 | 
			
		||||
		if (next->xoff + next->sx + 1 != edge)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
 | 
			
		||||
			return (window_pane_active_set(wp, wp2));
 | 
			
		||||
		end = next->yoff + next->sy - 1;
 | 
			
		||||
 | 
			
		||||
		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, that is adjacent to the
 | 
			
		||||
 * right edge and including the top edge.
 | 
			
		||||
 */
 | 
			
		||||
/* Find the pane directly to the right of another. */
 | 
			
		||||
struct window_pane *
 | 
			
		||||
window_pane_find_right(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane     *wp2;
 | 
			
		||||
	u_int			right, top;
 | 
			
		||||
	struct window_pane	*next, *best;
 | 
			
		||||
	u_int			 edge, top, bottom, end;
 | 
			
		||||
	struct window_pane_list	 list;
 | 
			
		||||
	int			 found;
 | 
			
		||||
 | 
			
		||||
	if (wp == NULL || !window_pane_visible(wp))
 | 
			
		||||
		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;
 | 
			
		||||
	bottom = wp->yoff + wp->sy;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
 | 
			
		||||
		if (!window_pane_visible(wp2))
 | 
			
		||||
	TAILQ_FOREACH(next, &wp->window->panes, entry) {
 | 
			
		||||
		if (next == wp || !window_pane_visible(next))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (wp2->xoff != right)
 | 
			
		||||
		if (next->xoff != edge)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
 | 
			
		||||
			return (window_pane_active_set(wp, wp2));
 | 
			
		||||
		end = next->yoff + next->sy - 1;
 | 
			
		||||
 | 
			
		||||
		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 */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user