Module Name:    src
Committed By:   jmmv
Date:           Wed Aug 17 18:48:37 UTC 2011

Modified Files:
        src/external/bsd/tmux/dist: cmd-paste-buffer.c cmd-server-info.c
            cmd-string.c environ.c input.c job.c options.c screen-write.c
            screen.c server-fn.c session.c tty-acs.c tty-keys.c tty-term.c
            window.c
        src/external/bsd/tmux/dist/compat: imsg-buffer.c imsg.c
Removed Files:
        src/external/bsd/tmux/dist: cmd-copy-buffer.c cmd-generic.c
            cmd-last-pane.c cmd-last-window.c cmd-lock-client.c
            cmd-lock-session.c cmd-next-layout.c cmd-next-window.c
            cmd-previous-layout.c cmd-previous-window.c cmd-set-window-option.c
            cmd-show-window-options.c layout-string.c

Log Message:
Fix merge conflicts after tmux 1.5 import.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r0 src/external/bsd/tmux/dist/cmd-copy-buffer.c
cvs rdiff -u -r1.1.1.1 -r0 src/external/bsd/tmux/dist/cmd-generic.c \
    src/external/bsd/tmux/dist/cmd-last-pane.c \
    src/external/bsd/tmux/dist/cmd-last-window.c \
    src/external/bsd/tmux/dist/cmd-lock-client.c \
    src/external/bsd/tmux/dist/cmd-lock-session.c \
    src/external/bsd/tmux/dist/cmd-next-layout.c \
    src/external/bsd/tmux/dist/cmd-next-window.c \
    src/external/bsd/tmux/dist/cmd-previous-layout.c \
    src/external/bsd/tmux/dist/cmd-previous-window.c \
    src/external/bsd/tmux/dist/cmd-set-window-option.c \
    src/external/bsd/tmux/dist/cmd-show-window-options.c \
    src/external/bsd/tmux/dist/layout-string.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/tmux/dist/cmd-paste-buffer.c \
    src/external/bsd/tmux/dist/cmd-server-info.c \
    src/external/bsd/tmux/dist/cmd-string.c \
    src/external/bsd/tmux/dist/environ.c src/external/bsd/tmux/dist/input.c \
    src/external/bsd/tmux/dist/job.c src/external/bsd/tmux/dist/options.c \
    src/external/bsd/tmux/dist/screen-write.c \
    src/external/bsd/tmux/dist/screen.c \
    src/external/bsd/tmux/dist/server-fn.c \
    src/external/bsd/tmux/dist/session.c src/external/bsd/tmux/dist/tty-acs.c \
    src/external/bsd/tmux/dist/tty-keys.c \
    src/external/bsd/tmux/dist/tty-term.c src/external/bsd/tmux/dist/window.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/tmux/dist/compat/imsg-buffer.c \
    src/external/bsd/tmux/dist/compat/imsg.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/tmux/dist/cmd-paste-buffer.c
diff -u src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.2 src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.3
--- src/external/bsd/tmux/dist/cmd-paste-buffer.c:1.2	Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-paste-buffer.c	Wed Aug 17 18:48:35 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-paste-buffer.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-paste-buffer.c,v 1.3 2011/08/17 18:48:35 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -27,131 +27,73 @@
  * Paste paste buffer if present.
  */
 
-struct cmd_paste_buffer_data {
-	char	*target;
-	int	 buffer;
-
-	int	 flag_delete;
-	char	*sepstr;
-};
-
-void	cmd_paste_buffer_init(struct cmd *, int);
-int	cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
 int	cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
+
 void	cmd_paste_buffer_filter(
-	    struct window_pane *, const char *, size_t, char *);
-void	cmd_paste_buffer_free(struct cmd *);
-size_t	cmd_paste_buffer_print(struct cmd *, char *, size_t);
+	    struct window_pane *, const char *, size_t, const char *);
 
 const struct cmd_entry cmd_paste_buffer_entry = {
 	"paste-buffer", "pasteb",
+	"db:rs:t:", 0, 0,
 	"[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
-	0, "",
-	cmd_paste_buffer_init,
-	cmd_paste_buffer_parse,
-	cmd_paste_buffer_exec,
-	cmd_paste_buffer_free,
-	cmd_paste_buffer_print
+	0,
+	NULL,
+	NULL,
+	cmd_paste_buffer_exec
 };
 
-/* ARGSUSED */
-void
-cmd_paste_buffer_init(struct cmd *self, unused int arg)
-{
-	struct cmd_paste_buffer_data	*data;
-
-	self->data = data = xmalloc(sizeof *data);
-	data->target = NULL;
-	data->buffer = -1;
-	data->flag_delete = 0;
-	data->sepstr = xstrdup("\r");
-}
-
-int
-cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
-{
-	struct cmd_paste_buffer_data	*data;
-	int			 opt, n;
-	const char		*errstr;
-
-	cmd_paste_buffer_init(self, 0);
-	data = self->data;
-
-	while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) {
-		switch (opt) {
-		case 'b':
-			if (data->buffer == -1) {
-				n = strtonum(optarg, 0, INT_MAX, &errstr);
-				if (errstr != NULL) {
-					xasprintf(cause, "buffer %s", errstr);
-					goto error;
-				}
-				data->buffer = n;
-			}
-			break;
-		case 'd':
-			data->flag_delete = 1;
-			break;
-		case 's':
-			if (data->sepstr != NULL)
-				xfree(data->sepstr);
-			data->sepstr = xstrdup(optarg);
-			break;
-		case 't':
-			if (data->target == NULL)
-				data->target = xstrdup(optarg);
-			break;
-		case 'r':
-			if (data->sepstr != NULL)
-				xfree(data->sepstr);
-			data->sepstr = xstrdup("\n");
-			break;
-		default:
-			goto usage;
-		}
-	}
-	argc -= optind;
-	argv += optind;
-
-	return (0);
-
-usage:
-	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
-
-error:
-	self->entry->free(self);
-	return (-1);
-}
-
 int
 cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_paste_buffer_data	*data = self->data;
-	struct window_pane		*wp;
-	struct session			*s;
-	struct paste_buffer		*pb;
+	struct args		*args = self->args;
+	struct window_pane	*wp;
+	struct session		*s;
+	struct paste_buffer	*pb;
+	const char		*sepstr;
+	char			*cause;
+	int			 buffer;
 
-	if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
+	if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
 		return (-1);
 
-	if (data->buffer == -1)
-		pb = paste_get_top(&s->buffers);
+	if (!args_has(args, 'b'))
+		buffer = -1;
 	else {
-		if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
-			ctx->error(ctx, "no buffer %d", data->buffer);
+		buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
+		if (cause != NULL) {
+			ctx->error(ctx, "buffer %s", cause);
+			xfree(cause);
 			return (-1);
 		}
 	}
 
-	if (pb != NULL)
-		cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
+	if (buffer == -1)
+		pb = paste_get_top(&global_buffers);
+	else {
+		pb = paste_get_index(&global_buffers, buffer);
+		if (pb == NULL) {
+			ctx->error(ctx, "no buffer %d", buffer);
+			return (-1);
+		}
+	}
+
+	if (pb != NULL) {
+		sepstr = args_get(args, 's');
+		if (sepstr == NULL) {
+			if (args_has(args, 'r'))
+				sepstr = "\n";
+			else
+				sepstr = "\r";
+		}
+		cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr);
+	}
 
 	/* Delete the buffer if -d. */
-	if (data->flag_delete) {
-		if (data->buffer == -1)
-			paste_free_top(&s->buffers);
+	if (args_has(args, 'd')) {
+		if (buffer == -1)
+			paste_free_top(&global_buffers);
 		else
-			paste_free_index(&s->buffers, data->buffer);
+			paste_free_index(&global_buffers, buffer);
 	}
 
 	return (0);
@@ -160,7 +102,7 @@
 /* Add bytes to a buffer and filter '\n' according to separator. */
 void
 cmd_paste_buffer_filter(
-    struct window_pane *wp, const char *data, size_t size, char *sep)
+    struct window_pane *wp, const char *data, size_t size, const char *sep)
 {
 	const char	*end = data + size;
 	const char	*lf;
@@ -177,46 +119,3 @@
 	if (end != data)
 		bufferevent_write(wp->event, data, end - data);
 }
