예제 #1
0
enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args	*args = self->args;
	struct winlink	*wl;
	const char	*layoutname;
	int		 next, previous, layout;

	if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
		return (CMD_RETURN_ERROR);
	server_unzoom_window(wl->window);

	next = self->entry == &cmd_next_layout_entry;
	if (args_has(self->args, 'n'))
		next = 1;
	previous = self->entry == &cmd_previous_layout_entry;
	if (args_has(self->args, 'p'))
		previous = 1;

	if (next || previous) {
		if (next)
			layout = layout_set_next(wl->window);
		else
			layout = layout_set_previous(wl->window);
		server_redraw_window(wl->window);
		cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
		return (CMD_RETURN_NORMAL);
	}

	if (args->argc == 0)
		layout = wl->window->lastlayout;
	else
		layout = layout_set_lookup(args->argv[0]);
	if (layout != -1) {
		layout = layout_set_select(wl->window, layout);
		server_redraw_window(wl->window);
		cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
		return (CMD_RETURN_NORMAL);
	}

	if (args->argc != 0) {
		layoutname = args->argv[0];
		if (layout_parse(wl->window, layoutname) == -1) {
			cmdq_error(cmdq, "can't set layout: %s", layoutname);
			return (CMD_RETURN_ERROR);
		}
		server_redraw_window(wl->window);
		cmdq_info(cmdq, "arranging in: %s", layoutname);
	}
	return (CMD_RETURN_NORMAL);
}
예제 #2
0
int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct winlink		*wl;
	struct window_pane	*loopwp, *nextwp, *wp;

	if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
		return (-1);

	if (window_count_panes(wl->window) == 1) {
		/* Only one pane, kill the window. */
		server_kill_window(wl->window);
		recalculate_sizes();
		return (0);
	}

	if (args_has(self->args, 'a')) {
		loopwp = TAILQ_FIRST(&wl->window->panes);
		while (loopwp != NULL) {
			nextwp = TAILQ_NEXT(loopwp, entry);
			if (loopwp != wp) {
				layout_close_pane(loopwp);
				window_remove_pane(wl->window, loopwp);
			}
			loopwp = nextwp;
		}
	} else {
		layout_close_pane(wp);
		window_remove_pane(wl->window, wp);
	}
	server_redraw_window(wl->window);

	return (0);
}
예제 #3
0
int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct winlink		*wl;
	const char	       	*errstr;
	struct window_pane	*wp;
	u_int			 adjust;

	if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
		return (-1);

	if (args->argc == 0)
		adjust = 1;
	else {
		adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
		if (errstr != NULL) {
			ctx->error(ctx, "adjustment %s", errstr);
			return (-1);
		}
	}

	layout_list_add(wp->window);
	if (args_has(self->args, 'L'))
		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust);
	else if (args_has(self->args, 'R'))
		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
	else if (args_has(self->args, 'U'))
		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust);
	else if (args_has(self->args, 'D'))
		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
	server_redraw_window(wl->window);

	return (0);
}
예제 #4
0
void
window_clock_timer(struct window_pane *wp)
{
	struct window_clock_mode_data	*data = wp->modedata;
	struct tm			 now, then;
	time_t				 t;

	t = time(NULL);
	gmtime_r(&t, &now);
	gmtime_r(&data->tim, &then);
	if (now.tm_min == then.tm_min)
		return;
	data->tim = t;

	window_clock_draw_screen(wp);
	server_redraw_window(wp->window);
}
예제 #5
0
static enum cmd_retval
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
{
	struct args		*args = self->args;
	struct spawn_context	 sc;
	struct session		*s = item->target.s;
	struct winlink		*wl = item->target.wl;
	char			*cause = NULL;
	const char		*add;
	struct args_value	*value;

	memset(&sc, 0, sizeof sc);
	sc.item = item;
	sc.s = s;
	sc.wl = wl;

	sc.name = NULL;
	sc.argc = args->argc;
	sc.argv = args->argv;
	sc.environ = environ_create();

	add = args_first_value(args, 'e', &value);
	while (add != NULL) {
		environ_put(sc.environ, add);
		add = args_next_value(&value);
	}

	sc.idx = -1;
	sc.cwd = args_get(args, 'c');

	sc.flags = SPAWN_RESPAWN;
	if (args_has(args, 'k'))
		sc.flags |= SPAWN_KILL;

	if (spawn_window(&sc, &cause) == NULL) {
		cmdq_error(item, "respawn window failed: %s", cause);
		free(cause);
		return (CMD_RETURN_ERROR);
	}

	server_redraw_window(wl->window);

	environ_free(sc.environ);
	return (CMD_RETURN_NORMAL);
}
예제 #6
0
int
cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct session		*dst_s;
	struct winlink		*src_wl, *dst_wl;
	struct window		*src_w, *dst_w;
	struct window_pane	*src_wp, *dst_wp;
	char			*cause;
	int			 size, percentage, dst_idx;
	enum layout_type	 type;
	struct layout_cell	*lc;

	dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp);
	if (dst_wl == NULL)
		return (-1);
	dst_w = dst_wl->window;
	dst_idx = dst_wl->idx;

	src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
	if (src_wl == NULL)
		return (-1);
	src_w = src_wl->window;

	if (src_w == dst_w) {
		ctx->error(ctx, "can't join a pane to its own window");
		return (-1);
	}

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 'l')) {
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
		if (cause != NULL) {
			ctx->error(ctx, "size %s", cause);
			xfree(cause);
			return (-1);
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, 100, &cause);
		if (cause != NULL) {
			ctx->error(ctx, "percentage %s", cause);
			xfree(cause);
			return (-1);
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (dst_wp->sy * percentage) / 100;
		else
			size = (dst_wp->sx * percentage) / 100;
	}

	if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) {
		ctx->error(ctx, "create pane failed: pane too small");
		return (-1);
	}

	layout_close_pane(src_wp);

	if (src_w->active == src_wp) {
		src_w->active = TAILQ_PREV(src_wp, window_panes, entry);
		if (src_w->active == NULL)
			src_w->active = TAILQ_NEXT(src_wp, entry);
	}
	TAILQ_REMOVE(&src_w->panes, src_wp, entry);

	if (window_count_panes(src_w) == 0)
		server_kill_window(src_w);

	src_wp->window = dst_w;
	TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
	layout_assign_pane(lc, src_wp);

	recalculate_sizes();

	server_redraw_window(src_w);
	server_redraw_window(dst_w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(dst_w, src_wp);
		session_select(dst_s, dst_idx);
		server_redraw_session(dst_s);
	} else
		server_status_session(dst_s);

	return (0);
}
예제 #7
0
static enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args	*args = self->args;
	struct winlink	*wl = cmdq->state.tflag.wl;
	struct window	*w;
	const char	*layoutname;
	char		*oldlayout;
	int		 next, previous, layout;

	w = wl->window;
	server_unzoom_window(w);

	next = self->entry == &cmd_next_layout_entry;
	if (args_has(args, 'n'))
		next = 1;
	previous = self->entry == &cmd_previous_layout_entry;
	if (args_has(args, 'p'))
		previous = 1;

	oldlayout = w->old_layout;
	w->old_layout = layout_dump(w->layout_root);

	if (next || previous) {
		if (next)
			layout_set_next(w);
		else
			layout_set_previous(w);
		goto changed;
	}

	if (!args_has(args, 'o')) {
		if (args->argc == 0)
			layout = w->lastlayout;
		else
			layout = layout_set_lookup(args->argv[0]);
		if (layout != -1) {
			layout_set_select(w, layout);
			goto changed;
		}
	}

	if (args->argc != 0)
		layoutname = args->argv[0];
	else if (args_has(args, 'o'))
		layoutname = oldlayout;
	else
		layoutname = NULL;

	if (layoutname != NULL) {
		if (layout_parse(w, layoutname) == -1) {
			cmdq_error(cmdq, "can't set layout: %s", layoutname);
			goto error;
		}
		goto changed;
	}

	free(oldlayout);
	return (CMD_RETURN_NORMAL);

