mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-03 16:46:18 +00:00 
			
		
		
		
	Multiple window splitting.
This commit is contained in:
		
							
								
								
									
										13
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGES
									
									
									
									
									
								
							@@ -1,5 +1,16 @@
 | 
			
		||||
14 January 2009
 | 
			
		||||
 | 
			
		||||
* Multiple vertical window splitting. Minimum pane size is four lines, an
 | 
			
		||||
  (unhelpful) error will be shown if attempting to split a window with less
 | 
			
		||||
  that eight lines. If the window is resized, as many panes are shown as can
 | 
			
		||||
  fit without reducing them below four lines. There is (currently!) not a way
 | 
			
		||||
  to show a hidden a pane without making the window larger.
 | 
			
		||||
 | 
			
		||||
  Note the -p and -l options to split-window are now gone, these may reappear
 | 
			
		||||
  once I think them through again.
 | 
			
		||||
 | 
			
		||||
  To come: up-pane, down-pane; switch-pane will support -p and become
 | 
			
		||||
  select-pane.
 | 
			
		||||
* Server locking on inactivity (lock-after-time) is now disabled by default.
 | 
			
		||||
 | 
			
		||||
13 January 2009
 | 
			
		||||
@@ -906,7 +917,7 @@
 | 
			
		||||
  (including mutt, emacs). No status bar yet and no key remapping or other
 | 
			
		||||
  customisation.
 | 
			
		||||
 | 
			
		||||
$Id: CHANGES,v 1.202 2009-01-14 18:41:55 nicm Exp $
 | 
			
		||||
$Id: CHANGES,v 1.203 2009-01-14 19:29:32 nicm Exp $
 | 
			
		||||
 | 
			
		||||
 LocalWords:  showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
 | 
			
		||||
 LocalWords:  rivo nurges lscm Erdely eol smysession mysession ek dstname RB
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								TODO
									
									
									
									
									
								
							@@ -98,3 +98,9 @@
 | 
			
		||||
- key handling sucks a bit and needs to be reworked
 | 
			
		||||
- prefix-time should only apply to a few commands otherwise it is too annoying
 | 
			
		||||
 | 
			
		||||
-----
 | 
			
		||||
SPLITTING
 | 
			
		||||