-
-void
-cmd_paste_buffer_free(struct cmd *self)
-{
-	struct cmd_paste_buffer_data	*data = self->data;
-
-	if (data->target != NULL)
-		xfree(data->target);
-	if (data->sepstr != NULL)
-		xfree(data->sepstr);
-	xfree(data);
-}
-
-size_t
-cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
-{
-	struct cmd_paste_buffer_data	*data = self->data;
-	size_t				 off = 0;
-	int				 r_flag;
-
-	r_flag = 0;
-	if (data->sepstr != NULL)
-		r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
-
-	off += xsnprintf(buf, len, "%s", self->entry->name);
-	if (data == NULL)
-		return (off);
-	if (off < len && data->flag_delete)
-		off += xsnprintf(buf + off, len - off, " -d");
-	if (off < len && r_flag)
-		off += xsnprintf(buf + off, len - off, " -r");
-	if (off < len && data->buffer != -1)
-		off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
-	if (off < len && data->sepstr != NULL && !r_flag) {
-		size_t slen = strlen(data->sepstr);
-		char tmp[slen * 4 + 1];
-		strvisx(tmp, data->sepstr, slen, VIS_OCTAL|VIS_TAB|VIS_NL);
-		off += cmd_prarg(buf + off, len - off, " -s ", tmp);
-	}
-	if (off < len && data->target != NULL)
-		off += cmd_prarg(buf + off, len - off, " -t ", data->target);
-	return (off);
-}
Index: src/external/bsd/tmux/dist/cmd-server-info.c
diff -u src/external/bsd/tmux/dist/cmd-server-info.c:1.2 src/external/bsd/tmux/dist/cmd-server-info.c:1.3
--- src/external/bsd/tmux/dist/cmd-server-info.c:1.2	Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-server-info.c	Wed Aug 17 18:48:35 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-server-info.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-server-info.c,v 1.3 2011/08/17 18:48:35 jmmv Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <n...@users.sourceforge.net>
@@ -34,44 +34,43 @@
 
 const struct cmd_entry cmd_server_info_entry = {
 	"server-info", "info",
+	"", 0, 0,
 	"",
-	0, "",
+	0,
 	NULL,
 	NULL,
-	cmd_server_info_exec,
-	NULL,
-	NULL
+	cmd_server_info_exec
 };
 
 /* ARGSUSED */
 int
 cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct tty_term			*term;
-	struct client			*c;
-	struct session			*s;
-	struct winlink			*wl;
-	struct window			*w;
-	struct window_pane		*wp;
-	struct tty_code			*code;
-	struct tty_term_code_entry	*ent;
-	struct utsname			 un;
-	struct job			*job;
-	struct grid			*gd;
-	struct grid_line		*gl;
-	u_int		 		 i, j, k;
-	char				*tim;
-	time_t		 		 t;
-	u_int				 lines, ulines;
-	size_t				 size, usize;
+	struct tty_term				*term;
+	struct client				*c;
+	struct session				*s;
+	struct winlink				*wl;
+	struct window				*w;
+	struct window_pane			*wp;
+	struct tty_code				*code;
+	const struct tty_term_code_entry	*ent;
+	struct utsname				 un;
+	struct job				*job;
+	struct grid				*gd;
+	struct grid_line			*gl;
+	u_int		 			 i, j, k;
+	char					*tim;
+	time_t		 			 t;
+	u_int					 lines, ulines;
+	size_t					 size, usize;
 
 	tim = ctime(&start_time);
 	*strchr(tim, '\n') = '\0';
 	ctx->print(ctx,
-	    "tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
+	    "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
 	ctx->print(
 	    ctx, "socket path %s, debug level %d", socket_path, debug_level);
-	if (uname(&un) == 0) {
+	if (uname(&un) >= 0) {
 		ctx->print(ctx, "system is %s %s %s %s",
 		    un.sysname, un.release, un.version, un.machine);
 	}
@@ -88,10 +87,11 @@
 		if (c == NULL || c->session == NULL)
 			continue;
 
-		ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] "
+		ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho] "
 		    "[flags=0x%x/0x%x, references=%u]", i, c->tty.path,
 		    c->ibuf.fd, c->tty.fd, c->session->name,
-		    c->tty.sx, c->tty.sy, c->tty.termname, c->flags,
+		    c->tty.sx, c->tty.sy, c->tty.termname,
+		    c->tty.tio.c_cc[VERASE], c->flags,
 		    c->tty.flags, c->references);
 	}
 	ctx->print(ctx, "%s", "");
@@ -141,7 +141,7 @@
 	ctx->print(ctx, "%s", "");
 
 	ctx->print(ctx, "Terminals:");
-	SLIST_FOREACH(term, &tty_terms, entry) {
+	LIST_FOREACH(term, &tty_terms, entry) {
 		ctx->print(ctx, "%s [references=%u, flags=0x%x]:",
 		    term->name, term->references, term->flags);
 		for (i = 0; i < NTTYCODE; i++) {
@@ -176,9 +176,9 @@
 	ctx->print(ctx, "%s", "");
 
 	ctx->print(ctx, "Jobs:");
-	SLIST_FOREACH(job, &all_jobs, lentry) {
-		ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d, flags=0x%x]",
-		    job->cmd, job->fd, job->pid, job->status, job->flags);
+	LIST_FOREACH(job, &all_jobs, lentry) {
+		ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d]",
+		    job->cmd, job->fd, job->pid, job->status);
 	}
 
 	return (0);
Index: src/external/bsd/tmux/dist/cmd-string.c
diff -u src/external/bsd/tmux/dist/cmd-string.c:1.2 src/external/bsd/tmux/dist/cmd-string.c:1.3
--- src/external/bsd/tmux/dist/cmd-string.c:1.2	Sat Mar 12 03:02:58 2011
+++ src/external/bsd/tmux/dist/cmd-string.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: cmd-string.c,v 1.2 2011/03/12 03:02:58 christos Exp $ */
+/* $Id: cmd-string.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <n...@users.sourceforge.net>
Index: src/external/bsd/tmux/dist/environ.c
diff -u src/external/bsd/tmux/dist/environ.c:1.2 src/external/bsd/tmux/dist/environ.c:1.3
--- src/external/bsd/tmux/dist/environ.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/environ.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: environ.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: environ.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <n...@users.sourceforge.net>
Index: src/external/bsd/tmux/dist/input.c
diff -u src/external/bsd/tmux/dist/input.c:1.2 src/external/bsd/tmux/dist/input.c:1.3
--- src/external/bsd/tmux/dist/input.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/input.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: input.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: input.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -41,6 +41,9 @@
  *
  * - A state for the screen \033k...\033\\ sequence to rename a window. This is
  *   pretty stupid but not supporting it is more trouble than it is worth.
+ *
+ * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
+ *   be passed to the underlying teminal(s).
  */
 
 /* Helper functions. */
@@ -50,8 +53,6 @@
 
 /* Transition entry/exit handlers. */
 void	input_clear(struct input_ctx *);
-void	input_enter_dcs(struct input_ctx *);
-void	input_exit_dcs(struct input_ctx *);
 void	input_enter_osc(struct input_ctx *);
 void	input_exit_osc(struct input_ctx *);
 void	input_enter_apc(struct input_ctx *);
@@ -68,6 +69,7 @@
 int	input_esc_dispatch(struct input_ctx *);
 int	input_csi_dispatch(struct input_ctx *);
 void	input_csi_dispatch_sgr(struct input_ctx *);
+int	input_dcs_dispatch(struct input_ctx *);
 int	input_utf8_open(struct input_ctx *);
 int	input_utf8_add(struct input_ctx *);
 int	input_utf8_close(struct input_ctx *);
@@ -124,6 +126,7 @@
 	INPUT_CSI_CUU,
 	INPUT_CSI_DA,
 	INPUT_CSI_DCH,
+	INPUT_CSI_DECSCUSR,
 	INPUT_CSI_DECSTBM,
 	INPUT_CSI_DL,
 	INPUT_CSI_DSR,
@@ -166,6 +169,7 @@
 	{ 'l', "?", INPUT_CSI_RM_PRIVATE },
 	{ 'm', "",  INPUT_CSI_SGR },
 	{ 'n', "",  INPUT_CSI_DSR },
+	{ 'q', " ", INPUT_CSI_DECSCUSR },
 	{ 'r', "",  INPUT_CSI_DECSTBM },
 };
 
@@ -204,6 +208,7 @@
 const struct input_transition input_state_dcs_parameter_table[];
 const struct input_transition input_state_dcs_intermediate_table[];
 const struct input_transition input_state_dcs_handler_table[];