changed:
	free(oldlayout);
	server_redraw_window(w);
	return (CMD_RETURN_NORMAL);

error:
	free(w->old_layout);
	w->old_layout = oldlayout;
	return (CMD_RETURN_ERROR);
}
예제 #8
0
int
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct session		*s;
	struct winlink		*wl;
	struct window		*w;
	struct window_pane	*wp, *new_wp = NULL;
	struct environ		 env;
	char		 	*cmd, *cwd, *cause;
	const char		*shell;
	u_int			 hlimit, paneidx;
	int			 size, percentage;
	enum layout_type	 type;
	struct layout_cell	*lc;

	if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
		return (-1);
	w = wl->window;

	environ_init(&env);
	environ_copy(&global_environ, &env);
	environ_copy(&s->environ, &env);
	server_fill_environ(s, &env);

	if (args->argc == 0)
		cmd = options_get_string(&s->options, "default-command");
	else
		cmd = args->argv[0];
	cwd = options_get_string(&s->options, "default-path");
	if (*cwd == '\0') {
		if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
			cwd = ctx->cmdclient->cwd;
		else
			cwd = s->cwd;
	}

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 's')) {
		size = args_strtonum(args, 's', 0, INT_MAX, &cause);
		if (cause != NULL) {
			ctx->error(ctx, "size %s", cause);
			xfree(cause);
			return (-1);
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
		if (cause != NULL) {
			ctx->error(ctx, "percentage %s", cause);
			xfree(cause);
			return (-1);
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (wp->sy * percentage) / 100;
		else
			size = (wp->sx * percentage) / 100;
	}
	hlimit = options_get_number(&s->options, "history-limit");

	shell = options_get_string(&s->options, "default-shell");
	if (*shell == '\0' || areshell(shell))
		shell = _PATH_BSHELL;

	if ((lc = layout_split_pane(wp, type, size)) == NULL) {
		cause = xstrdup("pane too small");
		goto error;
	}
	new_wp = window_add_pane(w, hlimit);
	if (window_pane_spawn(
	    new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
		goto error;
	layout_assign_pane(lc, new_wp);

	server_redraw_window(w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(w, new_wp);
		session_select(s, wl->idx);
		server_redraw_session(s);
	} else
		server_status_session(s);

	environ_free(&env);

	if (args_has(args, 'P')) {
		paneidx = window_pane_index(wl->window, new_wp);
		ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx);
	}
	return (0);

error:
	environ_free(&env);
	if (new_wp != NULL)
		window_remove_pane(w, new_wp);
	ctx->error(ctx, "create pane failed: %s", cause);
	xfree(cause);
	return (-1);
}
예제 #9
0
enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args		*args = self->args;
	struct session		*s;
	struct winlink		*wl;
	struct window		*w;
	struct window_pane	*wp, *new_wp = NULL;
	struct environ		 env;
	const char		*cmd, *shell, *template;
	char			*cause, *new_cause, *cp;
	u_int			 hlimit;
	int			 size, percentage, cwd, fd = -1;
	enum layout_type	 type;
	struct layout_cell	*lc;
	struct client		*c;
	struct format_tree	*ft;

	if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
		return (CMD_RETURN_ERROR);
	w = wl->window;
	server_unzoom_window(w);

	environ_init(&env);
	environ_copy(&global_environ, &env);
	environ_copy(&s->environ, &env);
	server_fill_environ(s, &env);

	if (args->argc == 0)
		cmd = options_get_string(&s->options, "default-command");
	else
		cmd = args->argv[0];

	if (args_has(args, 'c')) {
		ft = format_create();
		if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
			format_client(ft, c);
		format_session(ft, s);
		format_winlink(ft, s, s->curw);
		format_window_pane(ft, s->curw->window->active);
		cp = format_expand(ft, args_get(args, 'c'));
		format_free(ft);

		fd = open(cp, O_RDONLY|O_DIRECTORY);
		free(cp);
		if (fd == -1) {
			cmdq_error(cmdq, "bad working directory: %s",
			    strerror(errno));
			return (CMD_RETURN_ERROR);
		}
		cwd = fd;
	} else if (cmdq->client != NULL && cmdq->client->session == NULL)
		cwd = cmdq->client->cwd;
	else
		cwd = s->cwd;

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 'l')) {
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
		if (cause != NULL) {
			xasprintf(&new_cause, "size %s", cause);
			free(cause);
			cause = new_cause;
			goto error;
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
		if (cause != NULL) {
			xasprintf(&new_cause, "percentage %s", cause);
			free(cause);
			cause = new_cause;
			goto error;
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (wp->sy * percentage) / 100;
		else
			size = (wp->sx * percentage) / 100;
	}
	hlimit = options_get_number(&s->options, "history-limit");

	shell = options_get_string(&s->options, "default-shell");
	if (*shell == '\0' || areshell(shell))
		shell = _PATH_BSHELL;

	if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) {
		cause = xstrdup("pane too small");
		goto error;
	}
	new_wp = window_add_pane(w, hlimit);
	if (window_pane_spawn(
	    new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
		goto error;
	layout_assign_pane(lc, new_wp);

	server_redraw_window(w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(w, new_wp);
		session_select(s, wl->idx);
		server_redraw_session(s);
	} else
		server_status_session(s);

	environ_free(&env);

	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)
예제 #10
0
int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct winlink		*src_wl, *dst_wl;
	struct window		*src_w, *dst_w;
	struct window_pane	*tmp_wp, *src_wp, *dst_wp;
	struct layout_cell	*src_lc, *dst_lc;
	u_int			 sx, sy, xoff, yoff;

	dst_wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &dst_wp);
	if (dst_wl == NULL)
		return (-1);
	dst_w = dst_wl->window;

	if (!args_has(args, 's')) {
		src_w = dst_w;
		if (args_has(self->args, 'D')) {
			src_wp = TAILQ_NEXT(dst_wp, entry);
			if (src_wp == NULL)
				src_wp = TAILQ_FIRST(&dst_w->panes);
		} else if (args_has(self->args, 'U')) {
			src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
			if (src_wp == NULL)
				src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
		} else
			return (0);
	} else {
		src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
		if (src_wl == NULL)
			return (-1);
		src_w = src_wl->window;
	}

	if (src_wp == dst_wp)
		return (0);

	tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
	TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
	TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
	if (tmp_wp == src_wp)
		tmp_wp = dst_wp;
	if (tmp_wp == NULL)
		TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
	else
		TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);

	src_lc = src_wp->layout_cell;
	dst_lc = dst_wp->layout_cell;
	src_lc->wp = dst_wp;
	dst_wp->layout_cell = src_lc;
	dst_lc->wp = src_wp;
	src_wp->layout_cell = dst_lc;

	src_wp->window = dst_w;
	dst_wp->window = src_w;

	sx = src_wp->sx; sy = src_wp->sy;
	xoff = src_wp->xoff; yoff = src_wp->yoff;
	src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff;
	window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
	dst_wp->xoff = xoff; dst_wp->yoff = yoff;
	window_pane_resize(dst_wp, sx, sy);

	if (!args_has(self->args, 'd')) {
		if (src_w != dst_w) {
			window_set_active_pane(src_w, dst_wp);
			window_set_active_pane(dst_w, src_wp);
		} else {
			tmp_wp = dst_wp;
			if (!window_pane_visible(tmp_wp))
				tmp_wp = src_wp;
			window_set_active_pane(src_w, tmp_wp);
		}
	} else {
		if (src_w->active == src_wp)
			window_set_active_pane(src_w, dst_wp);
		if (dst_w->active == dst_wp)
			window_set_active_pane(dst_w, src_wp);
	}
	if (src_w != dst_w) {
		if (src_w->last == src_wp)
			src_w->last = NULL;
		if (dst_w->last == dst_wp)
			dst_w->last = NULL;
	}
	server_redraw_window(src_w);
	server_redraw_window(dst_w);

	return (0);
}
예제 #11
0
static enum cmd_retval
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
{
	struct args		*args = self->args;
	struct cmd_find_state	*current = &item->shared->current;
	struct session		*dst_s;
	struct winlink		*src_wl, *dst_wl;
	struct window		*src_w, *dst_w;
	struct window_pane	*src_wp, *dst_wp;
	char			*cause;
	int			 size, percentage, dst_idx;
	enum layout_type	 type;
	struct layout_cell	*lc;
	int			 not_same_window, flags;

	if (self->entry == &cmd_join_pane_entry)
		not_same_window = 1;
	else
		not_same_window = 0;

	dst_s = item->target.s;
	dst_wl = item->target.wl;
	dst_wp = item->target.wp;
	dst_w = dst_wl->window;
	dst_idx = dst_wl->idx;
	server_unzoom_window(dst_w);

	src_wl = item->source.wl;
	src_wp = item->source.wp;
	src_w = src_wl->window;
	server_unzoom_window(src_w);

	if (not_same_window && src_w == dst_w) {
		cmdq_error(item, "can't join a pane to its own window");
		return (CMD_RETURN_ERROR);
	}
	if (!not_same_window && src_wp == dst_wp) {
		cmdq_error(item, "source and target panes must be different");
		return (CMD_RETURN_ERROR);
	}

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 'l')) {
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
		if (cause != NULL) {
			cmdq_error(item, "size %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, 100, &cause);
		if (cause != NULL) {
			cmdq_error(item, "percentage %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (dst_wp->sy * percentage) / 100;
		else
			size = (dst_wp->sx * percentage) / 100;
	}
	if (args_has(args, 'b'))
		flags = SPAWN_BEFORE;
	else
		flags = 0;
	lc = layout_split_pane(dst_wp, type, size, flags);
	if (lc == NULL) {
		cmdq_error(item, "create pane failed: pane too small");
		return (CMD_RETURN_ERROR);
	}

	layout_close_pane(src_wp);

	window_lost_pane(src_w, src_wp);
	TAILQ_REMOVE(&src_w->panes, src_wp, entry);

	src_wp->window = dst_w;
	TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
	layout_assign_pane(lc, src_wp);

	recalculate_sizes();

	server_redraw_window(src_w);
	server_redraw_window(dst_w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(dst_w, src_wp, 1);
		session_select(dst_s, dst_idx);
		cmd_find_from_session(current, dst_s, 0);
		server_redraw_session(dst_s);
	} else
		server_status_session(dst_s);

	if (window_count_panes(src_w) == 0)
		server_kill_window(src_w);
	else
		notify_window("window-layout-changed", src_w);
	notify_window("window-layout-changed", dst_w);

	return (CMD_RETURN_NORMAL);
}
예제 #12
0
void
recalculate_sizes(void)
{
	struct session		*s;
	struct client		*c;
	struct window		*w;
	struct window_pane	*wp;
	u_int		 	 i, j, ssx, ssy, has, limit;
	int		 	 flag;

	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
		s = ARRAY_ITEM(&sessions, i);
		if (s == NULL)
			continue;

		ssx = ssy = UINT_MAX;
		for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
			c = ARRAY_ITEM(&clients, j);
			if (c == NULL || c->flags & CLIENT_SUSPENDED)
				continue;
			if (c->session == s) {
				if (c->tty.sx < ssx)
					ssx = c->tty.sx;
				if (c->tty.sy < ssy)
					ssy = c->tty.sy;
			}
		}
		if (ssx == UINT_MAX || ssy == UINT_MAX) {
			s->flags |= SESSION_UNATTACHED;
			continue;
		}
		s->flags &= ~SESSION_UNATTACHED;

		if (options_get_number(&s->options, "status")) {
			if (ssy == 0)
				ssy = 1;
			else
				ssy--;
		}
		if (s->sx == ssx && s->sy == ssy)
			continue;

		log_debug(
		    "session size %u,%u (was %u,%u)", ssx, ssy, s->sx, s->sy);

		s->sx = ssx;
		s->sy = ssy;
	}

	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
		w = ARRAY_ITEM(&windows, i);
		if (w == NULL)
			continue;
		flag = options_get_number(&w->options, "aggressive-resize");

		ssx = ssy = UINT_MAX;
		for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
			s = ARRAY_ITEM(&sessions, j);
			if (s == NULL || s->flags & SESSION_UNATTACHED)
				continue;
			if (flag)
				has = s->curw->window == w;
			else
				has = session_has(s, w);
			if (has) {
				if (s->sx < ssx)
					ssx = s->sx;
				if (s->sy < ssy)
					ssy = s->sy;
			}
		}
		if (ssx == UINT_MAX || ssy == UINT_MAX) {
			w->flags |= WINDOW_HIDDEN;
			continue;
		}
		w->flags &= ~WINDOW_HIDDEN;

		limit = options_get_number(&w->options, "force-width");
		if (limit != 0 && ssx > limit)
			ssx = limit;
		limit = options_get_number(&w->options, "force-height");
		if (limit != 0 && ssy > limit)
			ssy = limit;

		if (w->sx == ssx && w->sy == ssy)
			continue;

		log_debug(
		    "window size %u,%u (was %u,%u)", ssx, ssy, w->sx, w->sy);

		layout_resize(w, ssx, ssy);
		window_resize(w, ssx, ssy);

		/*
		 * If the current pane is now not visible, move to the next
		 * that is.
		 */
		wp = w->active;
		while (!window_pane_visible(w->active)) {
			w->active = TAILQ_PREV(w->active, window_panes, entry);
			if (w->active == NULL)
				w->active = TAILQ_LAST(&w->panes, window_panes);
			if (w->active == wp)
			       break;
		}

		server_redraw_window(w);
	}
}
int
cmd_resize_pane_down_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_pane_data	*data = self->data;
	struct winlink		*wl;
	const char	       	*errstr;
	struct window_pane	*wp, *wq;
	u_int			 adjust;
	
	if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
		return (-1);
	if (wl->window->layout != 0) {
		ctx->error(ctx, "window not in manual layout");
		return (-1);
	}
	if (data->pane == -1)
		wp = wl->window->active;
	else {
		wp = window_pane_at_index(wl->window, data->pane);
		if (wp == NULL) {
			ctx->error(ctx, "no pane: %d", data->pane);
			return (-1);
		}
	}

	if (data->arg == NULL)
		adjust = 1;
	else {
		adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
		if (errstr != NULL) {
			ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
			return (-1);
		}
	}

	/*
	 * If this is not the last window, keep trying to increase size and
	 * remove it from the next windows. If it is the last, do so on the
	 * previous window.
	 */
	if (TAILQ_NEXT(wp, entry) == NULL) {
		if (wp == TAILQ_FIRST(&wl->window->panes)) {
			/* Only one pane. */
			return (0);
		}
		wp = TAILQ_PREV(wp, window_panes, entry);
	}
	while (adjust-- > 0) {
		wq = wp;
		while ((wq = TAILQ_NEXT(wq, entry)) != NULL) {
			if (wq->sy > PANE_MINIMUM) {
				window_pane_resize(wq, wq->sx, wq->sy - 1);
				break;
			}
		}
		if (wq == NULL)
			break;
		window_pane_resize(wp, wp->sx, wp->sy + 1);

	}
	window_update_panes(wl->window);

	server_redraw_window(wl->window);

	return (0);
}
예제 #14
0
int
cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args	*args = self->args;
	struct winlink	*wl;
	struct window	*w;
	const char	*layoutname;
	int		 next, previous, layout;

	if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
		return (-1);
	w = wl->window;

	next = self->entry == &cmd_next_layout_entry;
	if (args_has(self->args, 'n'))
		next = 1;
	previous = self->entry == &cmd_previous_layout_entry;
	if (args_has(self->args, 'p'))
		previous = 1;

	layout_list_add(w);
	if (args_has(self->args, 'U')) {
		if ((layoutname = layout_list_redo(w)) == NULL) {
			ctx->info(ctx, "no more layout history");
			return (-1);
		}
		goto set_layout;
	} else if (args_has(self->args, 'u')) {
		if ((layoutname = layout_list_undo(w)) == NULL) {
			ctx->info(ctx, "no more layout history");
			return (-1);
		}
		goto set_layout;
	}

	if (next || previous) {
		if (next)
			layout = layout_set_next(wl->window);
		else
			layout = layout_set_previous(wl->window);
		server_redraw_window(wl->window);
		ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
		return (0);
	}

	if (args->argc == 0)
		layout = wl->window->lastlayout;
	else
		layout = layout_set_lookup(args->argv[0]);
	if (layout != -1) {
		layout = layout_set_select(wl->window, layout);
		server_redraw_window(wl->window);
		ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
		return (0);
	}

	if (args->argc == 0)
		return (0);
	layoutname = args->argv[0];