emacs-style:
 | 
			
		||||
	- when resizing, always expand and reduce from top to bottom
 | 
			
		||||
	- minimum size 4 + separator
 | 
			
		||||
	- if not enough room hide windows from top to bottom
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-kill-pane.c,v 1.1 2009-01-13 06:50:10 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-kill-pane.c,v 1.2 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -53,17 +53,18 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	if (data->pane == -1)
 | 
			
		||||
		wp = wl->window->active;
 | 
			
		||||
	else {
 | 
			
		||||
		if (data->pane > 1 || wl->window->panes[data->pane] == NULL) {
 | 
			
		||||
		wp = window_pane_at_index(wl->window, data->pane);
 | 
			
		||||
		if (wp == NULL) {
 | 
			
		||||
			ctx->error(ctx, "no pane: %d", data->pane);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		wp = wl->window->panes[data->pane];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (window_remove_pane(wl->window, wp) != 0) {
 | 
			
		||||
	if (window_count_panes(wl->window) == 1) {
 | 
			
		||||
		ctx->error(ctx, "can't kill pane: %d", data->pane);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	window_remove_pane(wl->window, wp);
 | 
			
		||||
	server_redraw_window(wl->window);
 | 
			
		||||
 | 
			
		||||
	if (ctx->cmdclient != NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-list-windows.c,v 1.27 2009-01-12 18:22:47 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-list-windows.c,v 1.28 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -62,10 +62,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
 | 
			
		||||
		ctx->print(ctx,
 | 
			
		||||
		    "%d: %s [%ux%u]", wl->idx, w->name, w->sx, w->sy);
 | 
			
		||||
		for (i = 0; i < 2; i++) {
 | 
			
		||||
			wp = w->panes[i];
 | 
			
		||||
			if (wp == NULL)
 | 
			
		||||
				continue;	
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			gd = wp->base.grid;
 | 
			
		||||
			
 | 
			
		||||
			size = 0;
 | 
			
		||||
@@ -79,9 +76,9 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
			else
 | 
			
		||||
				name = "";
 | 
			
		||||
		
 | 
			
		||||
			ctx->print(ctx, "   pane %d:"
 | 
			
		||||
			    " %s [%ux%u] [history %u/%u, %llu bytes]", i, name,
 | 
			
		||||
			    wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
 | 
			
		||||
			ctx->print(ctx, 
 | 
			
		||||
			    "    %s [%ux%u] [history %u/%u, %llu bytes]", i, 
 | 
			
		||||
			    name, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-resize-pane-down.c,v 1.1 2009-01-12 19:23:14 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-resize-pane-down.c,v 1.2 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -23,69 +23,81 @@
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Increase pane size.
 | 
			
		||||
 * Decrease pane size.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void	cmd_resize_pane_down_exec(struct cmd *, struct cmd_ctx *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_resize_pane_down_entry = {
 | 
			
		||||
	"resize-pane-down", "resizep-dn",
 | 
			
		||||
	CMD_TARGET_WINDOW_USAGE " [adjustment]",
 | 
			
		||||
	"resize-pane-down", "resizep-down",
 | 
			
		||||
	CMD_PANE_WINDOW_USAGE " [adjustment]",
 | 
			
		||||
	CMD_ZEROONEARG,
 | 
			
		||||
	cmd_target_init,
 | 
			
		||||
	cmd_target_parse,
 | 
			
		||||
	cmd_pane_init,
 | 
			
		||||
	cmd_pane_parse,
 | 
			
		||||
	cmd_resize_pane_down_exec,
 | 
			
		||||
       	cmd_target_send,
 | 
			
		||||
	cmd_target_recv,
 | 
			
		||||
	cmd_target_free,
 | 
			
		||||
	cmd_target_print
 | 
			
		||||
       	cmd_pane_send,
 | 
			
		||||
	cmd_pane_recv,
 | 
			
		||||
	cmd_pane_free,
 | 
			
		||||
	cmd_pane_print
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
cmd_resize_pane_down_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_target_data	*data = self->data;
 | 
			
		||||
	struct cmd_pane_data	*data = self->data;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	int			 adjust;
 | 
			
		||||
	const char	       	*errstr;
 | 
			
		||||
	u_int			 y0, y1;
 | 
			
		||||
	struct window_pane	*wp, *wq;
 | 
			
		||||
	u_int			 adjust;
 | 
			
		||||
	
 | 
			
		||||
	if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
#ifdef notyet
 | 
			
		||||
	if (data->pane == -1)
 | 
			
		||||
		wp = wl->window->active;
 | 
			
		||||
	else {
 | 
			
		||||
		if (data->pane > 1 || wl->window->panes[data->pane] == NULL) {
 | 
			
		||||
		wp = window_pane_at_index(wl->window, data->pane);
 | 
			
		||||
		if (wp == NULL) {
 | 
			
		||||
			ctx->error(ctx, "no pane: %d", data->pane);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		wp = wl->window->panes[data->pane];
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (data->arg == NULL)
 | 
			
		||||
		adjust = 1;
 | 
			
		||||
	else {
 | 
			
		||||
		adjust = strtonum(data->arg, 0, INT_MAX, &errstr);
 | 
			
		||||
		adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl->window->panes[1] == NULL)
 | 
			
		||||
		goto out;
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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. */
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
	y0 = wl->window->panes[0]->sy;
 | 
			
		||||
	y1 = wl->window->panes[1]->sy;
 | 
			
		||||
	if (adjust >= y1)
 | 
			
		||||
		adjust = y1 - 1;
 | 
			
		||||
	y0 += adjust;
 | 
			
		||||
	y1 -= adjust;		
 | 
			
		||||
	window_pane_resize(wl->window->panes[0], wl->window->sx, y0);
 | 
			
		||||
	window_pane_resize(wl->window->panes[1], wl->window->sx, y1);
 | 
			
		||||
	wl->window->panes[1]->yoff = y0 + 1;		
 | 
			
		||||
	}
 | 
			
		||||
	window_update_panes(wl->window);
 | 
			
		||||
 | 
			
		||||
	server_redraw_window(wl->window);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-resize-pane-up.c,v 1.1 2009-01-12 19:23:14 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-resize-pane-up.c,v 1.2 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -30,62 +30,69 @@ void	cmd_resize_pane_up_exec(struct cmd *, struct cmd_ctx *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_resize_pane_up_entry = {
 | 
			
		||||
	"resize-pane-up", "resizep-up",
 | 
			
		||||
	CMD_TARGET_WINDOW_USAGE " [adjustment]",
 | 
			
		||||
	CMD_PANE_WINDOW_USAGE " [adjustment]",
 | 
			
		||||
	CMD_ZEROONEARG,
 | 
			
		||||
	cmd_target_init,
 | 
			
		||||
	cmd_target_parse,
 | 
			
		||||
	cmd_pane_init,
 | 
			
		||||
	cmd_pane_parse,
 | 
			
		||||
	cmd_resize_pane_up_exec,
 | 
			
		||||
       	cmd_target_send,
 | 
			
		||||
	cmd_target_recv,
 | 
			
		||||
	cmd_target_free,
 | 
			
		||||
	cmd_target_print
 | 
			
		||||
       	cmd_pane_send,
 | 
			
		||||
	cmd_pane_recv,
 | 
			
		||||
	cmd_pane_free,
 | 
			
		||||
	cmd_pane_print
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
cmd_resize_pane_up_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_target_data	*data = self->data;
 | 
			
		||||
	struct cmd_pane_data	*data = self->data;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	int			 adjust;
 | 
			
		||||
	const char	       	*errstr;
 | 
			
		||||
	u_int			 y0, y1;
 | 
			
		||||
	struct window_pane	*wp, *wq;
 | 
			
		||||
	u_int			 adjust;
 | 
			
		||||
	
 | 
			
		||||
	if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
#ifdef notyet
 | 
			
		||||
	if (data->pane == -1)
 | 
			
		||||
		wp = wl->window->active;
 | 
			
		||||
	else {
 | 
			
		||||
		if (data->pane > 1 || wl->window->panes[data->pane] == NULL) {
 | 
			
		||||
		wp = window_pane_at_index(wl->window, data->pane);
 | 
			
		||||
		if (wp == NULL) {
 | 
			
		||||
			ctx->error(ctx, "no pane: %d", data->pane);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		wp = wl->window->panes[data->pane];
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (data->arg == NULL)
 | 
			
		||||
		adjust = 1;
 | 
			
		||||
	else {
 | 
			
		||||
		adjust = strtonum(data->arg, 0, INT_MAX, &errstr);
 | 
			
		||||
		adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl->window->panes[1] == NULL)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	y0 = wl->window->panes[0]->sy;
 | 
			
		||||
	y1 = wl->window->panes[1]->sy;
 | 
			
		||||
	if (adjust >= y0)
 | 
			
		||||
		adjust = y0 - 1;
 | 
			
		||||
	y0 -= adjust;
 | 
			
		||||
	y1 += adjust;		
 | 
			
		||||
	window_pane_resize(wl->window->panes[0], wl->window->sx, y0);
 | 
			
		||||
	window_pane_resize(wl->window->panes[1], wl->window->sx, y1);
 | 
			
		||||
	wl->window->panes[1]->yoff = y0 + 1;		
 | 
			
		||||
	/*
 | 
			
		||||
	 * If this is not the last window, keep trying to reduce size and add
 | 
			
		||||
	 * to the following window. If it is the last, do so on the previous
 | 
			
		||||
	 * window.
 | 
			
		||||
	 */
 | 
			
		||||
	wq = TAILQ_NEXT(wp, entry);
 | 
			
		||||
	if (wq == NULL) {
 | 
			
		||||
		if (wp == TAILQ_FIRST(&wl->window->panes)) {
 | 
			
		||||
			/* Only one pane. */
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		wq = wp;
 | 
			
		||||
		wp = TAILQ_PREV(wq, window_panes, entry);
 | 
			
		||||
	}
 | 
			
		||||
	while (adjust-- > 0) {
 | 
			
		||||
		if (wp->sy <= PANE_MINIMUM)
 | 
			
		||||
			break;
 | 
			
		||||
		window_pane_resize(wq, wq->sx, wq->sy + 1);
 | 
			
		||||
		window_pane_resize(wp, wp->sx, wp->sy - 1);
 | 
			
		||||
	}
 | 
			
		||||
	window_update_panes(wl->window);
 | 
			
		||||
 | 
			
		||||
	server_redraw_window(wl->window);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-respawn-window.c,v 1.9 2009-01-13 06:50:10 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-respawn-window.c,v 1.10 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -47,6 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	struct cmd_target_data	*data = self->data;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	const char		*env[] = CHILD_ENVIRON;
 | 
			
		||||
	char		 	 buf[256];
 | 
			
		||||
@@ -56,10 +57,14 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
		return;
 | 
			
		||||
	w = wl->window;
 | 
			
		||||
 | 
			
		||||
	if ((w->panes[0]->fd != -1 || (w->panes[1] != NULL &&
 | 
			
		||||
	    w->panes[1]->fd != -1)) && !(data->flags & CMD_KFLAG)) {
 | 
			
		||||
		ctx->error(ctx, "window still active: %s:%d", s->name, wl->idx);
 | 
			
		||||
		return;
 | 
			
		||||
	if (!(data->flags & CMD_KFLAG)) {
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			if (wp->fd == -1)
 | 
			
		||||
				continue;
 | 
			
		||||
			ctx->error(ctx,
 | 
			
		||||
			    "window still active: %s:%d", s->name, wl->idx);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (session_index(s, &i) != 0)
 | 
			
		||||
@@ -67,14 +72,16 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i);
 | 
			
		||||
	env[0] = buf;
 | 
			
		||||
 | 
			
		||||
	if (w->panes[1] != NULL)
 | 
			
		||||
		window_remove_pane(w, w->panes[1]);
 | 
			
		||||
 | 
			
		||||
	if (window_pane_spawn(w->panes[0], data->arg, NULL, env) != 0) {
 | 
			
		||||
	wp = TAILQ_FIRST(&w->panes);
 | 
			
		||||
	TAILQ_REMOVE(&w->panes, wp, entry);
 | 
			
		||||
 	window_destroy_panes(w);
 | 
			
		||||
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
			
		||||
	window_pane_resize(wp, w->sx, w->sy);
 | 
			
		||||
	if (window_pane_spawn(wp, data->arg, NULL, env) != 0) {
 | 
			
		||||
		ctx->error(ctx, "respawn failed: %s:%d", s->name, wl->idx);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	screen_reinit(&w->panes[0]->base);
 | 
			
		||||
	screen_reinit(&wp->base);
 | 
			
		||||
 | 
			
		||||
	recalculate_sizes();
 | 
			
		||||
	server_redraw_window(w);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-split-window.c,v 1.3 2009-01-12 18:22:47 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-split-window.c,v 1.4 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -39,14 +39,11 @@ struct cmd_split_window_data {
 | 
			
		||||
	char	*target;
 | 
			
		||||
	char	*cmd;
 | 
			
		||||
	int	 flag_detached;
 | 
			
		||||
	
 | 
			
		||||
	int	 lines;
 | 
			
		||||
	int	 percentage;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_split_window_entry = {
 | 
			
		||||
	"split-window", "splitw",
 | 
			
		||||
	"[-d] [-t target-window] [-l lines|-p percentage] [command]",
 | 
			
		||||
	"[-d] [-t target-window] [command]",
 | 
			
		||||
	0,
 | 
			
		||||
	cmd_split_window_init,
 | 
			
		||||
	cmd_split_window_parse,
 | 
			
		||||
@@ -66,16 +63,13 @@ cmd_split_window_init(struct cmd *self, unused int arg)
 | 
			
		||||
	data->target = NULL;
 | 
			
		||||
	data->cmd = NULL;
 | 
			
		||||
	data->flag_detached = 0;
 | 
			
		||||
	data->lines = -1;
 | 
			
		||||
	data->percentage = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_split_window_data	*data;
 | 
			
		||||
	int				 opt, n;
 | 
			
		||||
	const char		        *errstr;
 | 
			
		||||
	int				 opt;
 | 
			
		||||
 | 
			
		||||
	self->entry->init(self, 0);
 | 
			
		||||
	data = self->data;
 | 
			
		||||
@@ -85,30 +79,6 @@ cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
			
		||||
		case 'd':
 | 
			
		||||
			data->flag_detached = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'l':
 | 
			
		||||
			if (data->percentage != -1)
 | 
			
		||||
				goto usage;
 | 
			
		||||
			if (data->lines == -1) {
 | 
			
		||||
				n = strtonum(optarg, 0, INT_MAX, &errstr);
 | 
			
		||||
				if (errstr != NULL) {
 | 
			
		||||
					xasprintf(cause, "number %s", errstr);
 | 
			
		||||
					goto error;
 | 
			
		||||
				}
 | 
			
		||||
				data->lines = n;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'p':
 | 
			
		||||
			if (data->lines != -1)
 | 
			
		||||
				goto usage;
 | 
			
		||||
			if (data->percentage == -1) {
 | 
			
		||||
				n = strtonum(optarg, 0, INT_MAX, &errstr);
 | 
			
		||||
				if (errstr != NULL) {
 | 
			
		||||
					xasprintf(cause, "number %s", errstr);
 | 
			
		||||
					goto error;
 | 
			
		||||
				}
 | 
			
		||||
				data->percentage = n;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 't':
 | 
			
		||||
			if (data->target == NULL)
 | 
			
		||||
				data->target = xstrdup(optarg);
 | 
			
		||||
@@ -130,7 +100,6 @@ cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 | 
			
		||||
usage:
 | 
			
		||||
	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	self->entry->free(self);
 | 
			
		||||
	return (-1);
 | 
			
		||||
}
 | 
			
		||||
@@ -142,20 +111,16 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	struct session			*s;
 | 
			
		||||
	struct winlink			*wl;
 | 
			
		||||
	struct window			*w;
 | 
			
		||||
	struct window_pane		*wp;
 | 
			
		||||
	const char			*env[] = CHILD_ENVIRON;
 | 
			
		||||
	char		 		 buf[256];
 | 
			
		||||
	char				*cmd, *cwd;
 | 
			
		||||
	u_int				 i, hlimit, size;
 | 
			
		||||
	u_int				 i, hlimit;
 | 
			
		||||
 | 
			
		||||
	if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	w = wl->window;
 | 
			
		||||
 | 
			
		||||
	if (w->panes[1] != NULL) {
 | 
			
		||||
		ctx->error(ctx, "window is already split");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (session_index(s, &i) != 0)
 | 
			
		||||
		fatalx("session not found");
 | 
			
		||||
	xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i);
 | 
			
		||||
@@ -169,26 +134,15 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	else
 | 
			
		||||
		cwd = ctx->cmdclient->cwd;
 | 
			
		||||
 | 
			
		||||
	size = w->sy / 2;
 | 
			
		||||
	if (data->lines != -1)
 | 
			
		||||
		size = data->lines;
 | 
			
		||||
	if (data->percentage != -1) {
 | 
			
		||||
		if (data->percentage > 100)
 | 
			
		||||
			data->percentage = 100;
 | 
			
		||||
		size = (w->sy * data->percentage) / 100;
 | 
			
		||||
	}
 | 
			
		||||
	if (size > w->sy)
 | 
			
		||||
		size = w->sy;	/* let window_add_pane sort it out */
 | 
			
		||||
 | 
			
		||||
	hlimit = options_get_number(&s->options, "history-limit");
 | 
			
		||||
	if (window_add_pane(w, size, cmd, cwd, env, hlimit) < 0) {
 | 
			
		||||
	if ((wp = window_add_pane(w, cmd, cwd, env, hlimit)) == NULL) {
 | 
			
		||||
		ctx->error(ctx, "command failed: %s", cmd);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	server_redraw_window(w);
 | 
			
		||||
	
 | 
			
		||||
	if (!data->flag_detached) {
 | 
			
		||||
		w->active = w->panes[1];
 | 
			
		||||
		window_set_active_pane(w, wp);
 | 
			
		||||
		session_select(s, wl->idx);
 | 
			
		||||
		server_redraw_session(s);
 | 
			
		||||
	} else
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-switch-pane.c,v 1.1 2009-01-11 23:31:46 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-switch-pane.c,v 1.2 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -44,17 +44,17 @@ cmd_switch_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_target_data	*data = self->data;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
 | 
			
		||||
	if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	
 | 
			
		||||
	wp = TAILQ_NEXT(wl->window->active, entry);
 | 
			
		||||
	if (wp == NULL)
 | 
			
		||||
		wp = TAILQ_FIRST(&wl->window->panes);
 | 
			
		||||
	window_set_active_pane(wl->window, wp);
 | 
			
		||||
 | 
			
		||||
	if (wl->window->panes[1] != NULL) {
 | 
			
		||||
		if (wl->window->active == wl->window->panes[0])
 | 
			
		||||
			wl->window->active = wl->window->panes[1];
 | 
			
		||||
		else
 | 
			
		||||
			wl->window->active = wl->window->panes[0];
 | 
			
		||||
		server_redraw_window(wl->window);
 | 
			
		||||
	}
 | 
			
		||||
	server_redraw_window(wl->window);
 | 
			
		||||
 | 
			
		||||
	if (ctx->cmdclient != NULL)
 | 
			
		||||
		server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: key-bindings.c,v 1.45 2009-01-13 01:08:40 nicm Exp $ */
 | 
			
		||||
/* $Id: key-bindings.c,v 1.46 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -108,6 +108,7 @@ key_bindings_init(void)
 | 
			
		||||
		{ 's', &cmd_list_sessions_entry },
 | 
			
		||||
		{ 't', &cmd_clock_mode_entry },
 | 
			
		||||
		{ 'w', &cmd_list_windows_entry },
 | 
			
		||||
		{ 'x', &cmd_kill_pane_entry, },
 | 
			
		||||
		{ KEYC_ADDCTL(KEYC_UP), &cmd_resize_pane_up_entry },
 | 
			
		||||
		{ KEYC_ADDCTL(KEYC_DOWN), &cmd_resize_pane_down_entry },
 | 
			
		||||
		{ META, &cmd_send_prefix_entry },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: screen-redraw.c,v 1.17 2009-01-12 18:22:47 nicm Exp $ */
 | 
			
		||||
/* $Id: screen-redraw.c,v 1.18 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
void	screen_redraw_blankx(struct client *, u_int, u_int);
 | 
			
		||||
void	screen_redraw_blanky(struct client *, u_int, u_int);
 | 
			
		||||
void	screen_redraw_blanky(struct client *, u_int, u_int, char);
 | 
			
		||||
void	screen_redraw_line(struct client *, struct screen *, u_int, u_int);
 | 
			
		||||
 | 
			
		||||
/* Redraw entire screen.. */
 | 
			
		||||
@@ -42,38 +42,24 @@ screen_redraw_screen(struct client *c, struct screen *s)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* 
 | 
			
		||||
	 * A normal client screen is made up of three parts: a top window, a
 | 
			
		||||
	 * bottom window and a status line. The bottom window may be turned
 | 
			
		||||
	 * off; the status line is always drawn.
 | 
			
		||||
	 */
 | 
			
		||||
	status = options_get_number(&c->session->options, "status");
 | 
			
		||||
 | 
			
		||||
	/* Draw the top window. */
 | 
			
		||||
	wp = w->panes[0];
 | 
			
		||||
	s = wp->screen;
 | 
			
		||||
 | 
			
		||||
	sy = screen_size_y(s);
 | 
			
		||||
	if (screen_size_y(s) == c->sy && w->panes[1] == NULL)
 | 
			
		||||
		sy--;
 | 
			
		||||
	cx = s->cx;
 | 
			
		||||
	cy = s->cy;
 | 
			
		||||
	for (i = 0; i < sy; i++)
 | 
			
		||||
		screen_redraw_line(c, s, wp->yoff, i);
 | 
			
		||||
	s->cx = cx;
 | 
			
		||||
	s->cy = cy;
 | 
			
		||||
 | 
			
		||||
	/* Draw the bottom window. */
 | 
			
		||||
	if (c->sy > 2 && w->panes[1] != NULL) {
 | 
			
		||||
		wp = w->panes[1];
 | 
			
		||||
	/* Draw the panes. */
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
		s = wp->screen;
 | 
			
		||||
 | 
			
		||||
		sy = screen_size_y(s);
 | 
			
		||||
		if (wp->yoff + screen_size_y(s) == s->cy)
 | 
			
		||||
		if (!status && TAILQ_NEXT(wp, entry) == NULL)
 | 
			
		||||
			sy--;
 | 
			
		||||
 | 
			
		||||
		cx = s->cx;
 | 
			
		||||
		cy = s->cy;
 | 
			
		||||
		for (i = 0; i < sy; i++)
 | 
			
		||||
			screen_redraw_line(c, s, wp->yoff, i);
 | 
			
		||||
		if (wp->yoff + sy <= w->sy) {
 | 
			
		||||
			for (i = 0; i < sy; i++)
 | 
			
		||||
				screen_redraw_line(c, s, wp->yoff, i);
 | 
			
		||||
			if (TAILQ_NEXT(wp, entry) != NULL)
 | 
			
		||||
				screen_redraw_blanky(c, wp->yoff + sy, 1, '-');
 | 
			
		||||
		}
 | 
			
		||||
		s->cx = cx;
 | 
			
		||||
		s->cy = cy;
 | 
			
		||||
	}
 | 
			
		||||
@@ -82,12 +68,7 @@ screen_redraw_screen(struct client *c, struct screen *s)
 | 
			
		||||
	if (w->sx < c->sx)
 | 
			
		||||
		screen_redraw_blankx(c, w->sx, c->sx - w->sx);
 | 
			
		||||
	if (w->sy < c->sy - status)
 | 
			
		||||
		screen_redraw_blanky(c, w->sy, c->sy - w->sy);
 | 
			
		||||
 | 
			
		||||
	/* Draw separator line. */
 | 
			
		||||
	s = w->panes[0]->screen;
 | 
			
		||||
	if (c->sy > 1 && screen_size_y(s) != w->sy)
 | 
			
		||||
		screen_redraw_blanky(c, screen_size_y(s), 1);
 | 
			
		||||
		screen_redraw_blanky(c, w->sy, c->sy - w->sy, '=');
 | 
			
		||||
 | 
			
		||||
	/* Draw the status line. */
 | 
			
		||||
	screen_redraw_status(c);
 | 
			
		||||
@@ -120,7 +101,7 @@ screen_redraw_blankx(struct client *c, u_int ox, u_int nx)
 | 
			
		||||
 | 
			
		||||
/* Draw blank lines. */
 | 
			
		||||
void
 | 
			
		||||
screen_redraw_blanky(struct client *c, u_int oy, u_int ny)
 | 
			
		||||
screen_redraw_blanky(struct client *c, u_int oy, u_int ny, char ch)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i, j;
 | 
			
		||||
 | 
			
		||||
@@ -129,7 +110,7 @@ screen_redraw_blanky(struct client *c, u_int oy, u_int ny)
 | 
			
		||||
		tty_putcode2(&c->tty, TTYC_CUP, oy + j, 0);
 | 
			
		||||
		for (i = 0; i < c->sx; i++) {
 | 
			
		||||
			if (j == 0)
 | 
			
		||||
				tty_putc(&c->tty, '-');
 | 
			
		||||
				tty_putc(&c->tty, ch);
 | 
			
		||||
			else
 | 
			
		||||
				tty_putc(&c->tty, ' ');
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server.c,v 1.99 2009-01-13 06:50:10 nicm Exp $ */
 | 
			
		||||
/* $Id: server.c,v 1.100 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -49,9 +49,9 @@ void		 server_fill_clients(struct pollfd **);
 | 
			
		||||
void		 server_handle_clients(struct pollfd **);
 | 
			
		||||
struct client	*server_accept_client(int);
 | 
			
		||||
void		 server_handle_client(struct client *);
 | 
			
		||||
void		 server_handle_window(struct window *, int);
 | 
			
		||||
void		 server_handle_window(struct window *, struct window_pane *wp);
 | 
			
		||||
void		 server_lost_client(struct client *);
 | 
			
		||||
int	 	 server_lost_window(struct window *, int);
 | 
			
		||||
void	 	 server_check_window(struct window *);
 | 
			
		||||
void		 server_check_redraw(struct client *);
 | 
			
		||||
void		 server_redraw_locked(struct client *);
 | 
			
		||||
void		 server_check_timers(struct client *);
 | 
			
		||||
@@ -171,6 +171,7 @@ server_start(const char *path)
 | 
			
		||||
int
 | 
			
		||||
server_main(const char *srv_path, int srv_fd)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	struct pollfd	*pfds, *pfd;
 | 
			
		||||
	int		 nfds, xtimeout;
 | 
			
		||||
	u_int		 i, n;
 | 
			
		||||
@@ -184,7 +185,11 @@ server_main(const char *srv_path, int srv_fd)
 | 
			
		||||
	while (!sigterm) {
 | 
			
		||||
		/* Initialise pollfd array. */
 | 
			
		||||
		nfds = 1;
 | 
			
		||||
		nfds += ARRAY_LENGTH(&windows) * 2;
 | 
			
		||||
		for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
			w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
			if (w != NULL)
 | 
			
		||||
				nfds += window_count_panes(w);
 | 
			
		||||
		}
 | 
			
		||||
		nfds += ARRAY_LENGTH(&clients) * 2;
 | 
			
		||||
		pfds = xrealloc(pfds, nfds, sizeof *pfds);
 | 
			
		||||
		pfd = pfds;
 | 
			
		||||
@@ -282,17 +287,16 @@ server_fill_windows(struct pollfd **pfd)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i, j;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
		w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
		for (j = 0; j < 2; j++) {
 | 
			
		||||
			if (w != NULL)
 | 
			
		||||
				wp = w->panes[j];
 | 
			
		||||
			if (w == NULL || wp == NULL || wp->fd == -1) {
 | 
			
		||||
				(*pfd)->fd = -1;
 | 
			
		||||
			} else {
 | 
			
		||||
				(*pfd)->fd = wp->fd;
 | 
			
		||||
		if (w == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			(*pfd)->fd = wp->fd;
 | 
			
		||||
			if (wp->fd != -1) {
 | 
			
		||||
				(*pfd)->events = POLLIN;
 | 
			
		||||
				if (BUFFER_USED(wp->out) > 0)
 | 
			
		||||
					(*pfd)->events |= POLLOUT;
 | 
			
		||||
@@ -308,24 +312,25 @@ server_handle_windows(struct pollfd **pfd)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i, j;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
		w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
		for (j = 0; j < 2; j++) {
 | 
			
		||||
			if (w != NULL)
 | 
			
		||||
				wp = w->panes[j];
 | 
			
		||||
			if (w != NULL && wp != NULL && wp->fd != -1) {
 | 
			
		||||
		if (w == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			if (wp->fd != -1) {
 | 
			
		||||
				if (buffer_poll(*pfd, wp->in, wp->out) != 0) {
 | 
			
		||||
					if (server_lost_window(w, j) != 0) {
 | 
			
		||||
						(*pfd) += 1 - j;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					close(wp->fd);
 | 
			
		||||
					wp->fd = -1;
 | 
			
		||||
				} else
 | 
			
		||||
					server_handle_window(w, j);
 | 
			
		||||
					server_handle_window(w, wp);
 | 
			
		||||
			}
 | 
			
		||||
			(*pfd)++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		server_check_window(w);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -660,14 +665,14 @@ server_lost_client(struct client *c)
 | 
			
		||||
 | 
			
		||||
/* Handle window data. */
 | 
			
		||||
void
 | 
			
		||||
server_handle_window(struct window *w, int pane)
 | 
			
		||||
server_handle_window(struct window *w, struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
	int		 action, update;
 | 
			
		||||
 | 
			
		||||
	window_pane_parse(w->panes[pane]);
 | 
			
		||||
	window_pane_parse(wp);
 | 
			
		||||
 | 
			
		||||
	if (!(w->flags & WINDOW_BELL) && !(w->flags & WINDOW_ACTIVITY))
 | 
			
		||||
		return;
 | 
			
		||||
@@ -694,7 +699,7 @@ server_handle_window(struct window *w, int pane)
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			case BELL_CURRENT:
 | 
			
		||||
				if (w->active != w->panes[pane])
 | 
			
		||||
				if (w->active != wp)
 | 
			
		||||
					break;
 | 
			
		||||
				for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
					c = ARRAY_ITEM(&clients, i);
 | 
			
		||||
@@ -719,29 +724,35 @@ server_handle_window(struct window *w, int pane)
 | 
			
		||||
	w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Lost window: move clients on to next window. */
 | 
			
		||||
int
 | 
			
		||||
server_lost_window(struct window *w, int pane)
 | 
			
		||||
/* Check if window still exists.. */
 | 
			
		||||
void
 | 
			
		||||
server_check_window(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp, *wq;
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i, j;
 | 
			
		||||
	int		 	 destroyed;
 | 
			
		||||
	int		 	 destroyed, flag;
 | 
			
		||||
 | 
			
		||||
	wp = w->panes[pane];
 | 
			
		||||
	log_debug("lost window %d (%s pane %d)", wp->fd, w->name, pane);
 | 
			
		||||
	flag = options_get_number(&w->options, "remain-on-exit");
 | 
			
		||||
 | 
			
		||||
	if (window_remove_pane(w, wp) == 0) {
 | 
			
		||||
		server_redraw_window(w);
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
	destroyed = 1;
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(&w->options, "remain-on-exit")) {
 | 
			
		||||
		wp->fd = -1;
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
	wp = TAILQ_FIRST(&w->panes);
 | 
			
		||||
	while (wp != NULL) {
 | 
			
		||||
		wq = TAILQ_NEXT(wp, entry);
 | 
			
		||||
		if (wp->fd != -1)
 | 
			
		||||
			destroyed = 0;
 | 
			
		||||
		else if (!flag) {
 | 
			
		||||
			window_remove_pane(w, wp);
 | 
			
		||||
			server_redraw_window(w);
 | 
			
		||||
		}
 | 
			
		||||
		wp = wq;
 | 
			
		||||
	} 
 | 
			
		||||
 | 
			
		||||
	if (!destroyed)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
			
		||||
		s = ARRAY_ITEM(&sessions, i);
 | 
			
		||||
@@ -775,7 +786,6 @@ server_lost_window(struct window *w, int pane)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	recalculate_sizes();
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call any once-per-second timers. */
 | 
			
		||||
@@ -784,7 +794,7 @@ server_second_timers(void)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int		 	 i, j;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
	int			 xtimeout;
 | 
			
		||||
	struct tm	 	 now, then;
 | 
			
		||||
	static time_t	 	 last_t = 0;
 | 
			
		||||
@@ -799,10 +809,8 @@ server_second_timers(void)
 | 
			
		||||
		w = ARRAY_ITEM(&windows, i);
 | 
			
		||||
		if (w == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
		for (j = 0; j < 2; j++) {
 | 
			
		||||
			wp = w->panes[j];
 | 
			
		||||
			if (wp == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			if (wp->mode != NULL && wp->mode->timer != NULL)
 | 
			
		||||
				wp->mode->timer(wp);
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								status.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: status.c,v 1.61 2009-01-12 18:22:47 nicm Exp $ */
 | 
			
		||||
/* $Id: status.c,v 1.62 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -43,6 +43,7 @@ status_redraw(struct client *c)
 | 
			
		||||
	struct session		       *s = c->session;
 | 
			
		||||
	struct winlink		       *wl;
 | 
			
		||||
	struct window_pane	       *wp;
 | 
			
		||||
	struct screen		       *sc;
 | 
			
		||||
	char		 	       *left, *right, *text, *ptr;
 | 
			
		||||
	size_t				llen, rlen, offset, xx, yy, sy;
 | 
			
		||||
	size_t				size, start, width;
 | 
			
		||||
@@ -258,20 +259,22 @@ off:
 | 
			
		||||
	 * status is off. Not sure this is the right place for this.
 | 
			
		||||
	 */
 | 
			
		||||
	screen_write_start(&ctx, NULL, &c->status);
 | 
			
		||||
	wp = s->curw->window->panes[0];
 | 
			
		||||
 	sy = wp->sy;
 | 
			
		||||
	if (s->curw->window->panes[1] != NULL) {
 | 
			
		||||
		wp = s->curw->window->panes[1];
 | 
			
		||||
		sy += wp->sy + 1;
 | 
			
		||||
 | 
			
		||||
	sy = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
 | 
			
		||||
		sy += wp->sy;
 | 
			
		||||
		sc = wp->screen;
 | 
			
		||||
	}
 | 
			
		||||
	sy++;
 | 
			
		||||
 | 
			
		||||
	screen_write_cursormove(&ctx, 0, 0);
 | 
			
		||||
	if (sy < c->sy - 1) {
 | 
			
		||||
		/* If the screen is too small, use blank. */
 | 
			
		||||
		for (offset = 0; offset < c->sx; offset++)
 | 
			
		||||
			screen_write_putc(&ctx, &gc, ' ');
 | 
			
		||||
	} else {
 | 
			
		||||
		screen_write_copy(&ctx, wp->screen, 0, wp->screen->grid->hsize +
 | 
			
		||||
		    screen_size_y(wp->screen) - 1, c->sx, 1);
 | 
			
		||||
		screen_write_copy(&ctx,
 | 
			
		||||
		    sc, 0, sc->grid->hsize + screen_size_y(sc) - 1, c->sx, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.h,v 1.229 2009-01-13 06:50:10 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.h,v 1.230 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -124,6 +124,9 @@ extern const char    *__progname;
 | 
			
		||||
/* Default environment. */
 | 
			
		||||
#define CHILD_ENVIRON { NULL /* TMUX= */, "TERM=screen", NULL }
 | 
			
		||||
 | 
			
		||||
/* Minimum pane size. */
 | 
			
		||||
#define PANE_MINIMUM 4	/* includes separator line */
 | 
			
		||||
 | 
			
		||||
/* Fatal errors. */
 | 
			
		||||
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
 | 
			
		||||
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
 | 
			
		||||
@@ -578,6 +581,9 @@ struct window_pane {
 | 
			
		||||
	u_int		 sy;
 | 
			
		||||
 | 
			
		||||
	u_int		 yoff;
 | 
			
		||||
 | 
			
		||||
	int		 flags;
 | 
			
		||||
#define PANE_HIDDEN 0x1
 | 
			
		||||
	
 | 
			
		||||
	char		*cmd;
 | 
			
		||||
	char		*cwd;
 | 
			
		||||
@@ -593,14 +599,17 @@ struct window_pane {
 | 
			
		||||
 | 
			
		||||
	const struct window_mode *mode;
 | 
			
		||||
	void		*modedata;
 | 
			
		||||
 | 
			
		||||
	TAILQ_ENTRY(window_pane) entry;
 | 
			
		||||
};
 | 
			
		||||
TAILQ_HEAD(window_panes, window_pane);
 | 
			
		||||
 | 
			
		||||
/* Window structure. */
 | 
			
		||||
struct window {
 | 
			
		||||
	char		*name;
 | 
			
		||||
 | 
			
		||||
	struct window_pane *active;
 | 
			
		||||
	struct window_pane *panes[2];
 | 
			
		||||
	struct window_pane *active;	
 | 
			
		||||
	struct window_panes panes;
 | 
			
		||||
 | 
			
		||||
	u_int		 sx;
 | 
			
		||||
	u_int		 sy;
 | 
			
		||||
@@ -1378,13 +1387,21 @@ struct winlink	*winlink_next(struct winlinks *, struct winlink *);
 | 
			
		||||
struct winlink	*winlink_previous(struct winlinks *, struct winlink *);
 | 
			
		||||
void		 winlink_stack_push(struct winlink_stack *, struct winlink *);
 | 
			
		||||
void		 winlink_stack_remove(struct winlink_stack *, struct winlink *);
 | 
			
		||||
int	 	 window_index(struct window *, u_int *);
 | 
			
		||||
struct window	*window_create(const char *, const char *,
 | 
			
		||||
		     const char *, const char **, u_int, u_int, u_int);
 | 
			
		||||
void		 window_destroy(struct window *);
 | 
			
		||||
int		 window_resize(struct window *, u_int, u_int);
 | 
			
		||||
int		 window_add_pane(struct window *,
 | 
			
		||||
		     u_int, const char *, const char *, const char **, u_int);
 | 
			
		||||
int		 window_remove_pane(struct window *, struct window_pane *);
 | 
			
		||||
void		 window_set_active_pane(struct window *, struct window_pane *);
 | 
			
		||||
struct window_pane *window_add_pane(struct window *,
 | 
			
		||||
    		     const char *, const char *, const char **, u_int);
 | 
			
		||||
void		 window_remove_pane(struct window *, struct window_pane *);
 | 
			
		||||
u_int		 window_index_of_pane(struct window *, struct window_pane *);
 | 
			
		||||
struct window_pane *window_pane_at_index(struct window *, u_int);
 | 
			
		||||
void  		 window_fit_panes(struct window *);
 | 
			
		||||
void		 window_update_panes(struct window *);
 | 
			
		||||
u_int		 window_count_panes(struct window *);
 | 
			
		||||
void		 window_destroy_panes(struct window *);
 | 
			
		||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
 | 
			
		||||
void		 window_pane_destroy(struct window_pane *);
 | 
			
		||||
int		 window_pane_spawn(struct window_pane *,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tty-write.c,v 1.5 2009-01-12 18:22:47 nicm Exp $ */
 | 
			
		||||
/* $Id: tty-write.c,v 1.6 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -38,7 +38,7 @@ tty_vwrite_window(void *ptr, enum tty_cmd cmd, va_list ap)
 | 
			
		||||
	va_list		 	 aq;
 | 
			
		||||
	u_int		 	 i;
 | 
			
		||||
 | 
			
		||||
	if (wp->window->flags & WINDOW_HIDDEN)
 | 
			
		||||
	if (wp->window->flags & WINDOW_HIDDEN || wp->flags & PANE_HIDDEN)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										305
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										305
									
								
								window.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: window.c,v 1.57 2009-01-13 06:50:10 nicm Exp $ */
 | 
			
		||||
/* $Id: window.c,v 1.58 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -204,17 +204,29 @@ winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
window_index(struct window *s, u_int *i)
 | 
			
		||||
{
 | 
			
		||||
	for (*i = 0; *i < ARRAY_LENGTH(&windows); (*i)++) {
 | 
			
		||||
		if (s == ARRAY_ITEM(&windows, *i))
 | 
			
		||||
			return (0);
 | 
			
		||||
	}
 | 
			
		||||
	return (-1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct window *
 | 
			
		||||
window_create(const char *name, const char *cmd,
 | 
			
		||||
    const char *cwd, const char **envp, u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
	char		*ptr, *copy;
 | 
			
		||||
 | 
			
		||||
	w = xmalloc(sizeof *w);
 | 
			
		||||
	w->flags = 0;
 | 
			
		||||
	w->panes[0] = NULL;
 | 
			
		||||
	w->panes[1] = NULL;
 | 
			
		||||
 | 
			
		||||
	TAILQ_INIT(&w->panes);
 | 
			
		||||
	w->active = NULL;
 | 
			
		||||
 | 
			
		||||
	w->sx = sx;
 | 
			
		||||
	w->sy = sy;
 | 
			
		||||
@@ -244,14 +256,21 @@ window_create(const char *name, const char *cmd,
 | 
			
		||||
	} else
 | 
			
		||||
		w->name = xstrdup(name);
 | 
			
		||||
 | 
			
		||||
	ARRAY_ADD(&windows, w);
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&windows, i) == NULL) {
 | 
			
		||||
			ARRAY_SET(&windows, i, w);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (i == ARRAY_LENGTH(&windows))
 | 
			
		||||
		ARRAY_ADD(&windows, w);
 | 
			
		||||
	w->references = 0;
 | 
			
		||||
 | 
			
		||||
	if (window_add_pane(w, w->sy, cmd, cwd, envp, hlimit) < 0) {
 | 
			
		||||
	if (window_add_pane(w, cmd, cwd, envp, hlimit) == NULL) {
 | 
			
		||||
		window_destroy(w);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	}
 | 
			
		||||
	w->active = w->panes[0];
 | 
			
		||||
	w->active = TAILQ_FIRST(&w->panes);
 | 
			
		||||
	return (w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -260,17 +279,15 @@ window_destroy(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&windows, i) == w)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	ARRAY_REMOVE(&windows, i);
 | 
			
		||||
	if (window_index(w, &i) != 0)
 | 
			
		||||
		fatalx("index not found");
 | 
			
		||||
	ARRAY_SET(&windows, i, NULL);
 | 
			
		||||
	while (!ARRAY_EMPTY(&windows) && ARRAY_LAST(&windows) == NULL)
 | 
			
		||||
		ARRAY_TRUNC(&windows, 1);
 | 
			
		||||
 | 
			
		||||
	options_free(&w->options);
 | 
			
		||||
 | 
			
		||||
	window_pane_destroy(w->panes[0]);
 | 
			
		||||
	if (w->panes[1] != NULL)
 | 
			
		||||
		window_pane_destroy(w->panes[1]);
 | 
			
		||||
	window_destroy_panes(w);
 | 
			
		||||
	
 | 
			
		||||
	xfree(w->name);
 | 
			
		||||
	xfree(w);
 | 
			
		||||
@@ -279,111 +296,213 @@ window_destroy(struct window *w)
 | 
			
		||||
int
 | 
			
		||||
window_resize(struct window *w, u_int sx, u_int sy)
 | 
			
		||||
{
 | 
			
		||||
	int	change;
 | 
			
		||||
	u_int	y0, y1;
 | 
			
		||||
	w->sx = sx;
 | 
			
		||||
	w->sy = sy;
 | 
			
		||||
 | 
			
		||||
	if (w->panes[1] == NULL)
 | 
			
		||||
		window_pane_resize(w->panes[0], sx, sy);
 | 
			
		||||
	else {
 | 
			
		||||
		if (sy <= 3) {
 | 
			
		||||
			y0 = 1;
 | 
			
		||||
			y1 = 1;
 | 
			
		||||
	window_fit_panes(w);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_fit_panes(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int			 npanes, canfit, total;
 | 
			
		||||
	int			 left;
 | 
			
		||||
	
 | 
			
		||||
	if (TAILQ_EMPTY(&w->panes))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Clear hidden flags. */
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry)
 | 
			
		||||
	    	wp->flags &= ~PANE_HIDDEN;
 | 
			
		||||
 | 
			
		||||
	/* Check the new size. */
 | 
			
		||||
	npanes = window_count_panes(w);
 | 
			
		||||
	if (w->sy <= PANE_MINIMUM * npanes) {
 | 
			
		||||
		/* How many can we fit? */
 | 
			
		||||
		canfit = w->sy / PANE_MINIMUM;
 | 
			
		||||
		if (canfit == 0) {
 | 
			
		||||
			/* None. Just use this size for the first. */
 | 
			
		||||
			TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
				if (wp == TAILQ_FIRST(&w->panes))
 | 
			
		||||
					wp->sy = w->sy;
 | 
			
		||||
				else
 | 
			
		||||
					wp->flags |= PANE_HIDDEN;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			y0 = w->panes[0]->sy;
 | 
			
		||||
			y1 = w->panes[1]->sy;
 | 
			
		||||
			
 | 
			
		||||
			change = sy - w->sy;
 | 
			
		||||
			if (change > 0) {
 | 
			
		||||
				while (change > 0) {
 | 
			
		||||
					if (y1 < y0)
 | 
			
		||||
						y1++;
 | 
			
		||||
					else
 | 
			
		||||
						y0++;
 | 
			
		||||
					change--;
 | 
			
		||||
			/* >=1, set minimum for them all. */
 | 
			
		||||
			TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
				if (canfit-- > 0)
 | 
			
		||||
					wp->sy = PANE_MINIMUM - 1;
 | 
			
		||||
				else
 | 
			
		||||
					wp->flags |= PANE_HIDDEN;
 | 
			
		||||
			}
 | 
			
		||||
			/* And increase the first by the rest. */
 | 
			
		||||
			TAILQ_FIRST(&w->panes)->sy += 1 + w->sy % PANE_MINIMUM;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* In theory they will all fit. Find the current total. */
 | 
			
		||||
		total = 0;
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry)
 | 
			
		||||
			total += wp->sy;
 | 
			
		||||
		total += npanes - 1;
 | 
			
		||||
 | 
			
		||||
		/* Growing or shrinking? */
 | 
			
		||||
		left = w->sy - total;
 | 
			
		||||
		if (left > 0) {
 | 
			
		||||
			/* Growing. Expand evenly. */
 | 
			
		||||
			while (left > 0) {
 | 
			
		||||
				TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
					wp->sy++;
 | 
			
		||||
					if (--left == 0)
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
			} else if (change < 0) {
 | 
			
		||||
				while (change < 0) {
 | 
			
		||||
					if (y1 > y0)
 | 
			
		||||
						y1--;
 | 
			
		||||
					else
 | 
			
		||||
						y0--;
 | 
			
		||||
					change++;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Shrinking. Reduce evenly down to minimum. */
 | 
			
		||||
			while (left < 0) {
 | 
			
		||||
				TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
					if (wp->sy <= PANE_MINIMUM - 1)
 | 
			
		||||
						continue;
 | 
			
		||||
					wp->sy--;
 | 
			
		||||
					if (++left == 0)
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		window_pane_resize(w->panes[0], sx, y0);
 | 
			
		||||
		window_pane_resize(w->panes[1], sx, y1);
 | 
			
		||||
		w->panes[1]->yoff = y0 + 1;
 | 
			
		||||
	}
 | 
			
		||||
			
 | 
			
		||||
	/* Now do the resize. */
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
		wp->sy--;
 | 
			
		||||
	    	window_pane_resize(wp, w->sx, wp->sy + 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w->sx = sx;
 | 
			
		||||
	w->sy = sy;
 | 
			
		||||
	return (0);
 | 
			
		||||
	/* Fill in the offsets. */
 | 
			
		||||
	window_update_panes(w);
 | 
			
		||||
 | 
			
		||||
	/* Switch the active window if necessary. */
 | 
			
		||||
	window_set_active_pane(w, w->active);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
window_add_pane(struct window *w, u_int y1,
 | 
			
		||||
void
 | 
			
		||||
window_update_panes(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane     *wp;
 | 
			
		||||
	u_int			yoff;
 | 
			
		||||
 | 
			
		||||
	yoff = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
		if (wp->flags & PANE_HIDDEN)
 | 
			
		||||
			continue;
 | 
			
		||||
		wp->yoff = yoff;
 | 
			
		||||
		yoff += wp->sy + 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_set_active_pane(struct window *w, struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	w->active = wp;
 | 
			
		||||
	while (w->active->flags & PANE_HIDDEN)
 | 
			
		||||
		w->active = TAILQ_PREV(w->active, window_panes, entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct window_pane *
 | 
			
		||||
window_add_pane(struct window *w, 
 | 
			
		||||
    const char *cmd, const char *cwd, const char **envp, u_int hlimit)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int			 y0;
 | 
			
		||||
	u_int			 wanty;
 | 
			
		||||
 | 
			
		||||
	if (w->panes[1] != NULL)
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	if (w->panes[0] == NULL) {
 | 
			
		||||
		/* No existing panes. */
 | 
			
		||||
		wp = w->panes[0] = window_pane_create(w, w->sx, w->sy, hlimit);
 | 
			
		||||
		wp->yoff = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* One existing pane. */
 | 
			
		||||
		if (y1 > w->sy)
 | 
			
		||||
			y1 = w->sy;
 | 
			
		||||
		y0 = w->sy - y1;
 | 
			
		||||
		if (y0 == 0) {
 | 
			
		||||
			y0 = 1;
 | 
			
		||||
			y1--;
 | 
			
		||||
		}
 | 
			
		||||
		if (y0 > 1)
 | 
			
		||||
			y0--;
 | 
			
		||||
		else if (y1 > 1)
 | 
			
		||||
			y1--;
 | 
			
		||||
		window_pane_resize(w->panes[0], w->sx, y0);
 | 
			
		||||
 | 
			
		||||
		wp = w->panes[1] = window_pane_create(w, w->sx, y1, hlimit);
 | 
			
		||||
		wp->yoff = y0 + 1;
 | 
			
		||||
	if (TAILQ_EMPTY(&w->panes))
 | 
			
		||||
		wanty = w->sy;
 | 
			
		||||
	else {
 | 
			
		||||
		if (w->active->sy < PANE_MINIMUM * 2)
 | 
			
		||||
			return (NULL);
 | 
			
		||||
		wanty = (w->active->sy / 2 + w->active->sy % 2) - 1;
 | 
			
		||||
		window_pane_resize(w->active, w->sx, w->active->sy / 2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wp = window_pane_create(w, w->sx, wanty, hlimit);
 | 
			
		||||
	if (TAILQ_EMPTY(&w->panes))
 | 
			
		||||
		TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
			
		||||
	else
 | 
			
		||||
		TAILQ_INSERT_AFTER(&w->panes, w->active, wp, entry);
 | 
			
		||||
	window_update_panes(w);
 | 
			
		||||
	if (window_pane_spawn(wp, cmd, cwd, envp) != 0) {
 | 
			
		||||
		window_remove_pane(w, wp);
 | 
			
		||||
		return (-1);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	}
 | 
			
		||||
	return (0);
 | 
			
		||||
	return (wp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
void
 | 
			
		||||
window_remove_pane(struct window *w, struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	int	pane;
 | 
			
		||||
	w->active = TAILQ_PREV(wp, window_panes, entry);
 | 
			
		||||
	if (w->active == NULL)
 | 
			
		||||
		w->active = TAILQ_NEXT(wp, entry);
 | 
			
		||||
 | 
			
		||||
	pane = 0;
 | 
			
		||||
	if (wp == w->panes[1])
 | 
			
		||||
		pane = 1;
 | 
			
		||||
	TAILQ_REMOVE(&w->panes, wp, entry);
 | 
			
		||||
	window_pane_destroy(wp);
 | 
			
		||||
 | 
			
		||||
	if (w->panes[1] != NULL) {
 | 
			
		||||
		window_pane_destroy(w->panes[pane]);
 | 
			
		||||
		w->panes[pane] = NULL;
 | 
			
		||||
		if (pane == 0) {
 | 
			
		||||
			w->panes[0] = w->panes[1];
 | 
			
		||||
			w->panes[1] = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		w->active = w->panes[0];
 | 
			
		||||
	window_fit_panes(w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		window_pane_resize(w->active, w->sx, w->sy);
 | 
			
		||||
		w->active->yoff = 0;
 | 
			
		||||
		return (0);
 | 
			
		||||
u_int
 | 
			
		||||
window_index_of_pane(struct window *w, struct window_pane *find)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int			 n;
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
		if (wp == find)
 | 
			
		||||
			return (n);
 | 
			
		||||
		n++;
 | 
			
		||||
	}
 | 
			
		||||
	fatalx("unknown pane");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct window_pane *
 | 
			
		||||
window_pane_at_index(struct window *w, u_int idx)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int			 n;
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
		if (n == idx)
 | 
			
		||||
			return (wp);
 | 
			
		||||
		n++;
 | 
			
		||||
	}
 | 
			
		||||
	return (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u_int
 | 
			
		||||
window_count_panes(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	u_int			 n;
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &w->panes, entry)
 | 
			
		||||
		n++;
 | 
			
		||||
	return (n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_destroy_panes(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
 | 
			
		||||
	while (!TAILQ_EMPTY(&w->panes)) {
 | 
			
		||||
		wp = TAILQ_FIRST(&w->panes);
 | 
			
		||||
		TAILQ_REMOVE(&w->panes, wp, entry);
 | 
			
		||||
		window_pane_destroy(wp);
 | 
			
		||||
	}
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct window_pane *
 | 
			
		||||
@@ -391,7 +510,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
 | 
			
		||||
	wp = xmalloc(sizeof *wp);
 | 
			
		||||
	wp = xcalloc(1, sizeof *wp);
 | 
			
		||||
	wp->window = w;
 | 
			
		||||
 | 
			
		||||
	wp->cmd = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: xmalloc.c,v 1.6 2008-08-07 20:20:52 nicm Exp $ */
 | 
			
		||||
/* $Id: xmalloc.c,v 1.7 2009-01-14 19:29:32 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2004 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -44,7 +44,7 @@ xcalloc(size_t nmemb, size_t size)
 | 
			
		||||
        void	*ptr;
 | 
			
		||||
 | 
			
		||||
        if (size == 0 || nmemb == 0)
 | 
			
		||||
                fatalx("zero size");
 | 
			
		||||
	{ abort();fatalx("zero size");}
 | 
			
		||||
        if (SIZE_MAX / nmemb < size)
 | 
			
		||||
                fatalx("nmemb * size > SIZE_MAX");
 | 
			
		||||
        if ((ptr = calloc(nmemb, size)) == NULL)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user