+const struct input_transition input_state_dcs_escape_table[];
 const struct input_transition input_state_dcs_ignore_table[];
 const struct input_transition input_state_osc_string_table[];
 const struct input_transition input_state_apc_string_table[];
@@ -286,10 +291,17 @@
 /* dcs_handler state definition. */
 const struct input_state input_state_dcs_handler = {
 	"dcs_handler",
-	input_enter_dcs, input_exit_dcs,
+	NULL, NULL,
 	input_state_dcs_handler_table
 };
 
+/* dcs_escape state definition. */
+const struct input_state input_state_dcs_escape = {
+	"dcs_escape",
+	NULL, NULL,
+	input_state_dcs_escape_table
+};
+
 /* dcs_ignore state definition. */
 const struct input_state input_state_dcs_ignore = {
 	"dcs_ignore",
@@ -482,7 +494,7 @@
 	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore },
 	{ 0x3b, 0x3b, input_parameter,	  &input_state_dcs_parameter },
 	{ 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
-	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler },
+	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
 	{ 0x7f, 0xff, NULL,		  NULL },
 
 	{ -1, -1, NULL, NULL }
@@ -500,7 +512,7 @@
 	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore },
 	{ 0x3b, 0x3b, input_parameter,	  NULL },
 	{ 0x3c, 0x3f, NULL,		  &input_state_dcs_ignore },
-	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler },
+	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
 	{ 0x7f, 0xff, NULL,		  NULL },
 
 	{ -1, -1, NULL, NULL }
@@ -515,7 +527,7 @@
 	{ 0x1c, 0x1f, NULL,		  NULL },
 	{ 0x20, 0x2f, input_intermediate, NULL },
 	{ 0x30, 0x3f, NULL,		  &input_state_dcs_ignore },
-	{ 0x40, 0x7e, NULL,		  &input_state_dcs_handler },
+	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
 	{ 0x7f, 0xff, NULL,		  NULL },
 
 	{ -1, -1, NULL, NULL }
@@ -523,18 +535,27 @@
 
 /* dcs_handler state table. */
 const struct input_transition input_state_dcs_handler_table[] = {
-	INPUT_STATE_ANYWHERE,
+	/* No INPUT_STATE_ANYWHERE */
 
-	{ 0x00, 0x17, NULL,	    NULL },
-	{ 0x19, 0x19, input_input,  NULL },
-	{ 0x1c, 0x1f, input_input,  NULL },
-	{ 0x20, 0x7e, input_input,  NULL },
-	{ 0x7f, 0xff, NULL,	    NULL },
+	{ 0x00, 0x1a, input_input,  NULL },
+	{ 0x1b, 0x1b, NULL,	    &input_state_dcs_escape },
+	{ 0x1c, 0xff, input_input,  NULL },
+
+	{ -1, -1, NULL, NULL }
+};
+
+/* dcs_escape state table. */
+const struct input_transition input_state_dcs_escape_table[] = {
+	/* No INPUT_STATE_ANYWHERE */
+
+	{ 0x00, 0x5b, input_input,	  &input_state_dcs_handler },
+	{ 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
+	{ 0x5d, 0xff, input_input,	  &input_state_dcs_handler },
 
 	{ -1, -1, NULL, NULL }
 };
 
-/* device_ignore state table. */
+/* dcs_ignore state table. */
 const struct input_transition input_state_dcs_ignore_table[] = {
 	INPUT_STATE_ANYWHERE,
 
@@ -770,7 +791,7 @@
 	return (0);
 }
 
-/* Get an argument or return default value..*/
+/* Get an argument or return default value. */
 int
 input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
 {
@@ -812,6 +833,9 @@
 	*ictx->param_buf = '\0';
 	ictx->param_len = 0;
 
+	*ictx->input_buf = '\0';
+	ictx->input_len = 0;
+
 	ictx->flags &= ~INPUT_DISCARD;
 }
 
@@ -953,7 +977,7 @@
 		screen_write_insertmode(sctx, 0);
 		screen_write_kcursormode(sctx, 0);
 		screen_write_kkeypadmode(sctx, 0);
-		screen_write_mousemode(sctx, 0);
+		screen_write_mousemode_off(sctx);
 
 		screen_write_clearscreen(sctx);
 		screen_write_cursormove(sctx, 0, 0);
@@ -1156,7 +1180,13 @@
 			screen_write_cursormode(&ictx->ctx, 0);
 			break;
 		case 1000:
-			screen_write_mousemode(&ictx->ctx, 0);
+		case 1001:
+		case 1002:
+		case 1003:
+			screen_write_mousemode_off(&ictx->ctx);
+			break;
+		case 1005:
+			screen_write_utf8mousemode(&ictx->ctx, 0);
 			break;
 		case 1049:
 			window_pane_alternate_off(wp, &ictx->cell);
@@ -1192,7 +1222,18 @@
 			screen_write_cursormode(&ictx->ctx, 1);
 			break;
 		case 1000:
-			screen_write_mousemode(&ictx->ctx, 1);
+			screen_write_mousemode_on(
+			    &ictx->ctx, MODE_MOUSE_STANDARD);
+			break;
+		case 1002:
+			screen_write_mousemode_on(
+			    &ictx->ctx, MODE_MOUSE_BUTTON);
+			break;
+		case 1003:
+			screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
+			break;
+		case 1005:
+			screen_write_utf8mousemode(&ictx->ctx, 1);
 			break;
 		case 1049:
 			window_pane_alternate_on(wp, &ictx->cell);
@@ -1220,6 +1261,10 @@
 		n = input_get(ictx, 0, 1, 1);
 		screen_write_cursormove(sctx, s->cx, n - 1);
 		break;
+	case INPUT_CSI_DECSCUSR:
+		n = input_get(ictx, 0, 0, 0);
+		screen_set_cursor_style(s, n);
+		break;
 	}
 
 	return (0);
@@ -1257,7 +1302,7 @@
 					gc->fg = 8;
 				} else if (n == 48) {
 					gc->flags &= ~GRID_FLAG_BG256;
-					gc->fg = 8;
+					gc->bg = 8;
 				}
 
 			} else {
@@ -1371,20 +1416,26 @@
 	}
 }
 
-/* DCS string started. */
-void
-input_enter_dcs(struct input_ctx *ictx)
+/* DCS terminator (ST) received. */
+int
+input_dcs_dispatch(struct input_ctx *ictx)
 {
-	log_debug("%s", __func__);
+	const char	prefix[] = "tmux;";
+	const u_int	prefix_len = (sizeof prefix) - 1;
 
-	ictx->input_len = 0;
-}
+	if (ictx->flags & INPUT_DISCARD)
+		return (0);
 