set_layout:
	if (layout_parse(wl->window, layoutname) == -1) {
		ctx->error(ctx, "can't set layout: %s", layoutname);
		return (-1);
	}
	server_redraw_window(wl->window);
	ctx->info(ctx, "arranging in: %s", layoutname);
	return (0);
}
enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args		*args = self->args;
	struct winlink		*wl;
	struct window		*w;
	const char	       	*errstr;
	char			*cause;
	struct window_pane	*wp;
	u_int			 adjust;
	int			 x, y;

	if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
		return (CMD_RETURN_ERROR);
	w = wl->window;

	if (args_has(args, 'Z')) {
		if (w->flags & WINDOW_ZOOMED)
			window_unzoom(w);
		else
			window_zoom(wp);
		server_redraw_window(w);
		server_status_window(w);
		return (CMD_RETURN_NORMAL);
	}
	server_unzoom_window(w);

	if (args->argc == 0)
		adjust = 1;
	else {
		adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
		if (errstr != NULL) {
			cmdq_error(cmdq, "adjustment %s", errstr);
			return (CMD_RETURN_ERROR);
		}
	}

	if (args_has(self->args, 'x')) {
		x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX,
		    &cause);
		if (cause != NULL) {
			cmdq_error(cmdq, "width %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
		layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
	}
	if (args_has(self->args, 'y')) {
		y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX,
		    &cause);
		if (cause != NULL) {
			cmdq_error(cmdq, "height %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
		layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
	}

	if (args_has(self->args, 'L'))
		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust);
	else if (args_has(self->args, 'R'))
		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
	else if (args_has(self->args, 'U'))
		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust);
	else if (args_has(self->args, 'D'))
		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
	server_redraw_window(wl->window);

	return (CMD_RETURN_NORMAL);
}
예제 #16
0
enum cmd_retval
join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
{
	struct args		*args = self->args;
	struct session		*dst_s;
	struct winlink		*src_wl, *dst_wl;
	struct window		*src_w, *dst_w;
	struct window_pane	*src_wp, *dst_wp;
	char			*cause;
	int			 size, percentage, dst_idx;
	enum layout_type	 type;
	struct layout_cell	*lc;

	dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp);
	if (dst_wl == NULL)
		return (CMD_RETURN_ERROR);
	dst_w = dst_wl->window;
	dst_idx = dst_wl->idx;
	server_unzoom_window(dst_w);

	src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp);
	if (src_wl == NULL)
		return (CMD_RETURN_ERROR);
	src_w = src_wl->window;
	server_unzoom_window(src_w);

	if (not_same_window && src_w == dst_w) {
		cmdq_error(cmdq, "can't join a pane to its own window");
		return (CMD_RETURN_ERROR);
	}
	if (!not_same_window && src_wp == dst_wp) {
		cmdq_error(cmdq, "source and target panes must be different");
		return (CMD_RETURN_ERROR);
	}

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 'l')) {
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
		if (cause != NULL) {
			cmdq_error(cmdq, "size %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, 100, &cause);
		if (cause != NULL) {
			cmdq_error(cmdq, "percentage %s", cause);
			free(cause);
			return (CMD_RETURN_ERROR);
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (dst_wp->sy * percentage) / 100;
		else
			size = (dst_wp->sx * percentage) / 100;
	}
	lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'));
	if (lc == NULL) {
		cmdq_error(cmdq, "create pane failed: pane too small");
		return (CMD_RETURN_ERROR);
	}

	layout_close_pane(src_wp);

	window_lost_pane(src_w, src_wp);
	TAILQ_REMOVE(&src_w->panes, src_wp, entry);

	if (window_count_panes(src_w) == 0)
		server_kill_window(src_w);
	else
		notify_window_layout_changed(src_w);

	src_wp->window = dst_w;
	TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
	layout_assign_pane(lc, src_wp);

	recalculate_sizes();

	server_redraw_window(src_w);
	server_redraw_window(dst_w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(dst_w, src_wp);
		session_select(dst_s, dst_idx);
		server_redraw_session(dst_s);
	} else
		server_status_session(dst_s);

	notify_window_layout_changed(dst_w);
	return (CMD_RETURN_NORMAL);
}
예제 #17
0
int
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_split_window_data	*data = self->data;
	struct session			*s;
	struct winlink			*wl;
	struct window			*w;
	struct window_pane		*wp, *new_wp = NULL;
	struct environ			 env;
	char		 		*cmd, *cwd, *cause;
	const char			*shell;
	u_int				 hlimit;
	int				 size;
	enum layout_type		 type;
	struct layout_cell		*lc;

	if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL)
		return (-1);
	w = wl->window;

	environ_init(&env);
	environ_copy(&global_environ, &env);
	environ_copy(&s->environ, &env);
	server_fill_environ(s, &env);

	cmd = data->cmd;
	if (cmd == NULL)
		cmd = options_get_string(&s->options, "default-command");
	if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
		cwd = options_get_string(&s->options, "default-path");
	else
		cwd = ctx->cmdclient->cwd;

	type = LAYOUT_TOPBOTTOM;
	if (data->flag_horizontal)
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (data->size != -1)
		size = data->size;
	else if (data->percentage != -1) {
		if (type == LAYOUT_TOPBOTTOM)
			size = (wp->sy * data->percentage) / 100;
		else
			size = (wp->sx * data->percentage) / 100;
	}
	hlimit = options_get_number(&s->options, "history-limit");

	shell = options_get_string(&s->options, "default-shell");
	if (*shell == '\0' || areshell(shell))
		shell = _PATH_BSHELL;

	if ((lc = layout_split_pane(wp, type, size)) == NULL) {
		cause = xstrdup("pane too small");
		goto error;
	}
	new_wp = window_add_pane(w, hlimit);
	if (window_pane_spawn(
	    new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
		goto error;
	layout_assign_pane(lc, new_wp);

	server_redraw_window(w);

	if (!data->flag_detached) {
		window_set_active_pane(w, new_wp);
		session_select(s, wl->idx);
		server_redraw_session(s);
	} else
		server_status_session(s);

	environ_free(&env);
	return (0);

error:
	environ_free(&env);
	if (new_wp != NULL)
		window_remove_pane(w, new_wp);
	ctx->error(ctx, "create pane failed: %s", cause);
	xfree(cause);
	return (-1);
}
예제 #18
0
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE_SLAVE
	return (CMD_RETURN_ERROR);
#else
	struct winlink          *src_wl, *dst_wl;
	struct window		*src_w, *dst_w;
	struct window_pane	*tmp_wp, *src_wp, *dst_wp;
	struct layout_cell	*src_lc, *dst_lc;
	u_int			 sx, sy, xoff, yoff;

	dst_w = cmdq->state.tflag.wl->window;
	dst_wp = cmdq->state.tflag.wp;
	src_w = cmdq->state.sflag.wl->window;
	src_wp = cmdq->state.sflag.wp;
	server_unzoom_window(dst_w);

	if (args_has(self->args, 'D')) {
		src_w = dst_w;
		src_wp = TAILQ_NEXT(dst_wp, entry);
		if (src_wp == NULL)
			src_wp = TAILQ_FIRST(&dst_w->panes);
	} else if (args_has(self->args, 'U')) {
		src_w = dst_w;
		src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
		if (src_wp == NULL)
			src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
	}
	server_unzoom_window(src_w);

	if (src_wp == dst_wp)
		return (CMD_RETURN_NORMAL);

	tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
	TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
	TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
	if (tmp_wp == src_wp)
		tmp_wp = dst_wp;
	if (tmp_wp == NULL)
		TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
	else
		TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);

	src_lc = src_wp->layout_cell;
	dst_lc = dst_wp->layout_cell;
	src_lc->wp = dst_wp;
	dst_wp->layout_cell = src_lc;
	dst_lc->wp = src_wp;
	src_wp->layout_cell = dst_lc;

	src_wp->window = dst_w;
	dst_wp->window = src_w;

	sx = src_wp->sx; sy = src_wp->sy;
	xoff = src_wp->xoff; yoff = src_wp->yoff;
	src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff;
	window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
	dst_wp->xoff = xoff; dst_wp->yoff = yoff;
	window_pane_resize(dst_wp, sx, sy);

	if (!args_has(self->args, 'd')) {
		if (src_w != dst_w) {
			window_set_active_pane(src_w, dst_wp);
			window_set_active_pane(dst_w, src_wp);
		} else {
			tmp_wp = dst_wp;
			if (!window_pane_visible(tmp_wp))
				tmp_wp = src_wp;
			window_set_active_pane(src_w, tmp_wp);
		}
	} else {
		if (src_w->active == src_wp)
			window_set_active_pane(src_w, dst_wp);
		if (dst_w->active == dst_wp)
			window_set_active_pane(dst_w, src_wp);
	}
	if (src_w != dst_w) {
		if (src_w->last == src_wp)
			src_w->last = NULL;
		if (dst_w->last == dst_wp)
			dst_w->last = NULL;
	}
	server_redraw_window(src_w);
	server_redraw_window(dst_w);

	return (CMD_RETURN_NORMAL);
#endif
}
예제 #19
0
enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct session		*s;
	struct winlink		*wl;
	struct window		*w;
	struct window_pane	*wp, *new_wp = NULL;
	struct environ		 env;
	const char		*cmd, *cwd, *shell;
	char			*cause, *new_cause;
	u_int			 hlimit;
	int			 size, percentage;
	enum layout_type	 type;
	struct layout_cell	*lc;
	const char		*template;
	struct client		*c;
	struct format_tree	*ft;
	char			*cp;

	if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
		return (CMD_RETURN_ERROR);
	w = wl->window;

	environ_init(&env);
	environ_copy(&global_environ, &env);
	environ_copy(&s->environ, &env);
	server_fill_environ(s, &env);

	if (args->argc == 0)
		cmd = options_get_string(&s->options, "default-command");
	else
		cmd = args->argv[0];
	cwd = cmd_get_default_path(ctx, args_get(args, 'c'));

	type = LAYOUT_TOPBOTTOM;
	if (args_has(args, 'h'))
		type = LAYOUT_LEFTRIGHT;

	size = -1;
	if (args_has(args, 'l')) {
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
		if (cause != NULL) {
			xasprintf(&new_cause, "size %s", cause);
			free(cause);
			cause = new_cause;
			goto error;
		}
	} else if (args_has(args, 'p')) {
		percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
		if (cause != NULL) {
			xasprintf(&new_cause, "percentage %s", cause);
			free(cause);
			cause = new_cause;
			goto error;
		}
		if (type == LAYOUT_TOPBOTTOM)
			size = (wp->sy * percentage) / 100;
		else
			size = (wp->sx * percentage) / 100;
	}
	hlimit = options_get_number(&s->options, "history-limit");

	shell = options_get_string(&s->options, "default-shell");
	if (*shell == '\0' || areshell(shell))
		shell = _PATH_BSHELL;

	if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) {
		cause = xstrdup("pane too small");
		goto error;
	}
	new_wp = window_add_pane(w, hlimit);
	if (window_pane_spawn(
	    new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
		goto error;
	layout_assign_pane(lc, new_wp);

	server_redraw_window(w);

	if (!args_has(args, 'd')) {
		window_set_active_pane(w, new_wp);
		session_select(s, wl->idx);
		server_redraw_session(s);
	} else
		server_status_session(s);

	environ_free(&env);

	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)