-/* DCS terminator (ST) received. */
-void
-input_exit_dcs(unused struct input_ctx *ictx)
-{
-	log_debug("%s", __func__);
+	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+
+	/* Check for tmux prefix. */
+	if (ictx->input_len >= prefix_len &&
+	    strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
+		screen_write_rawstring(&ictx->ctx,
+		    ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
+	}
+
+	return (0);
 }
 
 /* OSC string started. */
@@ -1393,24 +1444,46 @@
 {
 	log_debug("%s", __func__);
 
-	ictx->input_len = 0;
+	input_clear(ictx);
 }
 
 /* OSC terminator (ST) received. */
 void
 input_exit_osc(struct input_ctx *ictx)
 {
-	if (ictx->flags & INPUT_DISCARD)
-		return;
-	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+	u_char *p = ictx->input_buf;
+	int	option;
 
-	if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
+	if (ictx->flags & INPUT_DISCARD)
 		return;
-	if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
+	if (ictx->input_len < 1 || *p < '0' || *p > '9')
 		return;
 
-	screen_set_title(ictx->ctx.s, (const char *)ictx->input_buf + 2);
-	server_status_window(ictx->wp->window);
+	log_debug("%s: \"%s\"", __func__, p);
+
+	option = 0;
+	while (*p >= '0' && *p <= '9')
+		option = option * 10 + *p++ - '0';
+	if (*p == ';')
+		p++;
+
+	switch (option) {
+	case 0:
+	case 2:
+		screen_set_title(ictx->ctx.s, p);
+		server_status_window(ictx->wp->window);
+		break;
+	case 12:
+		screen_set_cursor_colour(ictx->ctx.s, p);
+		break;
+	case 112:
+		if (*p == '\0') /* No arguments allowed. */
+			screen_set_cursor_colour(ictx->ctx.s, "");
+		break;
+	default:
+		log_debug("%s: unknown '%u'", __func__, option);
+		break;
+	}
 }
 
 /* APC string started. */
@@ -1419,7 +1492,7 @@
 {
 	log_debug("%s", __func__);
 
-	ictx->input_len = 0;
+	input_clear(ictx);
 }
 
 /* APC terminator (ST) received. */
@@ -1440,7 +1513,7 @@
 {
 	log_debug("%s", __func__);
 
-	ictx->input_len = 0;
+	input_clear(ictx);
 }
 
 /* Rename terminator (ST) received. */
Index: src/external/bsd/tmux/dist/job.c
diff -u src/external/bsd/tmux/dist/job.c:1.2 src/external/bsd/tmux/dist/job.c:1.3
--- src/external/bsd/tmux/dist/job.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/job.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: job.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: job.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <n...@users.sourceforge.net>
@@ -30,100 +30,99 @@
  * output.
  */
 
+void	job_callback(struct bufferevent *, short, void *);
+
 /* All jobs list. */
-struct joblist	all_jobs = SLIST_HEAD_INITIALIZER(all_jobs);
+struct joblist	all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
 
-RB_GENERATE(jobs, job, entry, job_cmp);
+/* Start a job running, if it isn't already. */
+struct job *
+job_run(const char *cmd,
+    void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
+{
+	struct job	*job;
+	struct environ	 env;
+	pid_t		 pid;
+	int		 nullfd, out[2];
 
-void	job_callback(struct bufferevent *, short, void *);
+	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
+		return (NULL);
 
-int
-job_cmp(struct job *job1, struct job *job2)
-{
-	return (strcmp(job1->cmd, job2->cmd));
-}
+	environ_init(&env);
+	environ_copy(&global_environ, &env);
+	server_fill_environ(NULL, &env);
 
-/* Initialise job tree. */
-void
-job_tree_init(struct jobs *jobs)
-{
-	RB_INIT(jobs);
-}
+	switch (pid = fork()) {
+	case -1:
+		environ_free(&env);
+		return (NULL);
+	case 0:		/* child */
+		clear_signals(1);
 
-/* Destroy a job tree. */
-void
-job_tree_free(struct jobs *jobs)
-{
-	struct job	*job;
+		environ_push(&env);
+		environ_free(&env);
 
-	while (!RB_EMPTY(jobs)) {
-		job = RB_ROOT(jobs);
-		RB_REMOVE(jobs, jobs, job);
-		job_free(job);
-	}
-}
+		if (dup2(out[1], STDOUT_FILENO) == -1)
+			fatal("dup2 failed");
+		if (out[1] != STDOUT_FILENO)
+			close(out[1]);
+		close(out[0]);
 
-/* Find a job and return it. */
-struct job *
-job_get(struct jobs *jobs, const char *cmd)
-{
-	struct job	job;
+		nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
+		if (nullfd < 0)
+			fatal("open failed");
+		if (dup2(nullfd, STDIN_FILENO) == -1)
+			fatal("dup2 failed");
+		if (dup2(nullfd, STDERR_FILENO) == -1)
+			fatal("dup2 failed");
+		if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
+			close(nullfd);
 
-	job.cmd = __UNCONST(cmd);
-	return (RB_FIND(jobs, jobs, &job));
-}
+		closefrom(STDERR_FILENO + 1);
 
-/* Add a job. */
-struct job *
-job_add(struct jobs *jobs, int flags, struct client *c, const char *cmd,
-    void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
-{
-	struct job	*job;
+		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
+		fatal("execl failed");
+	}
+
+	/* parent */
+	environ_free(&env);
+	close(out[1]);
 
 	job = xmalloc(sizeof *job);
 	job->cmd = xstrdup(cmd);
-	job->pid = -1;
+	job->pid = pid;
 	job->status = 0;
 
-	job->client = c;
-
-	job->fd = -1;
-	job->event = NULL;
+	LIST_INSERT_HEAD(&all_jobs, job, lentry);
 
 	job->callbackfn = callbackfn;
 	job->freefn = freefn;
 	job->data = data;
 
-	job->flags = flags;
+	job->fd = out[0];
+	setblocking(job->fd, 0);
 
-	if (jobs != NULL)
-		RB_INSERT(jobs, jobs, job);
-	SLIST_INSERT_HEAD(&all_jobs, job, lentry);
+	job->event = bufferevent_new(job->fd, NULL, NULL, job_callback, job);
+	bufferevent_enable(job->event, EV_READ);
 
+	log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
 	return (job);
 }
 
-/* Remove job from tree and free. */
-void
-job_remove(struct jobs *jobs, struct job *job)
-{
-	if (jobs != NULL)
-		RB_REMOVE(jobs, jobs, job);
-	job_free(job);
-}
-
 /* Kill and free an individual job. */
 void
 job_free(struct job *job)
 {
-	job_kill(job);
+	log_debug("free job %p: %s", job, job->cmd);
 
-	SLIST_REMOVE(&all_jobs, job, job, lentry);
+	LIST_REMOVE(job, lentry);
 	xfree(job->cmd);
 
 	if (job->freefn != NULL && job->data != NULL)
 		job->freefn(job->data);
 
+	if (job->pid != -1)
+		kill(job->pid, SIGTERM);
 	if (job->fd != -1)
 		close(job->fd);
 	if (job->event != NULL)
@@ -132,65 +131,6 @@
 	xfree(job);
 }
 
-/* Start a job running, if it isn't already. */
-int
-job_run(struct job *job)
-{
-	int	nullfd, out[2], mode;
-
-	if (job->fd != -1 || job->pid != -1)
-		return (0);
-
-	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
-		return (-1);
-
-	switch (job->pid = fork()) {
-	case -1:
-		return (-1);
-	case 0:		/* child */
-		clear_signals(1);
-
-		environ_push(&global_environ);
-
-		if (dup2(out[1], STDOUT_FILENO) == -1)
-			fatal("dup2 failed");
-		if (out[1] != STDOUT_FILENO)
-			close(out[1]);
-		close(out[0]);
-
-		nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
-		if (nullfd < 0)
-			fatal("open failed");
-		if (dup2(nullfd, STDIN_FILENO) == -1)
-			fatal("dup2 failed");
-		if (dup2(nullfd, STDERR_FILENO) == -1)
-			fatal("dup2 failed");
-		if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
-			close(nullfd);
-
-		closefrom(STDERR_FILENO + 1);
-
-		execl(_PATH_BSHELL, "sh", "-c", job->cmd, (char *) NULL);
-		fatal("execl failed");
-	default:	/* parent */
-		close(out[1]);
-
-		job->fd = out[0];
-		if ((mode = fcntl(job->fd, F_GETFL)) == -1)
-			fatal("fcntl failed");
-		if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
-			fatal("fcntl failed");
-
-		if (job->event != NULL)
-			bufferevent_free(job->event);
-		job->event =
-		    bufferevent_new(job->fd, NULL, NULL, job_callback, job);
-		bufferevent_enable(job->event, EV_READ);
-
-		return (0);
-	}
-}
-
 /* Job buffer error callback. */
 /* ARGSUSED */
 void
@@ -198,15 +138,16 @@
 {
 	struct job	*job = data;
 
-	bufferevent_disable(job->event, EV_READ);
-	close(job->fd);
-	job->fd = -1;
+	log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
 
 	if (job->pid == -1) {
 		if (job->callbackfn != NULL)
 			job->callbackfn(job);
-		if ((!job->flags & JOB_PERSIST))
-			job_free(job);
+		job_free(job);
+	} else {
+		bufferevent_disable(job->event, EV_READ);
+		close(job->fd);
+		job->fd = -1;
 	}
 }
 
@@ -214,23 +155,14 @@
 void
 job_died(struct job *job, int status)
 {
+	log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid);
+
 	job->status = status;
-	job->pid = -1;
 
 	if (job->fd == -1) {
 		if (job->callbackfn != NULL)
 			job->callbackfn(job);
-		if ((!job->flags & JOB_PERSIST))
-			job_free(job);
-	}
-}
-
-/* Kill a job. */
-void
-job_kill(struct job *job)
-{
-	if (job->pid == -1)
-		return;
-	kill(job->pid, SIGTERM);
-	job->pid = -1;
+		job_free(job);
+	} else
+		job->pid = -1;
 }
Index: src/external/bsd/tmux/dist/options.c
diff -u src/external/bsd/tmux/dist/options.c:1.2 src/external/bsd/tmux/dist/options.c:1.3
--- src/external/bsd/tmux/dist/options.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/options.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: options.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: options.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <n...@users.sourceforge.net>
Index: src/external/bsd/tmux/dist/screen-write.c
diff -u src/external/bsd/tmux/dist/screen-write.c:1.2 src/external/bsd/tmux/dist/screen-write.c:1.3
--- src/external/bsd/tmux/dist/screen-write.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/screen-write.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: screen-write.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: screen-write.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -830,16 +830,35 @@
 		s->mode &= ~MODE_INSERT;
 }
 
-/* Set mouse mode.  */
+/* Set UTF-8 mouse mode.  */
 void
-screen_write_mousemode(struct screen_write_ctx *ctx, int state)
+screen_write_utf8mousemode(struct screen_write_ctx *ctx, int state)
 {
 	struct screen	*s = ctx->s;
 
 	if (state)
-		s->mode |= MODE_MOUSE;
+		s->mode |= MODE_MOUSE_UTF8;
 	else
-		s->mode &= ~MODE_MOUSE;
+		s->mode &= ~MODE_MOUSE_UTF8;
+}
+
+/* Set mouse mode off. */
+void
+screen_write_mousemode_off(struct screen_write_ctx *ctx)
+{
+	struct screen	*s = ctx->s;
+
+	s->mode &= ~ALL_MOUSE_MODES;
+}
+
+/* Set mouse mode on. */
+void
+screen_write_mousemode_on(struct screen_write_ctx *ctx, int mode)
+{
+	struct screen	*s = ctx->s;
+
+	s->mode &= ~ALL_MOUSE_MODES;
+	s->mode |= mode;
 }
 
 /* Line feed. */
@@ -913,9 +932,14 @@
 	sx = screen_size_x(s);
 	sy = screen_size_y(s);
 
-	if (s->cx <= sx - 1)
-		grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
-	grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+	/* Scroll into history if it is enabled and clearing entire screen. */
+	if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
+		grid_view_clear_history(s->grid);
+	else {
+		if (s->cx <= sx - 1)
+			grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+		grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
+	}
 
 	tty_write(tty_cmd_clearendofscreen, &ttyctx);
 }
@@ -951,7 +975,13 @@
 
 	screen_write_initctx(ctx, &ttyctx, 0);
 
-	grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+	/* Scroll into history if it is enabled. */
+	if (s->grid->flags & GRID_HISTORY)
+		grid_view_clear_history(s->grid);
+	else {
+		grid_view_clear(
+		    s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
+	}
 
 	tty_write(tty_cmd_clearscreen, &ttyctx);
 }
@@ -983,8 +1013,10 @@
 	 * If this is a wide character and there is no room on the screen, for
 	 * the entire character, don't print it.
 	 */
-	if (width > 1 && (width > screen_size_x(s) ||
-	    (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
+	if (!(s->mode & MODE_WRAP)
+	    && (width > 1 && (width > screen_size_x(s) ||
+		(s->cx != screen_size_x(s)
+		 && s->cx > screen_size_x(s) - width))))
 		return;
 
 	/*
@@ -1016,7 +1048,7 @@
 	}
 
 	/* Sanity checks. */
-	if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - 1)
+	if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width)
 	    || s->cy > screen_size_y(s) - 1)
 		return;
 
@@ -1162,3 +1194,27 @@
 		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
 	}
 }
+
+void
+screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+	struct tty_ctx	ttyctx;
+
+	screen_write_initctx(ctx, &ttyctx, 0);
+	ttyctx.ptr = str;
+	ttyctx.num = len;
+
+	tty_write(tty_cmd_setselection, &ttyctx);
+}
+
+void
+screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+	struct tty_ctx		 ttyctx;
+
+	screen_write_initctx(ctx, &ttyctx, 0);
+	ttyctx.ptr = str;
+	ttyctx.num = len;
+
+	tty_write(tty_cmd_rawstring, &ttyctx);
+}
Index: src/external/bsd/tmux/dist/screen.c
diff -u src/external/bsd/tmux/dist/screen.c:1.2 src/external/bsd/tmux/dist/screen.c:1.3
--- src/external/bsd/tmux/dist/screen.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/screen.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: screen.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: screen.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -41,6 +41,8 @@
 	else
 		s->title = xstrdup("");
 
+	s->cstyle = 0;
+	s->ccolour = xstrdup("");
 	s->tabs = NULL;
 
 	screen_reinit(s);
@@ -72,6 +74,7 @@
 	if (s->tabs != NULL)
 		xfree(s->tabs);
 	xfree(s->title);
+	xfree(s->ccolour);
 	grid_destroy(s->grid);
 }
 
@@ -90,6 +93,22 @@
 		bit_set(s->tabs, i);
 }
 
+/* Set screen cursor style. */
+void
+screen_set_cursor_style(struct screen *s, u_int style)
+{
+	if (style <= 4)
+		s->cstyle = style;
+}
+
+/* Set screen cursor colour. */
+void
+screen_set_cursor_colour(struct screen *s, const char *colour_string)
+{
+	xfree(s->ccolour);
+	s->ccolour = xstrdup(colour_string);
+}
+
 /* Set screen title. */
 void
 screen_set_title(struct screen *s, const char *title)
Index: src/external/bsd/tmux/dist/server-fn.c
diff -u src/external/bsd/tmux/dist/server-fn.c:1.2 src/external/bsd/tmux/dist/server-fn.c:1.3
--- src/external/bsd/tmux/dist/server-fn.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/server-fn.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: server-fn.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: server-fn.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -30,14 +30,20 @@
 void
 server_fill_environ(struct session *s, struct environ *env)
 {
-	char	tmuxvar[MAXPATHLEN], *term;
-
-	xsnprintf(tmuxvar, sizeof tmuxvar,
-	    "%s,%ld,%u", socket_path, (long) getpid(), s->idx);
-	environ_set(env, "TMUX", tmuxvar);
-
-	term = options_get_string(&s->options, "default-terminal");
-	environ_set(env, "TERM", term);
+	char	var[MAXPATHLEN], *term;
+	u_int	idx;
+	long	pid;
+
+	if (s != NULL) {
+		term = options_get_string(&s->options, "default-terminal");
+		environ_set(env, "TERM", term);
+
+		idx = s->idx;
+	} else
+		idx = -1;
+	pid = getpid();
+	xsnprintf(var, sizeof var, "%s,%ld,%d", socket_path, pid, idx);
+	environ_set(env, "TMUX", var);
 }
 
 void
@@ -396,6 +402,7 @@
 		} else {
 			c->last_session = NULL;
 			c->session = s_new;
+			session_update_activity(s_new);
 			server_redraw_client(c);
 		}
 	}
Index: src/external/bsd/tmux/dist/session.c
diff -u src/external/bsd/tmux/dist/session.c:1.2 src/external/bsd/tmux/dist/session.c:1.3
--- src/external/bsd/tmux/dist/session.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/session.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: session.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: session.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -96,7 +96,7 @@
 
 	if (gettimeofday(&s->creation_time, NULL) != 0)
 		fatal("gettimeofday failed");
-	memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
+	session_update_activity(s);
 
 	s->cwd = xstrdup(cwd);
 
@@ -104,8 +104,6 @@
 	TAILQ_INIT(&s->lastw);
 	RB_INIT(&s->windows);
 
-	paste_init_stack(&s->buffers);
-
 	options_init(&s->options, &global_s_options);
 	environ_init(&s->environ);
 	if (env != NULL)
@@ -154,7 +152,6 @@
 	session_group_remove(s);
 	environ_free(&s->environ);
 	options_free(&s->options);
-	paste_free_stack(&s->buffers);
 
 	while (!TAILQ_EMPTY(&s->lastw))
 		winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
@@ -166,6 +163,21 @@
 	RB_INSERT(sessions, &dead_sessions, s);
 }
 
+/* Check a session name is valid: not empty and no colons. */
+int
+session_check_name(const char *name)
+{
+	return (*name != '\0' && strchr(name, ':') == NULL);
+}
+
+/* Update session active time. */
+void
+session_update_activity(struct session *s)
+{
+	if (gettimeofday(&s->activity_time, NULL) != 0)
+		fatal("gettimeofday");
+}
+
 /* Find the next usable session. */
 struct session *
 session_next_session(struct session *s)
@@ -175,12 +187,9 @@
 	if (RB_EMPTY(&sessions) || !session_alive(s))
 		return (NULL);
 
-	s2 = s;
-	do {
-		s2 = RB_NEXT(sessions, &sessions, s2);
-		if (s2 == NULL)
-			s2 = RB_MIN(sessions, &sessions);
-	} while (s2 != s);
+	s2 = RB_NEXT(sessions, &sessions, s);
+	if (s2 == NULL)
+		s2 = RB_MIN(sessions, &sessions);
 	if (s2 == s)
 		return (NULL);
 	return (s2);
@@ -195,12 +204,9 @@
 	if (RB_EMPTY(&sessions) || !session_alive(s))
 		return (NULL);
 
-	s2 = s;
-	do {
-		s2 = RB_PREV(sessions, &sessions, s2);
-		if (s2 == NULL)
-			s2 = RB_MAX(sessions, &sessions);
-	} while (s2 != s);
+	s2 = RB_PREV(sessions, &sessions, s);
+	if (s2 == NULL)
+		s2 = RB_MAX(sessions, &sessions);
 	if (s2 == s)
 		return (NULL);
 	return (s2);
@@ -212,10 +218,16 @@
     const char *name, const char *cmd, const char *cwd, int idx, char **cause)
 {
 	struct window	*w;
+	struct winlink	*wl;
 	struct environ	 env;
 	const char	*shell;
 	u_int		 hlimit;
 
+	if ((wl = winlink_add(&s->windows, idx)) == NULL) {
+		xasprintf(cause, "index in use: %d", idx);
+		return (NULL);
+	}
+
 	environ_init(&env);
 	environ_copy(&global_environ, &env);
 	environ_copy(&s->environ, &env);
@@ -229,15 +241,18 @@
 	w = window_create(
 	    name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy, hlimit, cause);
 	if (w == NULL) {
+		winlink_remove(&s->windows, wl);
 		environ_free(&env);
 		return (NULL);
 	}
+	winlink_set_window(wl, w);
 	environ_free(&env);
 
 	if (options_get_number(&s->options, "set-remain-on-exit"))
 		options_set_number(&w->options, "remain-on-exit", 1);
 
-	return (session_attach(s, w, idx, cause));
+	session_group_synchronize_from(s);
+	return (wl);
 }
 
 /* Attach a window to a session. */
@@ -246,8 +261,12 @@
 {
 	struct winlink	*wl;
 
-	if ((wl = winlink_add(&s->windows, w, idx)) == NULL)
+	if ((wl = winlink_add(&s->windows, idx)) == NULL) {
 		xasprintf(cause, "index in use: %d", idx);
+		return (NULL);
+	}
+	winlink_set_window(wl, w);
+
 	session_group_synchronize_from(s);
 	return (wl);
 }
@@ -526,7 +545,8 @@
 
 	/* Link all the windows from the target. */
 	RB_FOREACH(wl, winlinks, ww) {
-		wl2 = winlink_add(&s->windows, wl->window, wl->idx);
+		wl2 = winlink_add(&s->windows, wl->idx);
+		winlink_set_window(wl2, wl->window);
 		wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
 	}
 
Index: src/external/bsd/tmux/dist/tty-acs.c
diff -u src/external/bsd/tmux/dist/tty-acs.c:1.2 src/external/bsd/tmux/dist/tty-acs.c:1.3
--- src/external/bsd/tmux/dist/tty-acs.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-acs.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-acs.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-acs.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2010 Nicholas Marriott <n...@users.sourceforge.net>
Index: src/external/bsd/tmux/dist/tty-keys.c
diff -u src/external/bsd/tmux/dist/tty-keys.c:1.2 src/external/bsd/tmux/dist/tty-keys.c:1.3
--- src/external/bsd/tmux/dist/tty-keys.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-keys.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-keys.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-keys.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -38,7 +38,7 @@
 		    struct tty_key *, const char *, size_t, size_t *);
 struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
 void		tty_keys_callback(int, short, void *);
-int		tty_keys_mouse(
+int		tty_keys_mouse(struct tty *,
 		    const char *, size_t, size_t *, struct mouse_event *);
 
 struct tty_key_ent {
@@ -54,7 +54,7 @@
  * Default key tables. Those flagged with TTYKEY_RAW are inserted directly,
  * otherwise they are looked up in terminfo(5).
  */
-struct tty_key_ent tty_keys[] = {
+const struct tty_key_ent tty_keys[] = {
 	/*
 	 * Numeric keypad. Just use the vt100 escape sequences here and always
 	 * put the terminal into keypad_xmit mode. Translation of numbers
@@ -343,9 +343,9 @@
 void
 tty_keys_init(struct tty *tty)
 {
-	struct tty_key_ent	*tke;
-	u_int		 	 i;
-	const char		*s;
+	const struct tty_key_ent	*tke;
+	u_int		 		 i;
+	const char			*s;
 
 	tty->key_tree = NULL;
 	for (i = 0; i < nitems(tty_keys); i++) {
@@ -462,7 +462,7 @@
 	}
 
 	/* Is this a mouse key press? */
-	switch (tty_keys_mouse((const char *)buf, len, &size, &mouse)) {
+	switch (tty_keys_mouse(tty, buf, len, &size, &mouse)) {
 	case 0:		/* yes */
 		evbuffer_drain(tty->event->input, size);
 		key = KEYC_MOUSE;
@@ -584,44 +584,74 @@
  * (probably a mouse sequence but need more data).
  */
 int
-tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
+tty_keys_mouse(struct tty *tty,
+    const char *buf, size_t len, size_t *size, struct mouse_event *m)
 {
+	struct utf8_data	utf8data;
+	u_int			i, value;
+
 	/*
-	 * Mouse sequences are \033[M followed by three characters indicating
-	 * buttons, X and Y, all based at 32 with 1,1 top-left.
+	 * Standard mouse sequences are \033[M followed by three characters
+	 * indicating buttons, X and Y, all based at 32 with 1,1 top-left.
+	 *
+	 * UTF-8 mouse sequences are similar but the three are expressed as
+	 * UTF-8 characters.
 	 */
 
 	*size = 0;
 
+	/* First three bytes are always \033[M. */
 	if (buf[0] != '\033')
 		return (-1);
 	if (len == 1)
 		return (1);
-
 	if (buf[1] != '[')
 		return (-1);
 	if (len == 2)
 		return (1);
-
 	if (buf[2] != 'M')
 		return (-1);
 	if (len == 3)
 		return (1);
 
-	if (len < 6)
-		return (1);
-	*size = 6;
+	/* Read the three inputs. */
+	*size = 3;
+	for (i = 0; i < 3; i++) {
+		if (len < *size)
+			return (1);
+
+		if (tty->mode & MODE_MOUSE_UTF8) {
+			if (utf8_open(&utf8data, buf[*size])) {
+				if (utf8data.size != 2)
+					return (-1);
+				(*size)++;
+				if (len < *size)
+					return (1);
+				utf8_append(&utf8data, buf[*size]);
+				value = utf8_combine(&utf8data);
+			} else
+				value = (unsigned char)buf[*size];
+			(*size)++;
+		} else {
+			value = (unsigned char)buf[*size];
+			(*size)++;
+		}
 
-	log_debug(
-	    "mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
+		if (i == 0)
+			m->b = value;
+		else if (i == 1)
+			m->x = value;
+		else
+			m->y = value;
+	}
+	log_debug("mouse input: %.*s", (int) *size, buf);
 
-	m->b = buf[3];
-	m->x = buf[4];
-	m->y = buf[5];
+	/* Check and return the mouse input. */
 	if (m->b < 32 || m->x < 33 || m->y < 33)
 		return (-1);
 	m->b -= 32;
 	m->x -= 33;
 	m->y -= 33;
+	log_debug("mouse position: x=%u y=%u b=%u", m->x, m->y, m->b);
 	return (0);
 }
Index: src/external/bsd/tmux/dist/tty-term.c
diff -u src/external/bsd/tmux/dist/tty-term.c:1.2 src/external/bsd/tmux/dist/tty-term.c:1.3
--- src/external/bsd/tmux/dist/tty-term.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/tty-term.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: tty-term.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: tty-term.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <n...@users.sourceforge.net>
@@ -18,10 +18,10 @@
 
 #include <sys/types.h>
 
-#ifdef HAVE_BROKEN_CURSES_H
-#include <ncurses.h>
-#else
+#ifdef HAVE_CURSES_H
 #include <curses.h>
+#else
+#include <ncurses.h>
 #endif
 #include <fnmatch.h>
 #include <stdlib.h>
@@ -33,19 +33,23 @@
 void	 tty_term_override(struct tty_term *, const char *);
 char	*tty_term_strip(const char *);
 
-struct tty_terms tty_terms = SLIST_HEAD_INITIALIZER(tty_terms);
+struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms);
 
-struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
+const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
 	{ TTYC_ACSC, TTYCODE_STRING, "acsc" },
 	{ TTYC_AX, TTYCODE_FLAG, "AX" },
 	{ TTYC_BEL, TTYCODE_STRING, "bel" },
 	{ TTYC_BLINK, TTYCODE_STRING, "blink" },
 	{ TTYC_BOLD, TTYCODE_STRING, "bold" },
+	{ TTYC_CC, TTYCODE_STRING, "Cc" },
 	{ TTYC_CIVIS, TTYCODE_STRING, "civis" },
 	{ TTYC_CLEAR, TTYCODE_STRING, "clear" },
 	{ TTYC_CNORM, TTYCODE_STRING, "cnorm" },
 	{ TTYC_COLORS, TTYCODE_NUMBER, "colors" },
+	{ TTYC_CR, TTYCODE_STRING, "Cr" },
+	{ TTYC_CS1, TTYCODE_STRING, "Cs" },
 	{ TTYC_CSR, TTYCODE_STRING, "csr" },
+	{ TTYC_CSR1, TTYCODE_STRING, "Csr" },
 	{ TTYC_CUB, TTYCODE_STRING, "cub" },
 	{ TTYC_CUB1, TTYCODE_STRING, "cub1" },
 	{ TTYC_CUD, TTYCODE_STRING, "cud" },
@@ -63,6 +67,7 @@
 	{ TTYC_EL, TTYCODE_STRING, "el" },
 	{ TTYC_EL1, TTYCODE_STRING, "el1" },
 	{ TTYC_ENACS, TTYCODE_STRING, "enacs" },
+	{ TTYC_FSL, TTYCODE_STRING, "fsl" },
 	{ TTYC_HOME, TTYCODE_STRING, "home" },
 	{ TTYC_HPA, TTYCODE_STRING, "hpa" },
 	{ TTYC_ICH, TTYCODE_STRING, "ich" },
@@ -165,6 +170,7 @@
 	{ TTYC_KUP5, TTYCODE_STRING, "kUP5" },
 	{ TTYC_KUP6, TTYCODE_STRING, "kUP6" },
 	{ TTYC_KUP7, TTYCODE_STRING, "kUP7" },
+	{ TTYC_MS, TTYCODE_STRING, "Ms" },
 	{ TTYC_OP, TTYCODE_STRING, "op" },
 	{ TTYC_REV, TTYCODE_STRING, "rev" },
 	{ TTYC_RI, TTYCODE_STRING, "ri" },
@@ -175,14 +181,17 @@
 	{ TTYC_SETAB, TTYCODE_STRING, "setab" },
 	{ TTYC_SETAF, TTYCODE_STRING, "setaf" },
 	{ TTYC_SGR0, TTYCODE_STRING, "sgr0" },
+	{ TTYC_SITM, TTYCODE_STRING, "sitm" },
 	{ TTYC_SMACS, TTYCODE_STRING, "smacs" },
 	{ TTYC_SMCUP, TTYCODE_STRING, "smcup" },
 	{ TTYC_SMIR, TTYCODE_STRING, "smir" },
 	{ TTYC_SMKX, TTYCODE_STRING, "smkx" },
 	{ TTYC_SMSO, TTYCODE_STRING, "smso" },
 	{ TTYC_SMUL, TTYCODE_STRING, "smul" },
+	{ TTYC_TSL, TTYCODE_STRING, "tsl" },
 	{ TTYC_VPA, TTYCODE_STRING, "vpa" },
 	{ TTYC_XENL, TTYCODE_FLAG, "xenl" },
+	{ TTYC_XT, TTYCODE_FLAG, "XT" },
 };
 
 char *
@@ -217,13 +226,14 @@
 void
 tty_term_override(struct tty_term *term, const char *overrides)
 {
-	struct tty_term_code_entry	*ent;
-	struct tty_code			*code;
-	char				*termnext, *termstr, *entnext, *entstr;
-	char				*s, *ptr, *val;
-	const char			*errstr;
-	u_int				 i;
-	int				 n, removeflag;
+	const struct tty_term_code_entry	*ent;
+	struct tty_code				*code;
+	char					*termnext, *termstr;
+	char					*entnext, *entstr;
+	char					*s, *ptr, *val;
+	const char				*errstr;
+	u_int					 i;
+	int					 n, removeflag;
 
 	s = xstrdup(overrides);
 
@@ -253,7 +263,7 @@
 				entstr[strlen(entstr) - 1] = '\0';
 				removeflag = 1;
 			} else
-				continue;
+				val = xstrdup("");
 
 			for (i = 0; i < NTTYCODE; i++) {
 				ent = &tty_term_codes[i];
@@ -299,15 +309,15 @@
 struct tty_term *
 tty_term_find(char *name, int fd, const char *overrides, char **cause)
 {
-	struct tty_term			*term;
-	struct tty_term_code_entry	*ent;
-	struct tty_code			*code;
-	u_int				 i;
-	int		 		 n, error;
-	char				*s;
-	const char                      *acs;
+	struct tty_term				*term;
+	const struct tty_term_code_entry	*ent;
+	struct tty_code				*code;
+	u_int					 i;
+	int		 			 n, error;
+	char					*s;
+	const char				*acs;
 
-	SLIST_FOREACH(term, &tty_terms, entry) {
+	LIST_FOREACH(term, &tty_terms, entry) {
 		if (strcmp(term->name, name) == 0) {
 			term->references++;
 			return (term);
@@ -320,7 +330,7 @@
 	term->references = 1;
 	term->flags = 0;
 	memset(term->codes, 0, sizeof term->codes);
-	SLIST_INSERT_HEAD(&tty_terms, term, entry);
+	LIST_INSERT_HEAD(&tty_terms, term, entry);
 
 	/* Set up curses terminal. */
 	if (setupterm(name, fd, &error) != OK) {
@@ -426,6 +436,18 @@
 	for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
 		term->acs[(u_char) acs[0]][0] = acs[1];
 
+	/* On terminals with xterm titles (XT), fill in tsl and fsl. */
+	if (tty_term_flag(term, TTYC_XT) &&
+	    !tty_term_has(term, TTYC_TSL) &&
+	    !tty_term_has(term, TTYC_FSL)) {
+		code = &term->codes[TTYC_TSL];
+		code->value.string = xstrdup("\033]0;");
+		code->type = TTYCODE_STRING;
+		code = &term->codes[TTYC_FSL];
+		code->value.string = xstrdup("\007");
+		code->type = TTYCODE_STRING;
+	}
+
 	return (term);
 
 error:
@@ -441,7 +463,7 @@
 	if (--term->references != 0)
 		return;
 
-	SLIST_REMOVE(&tty_terms, term, tty_term, entry);
+	LIST_REMOVE(term, entry);
 
 	for (i = 0; i < NTTYCODE; i++) {
 		if (term->codes[i].type == TTYCODE_STRING)
@@ -480,6 +502,18 @@
 	return (tparm(tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
 }
 
+const char *
+tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
+{
+	return (tparm((char *) tty_term_string(term, code), (long)a, 0, 0, 0, 0, 0, 0, 0, 0));
+}
+
+const char *
+tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b)
+{
+	return (tparm((char *) tty_term_string(term, code), (long)a, (long)b, 0, 0, 0, 0, 0, 0, 0));
+}
+
 int
 tty_term_number(struct tty_term *term, enum tty_code_code code)
 {
Index: src/external/bsd/tmux/dist/window.c
diff -u src/external/bsd/tmux/dist/window.c:1.2 src/external/bsd/tmux/dist/window.c:1.3
--- src/external/bsd/tmux/dist/window.c:1.2	Sat Mar 12 03:02:59 2011
+++ src/external/bsd/tmux/dist/window.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.2 2011/03/12 03:02:59 christos Exp $ */
+/* $Id: window.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <n...@users.sourceforge.net>
@@ -53,6 +53,10 @@
 /* Global window list. */
 struct windows windows;
 
+/* Global panes tree. */
+struct window_pane_tree all_window_panes;
+u_int	next_window_pane;
+
 void	window_pane_read_callback(struct bufferevent *, void *);
 void	window_pane_error_callback(struct bufferevent *, short, void *);
 
@@ -64,6 +68,14 @@
 	return (wl1->idx - wl2->idx);
 }
 
+RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
+
+int
+window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2)
+{
+	return (wp1->id - wp2->id);
+}
+
 struct winlink *
 winlink_find_by_window(struct winlinks *wwl, struct window *w)
 {
@@ -120,7 +132,7 @@
 }
 
 struct winlink *
-winlink_add(struct winlinks *wwl, struct window *w, int idx)
+winlink_add(struct winlinks *wwl, int idx)
 {
 	struct winlink	*wl;
 
@@ -132,15 +144,19 @@
 
 	wl = xcalloc(1, sizeof *wl);
 	wl->idx = idx;
-	wl->window = w;
 	RB_INSERT(winlinks, wwl, wl);
 
-	w->references++;
-
 	return (wl);
 }
 
 void
+winlink_set_window(struct winlink *wl, struct window *w)
+{
+	wl->window = w;
+	w->references++;
+}
+
+void
 winlink_remove(struct winlinks *wwl, struct winlink *wl)
 {
 	struct window	*w = wl->window;
@@ -150,11 +166,13 @@
 		xfree(wl->status_text);
 	xfree(wl);
 
-	if (w->references == 0)
-		fatal("bad reference count");
-	w->references--;
-	if (w->references == 0)
-		window_destroy(w);
+	if (w != NULL) {
+		if (w->references == 0)
+			fatal("bad reference count");
+		w->references--;
+		if (w->references == 0)
+			window_destroy(w);
+	}
 }
 
 struct winlink *
@@ -335,21 +353,65 @@
 	}
 }
 
-void
-window_set_active_at(struct window *w, u_int x, u_int y)
+struct window_pane *
+window_get_active_at(struct window *w, u_int x, u_int y)
 {
 	struct window_pane	*wp;
 
 	TAILQ_FOREACH(wp, &w->panes, entry) {
-		if (wp == w->active || !window_pane_visible(wp))
+		if (!window_pane_visible(wp))
 			continue;
-		if (x < wp->xoff || x >= wp->xoff + wp->sx)
+		if (x < wp->xoff || x > wp->xoff + wp->sx)
 			continue;
-		if (y < wp->yoff || y >= wp->yoff + wp->sy)
+		if (y < wp->yoff || y > wp->yoff + wp->sy)
 			continue;
-		window_set_active_pane(w, wp);
-		break;
+		return (wp);
 	}
+	return (NULL);
+}
+
+void
+window_set_active_at(struct window *w, u_int x, u_int y)
+{
+	struct window_pane	*wp;
+
+	wp = window_get_active_at(w, x, y);
+	if (wp != NULL && wp != w->active)
+		window_set_active_pane(w, wp);
+}
+
+struct window_pane *
+window_find_string(struct window *w, const char *s)
+{
+	u_int	x, y;
+
+	x = w->sx / 2;
+	y = w->sy / 2;
+
+	if (strcasecmp(s, "top") == 0)
+		y = 0;
+	else if (strcasecmp(s, "bottom") == 0)
+		y = w->sy - 1;
+	else if (strcasecmp(s, "left") == 0)
+		x = 0;
+	else if (strcasecmp(s, "right") == 0)
+		x = w->sx - 1;
+	else if (strcasecmp(s, "top-left") == 0) {
+		x = 0;
+		y = 0;
+	} else if (strcasecmp(s, "top-right") == 0) {
+		x = w->sx - 1;
+		y = 0;
+	} else if (strcasecmp(s, "bottom-left") == 0) {
+		x = 0;
+		y = w->sy - 1;
+	} else if (strcasecmp(s, "bottom-right") == 0) {
+		x = w->sx - 1;
+		y = w->sy - 1;
+	} else
+		return (NULL);
+
+	return (window_get_active_at(w, x, y));
 }
 
 struct window_pane *
@@ -460,6 +522,42 @@
 	}
 }
 
+/* Return list of printable window flag symbols. No flags is just a space. */
+char *
+window_printable_flags(struct session *s, struct winlink *wl)
+{
+	char	flags[BUFSIZ];
+	int	pos;
+
+	pos = 0;
+	if (wl->flags & WINLINK_ACTIVITY)
+		flags[pos++] = '#';
+	if (wl->flags & WINLINK_BELL)
+		flags[pos++] = '!';
+	if (wl->flags & WINLINK_CONTENT)
+		flags[pos++] = '+';
+	if (wl->flags & WINLINK_SILENCE)
+		flags[pos++] = '~';
+	if (wl == s->curw)
+		flags[pos++] = '*';
+	if (wl == TAILQ_FIRST(&s->lastw))
+		flags[pos++] = '-';
+	if (pos == 0)
+		flags[pos++] = ' ';
+	flags[pos] = '\0';
+	return (xstrdup(flags));
+}
+
+/* Find pane in global tree by id. */
+struct window_pane *
+window_pane_find_by_id(u_int id)
+{
+	struct window_pane	wp;
+
+	wp.id = id;
+	return (RB_FIND(window_pane_tree, &all_window_panes, &wp));
+}
+
 struct window_pane *
 window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
 {
@@ -468,6 +566,9 @@
 	wp = xcalloc(1, sizeof *wp);
 	wp->window = w;
 
+	wp->id = next_window_pane++;
+	RB_INSERT(window_pane_tree, &all_window_panes, wp);
+
 	wp->cmd = NULL;
 	wp->shell = NULL;
 	wp->cwd = NULL;
@@ -520,6 +621,8 @@
 		bufferevent_free(wp->pipe_event);
 	}
 
+	RB_REMOVE(window_pane_tree, &all_window_panes, wp);
+
 	if (wp->cwd != NULL)
 		xfree(wp->cwd);
 	if (wp->shell != NULL)
@@ -534,8 +637,7 @@
     const char *cwd, struct environ *env, struct termios *tio, char **cause)
 {
 	struct winsize	 ws;
-	int		 mode;
-	char		*argv0;
+	char		*argv0, paneid[16];
 	const char	*ptr;
 	struct termios	 tio2;
 
@@ -582,6 +684,8 @@
 
 		closefrom(STDERR_FILENO + 1);
 
+		xsnprintf(paneid, sizeof paneid, "%%%u", wp->id);
+		environ_set(env, "TMUX_PANE", paneid);
 		environ_push(env);
 
 		clear_signals(1);
@@ -608,10 +712,8 @@
 		fatal("execl failed");
 	}
 
-	if ((mode = fcntl(wp->fd, F_GETFL)) == -1)
-		fatal("fcntl failed");
-	if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1)
-		fatal("fcntl failed");
+	setblocking(wp->fd, 0);
+
 	wp->event = bufferevent_new(wp->fd,
 	    window_pane_read_callback, NULL, window_pane_error_callback, wp);
 	bufferevent_enable(wp->event, EV_READ|EV_WRITE);
@@ -832,7 +934,8 @@
 	m->y -= wp->yoff;
 
 	if (wp->mode != NULL) {
-		if (wp->mode->mouse != NULL)
+		if (wp->mode->mouse != NULL &&
+		    options_get_number(&wp->window->options, "mode-mouse"))
 			wp->mode->mouse(wp, sess, m);
 	} else if (wp->fd != -1)
 		input_mouse(wp, m);

Index: src/external/bsd/tmux/dist/compat/imsg-buffer.c
diff -u src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.2 src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.3
--- src/external/bsd/tmux/dist/compat/imsg-buffer.c:1.2	Mon May 30 16:20:58 2011
+++ src/external/bsd/tmux/dist/compat/imsg-buffer.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: imsg-buffer.c,v 1.2 2011/05/30 16:20:58 joerg Exp $ */
+/* $Id: imsg-buffer.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 /*	$OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $	*/
 
 /*
Index: src/external/bsd/tmux/dist/compat/imsg.c
diff -u src/external/bsd/tmux/dist/compat/imsg.c:1.2 src/external/bsd/tmux/dist/compat/imsg.c:1.3
--- src/external/bsd/tmux/dist/compat/imsg.c:1.2	Mon May 30 16:20:58 2011
+++ src/external/bsd/tmux/dist/compat/imsg.c	Wed Aug 17 18:48:36 2011
@@ -1,4 +1,4 @@
-/* $Id: imsg.c,v 1.2 2011/05/30 16:20:58 joerg Exp $ */
+/* $Id: imsg.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
 /*	$OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $	*/
 
 /*

Reply via email to