commit c0299601c22639c9ed1732ac9cfdc3b206fca316
Author: Sean Estabrooks <seanlkml@sympatico.ca>
Date:   Sun Mar 13 13:47:05 2011 -0700

    Handle xterm OSC cursor-colour escape sequences
    
    For example the sequence "\033]12;red\007" should set the
    cursor colour for the current window to red.
    
    The cursor colour can be reset to default with "\033]112\007",
    although this only seems to work when xterm is explicitly
    instructed to operate with a default cursor colour.
    
    These sequences are not enabled and will not be sent to the
    underlying terminal until they have been seen in use by any
    of the programs using tmux for output.  Also, the underlying
    terminal must be one of "xterm", "screen" or "rxvt".
    
    One use of this facility is to allow the Vim editor to change
    the cursor colour during insert mode.  This is done by adding
    a pair of terminfo values similar to:
    
    	SI=\E]12;red\007, EI=\E]112\007,

diff --git a/input.c b/input.c
index 6e36c77..b2d5eeb 100644
--- a/input.c
+++ b/input.c
@@ -1445,17 +1445,36 @@ input_enter_osc(struct input_ctx *ictx)
 void
 input_exit_osc(struct input_ctx *ictx)
 {
-	if (ictx->flags & INPUT_DISCARD)
-		return;
-	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+	int option = 0;
+	u_char *p = ictx->input_buf;
 
-	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, ictx->input_buf + 2);
-	server_status_window(ictx->wp->window);
+	log_debug("%s: \"%s\"", __func__, p);
+
+	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:
+	case 112:
+		screen_set_cursor_colour(ictx->ctx.s, p);
+		break;
+	default:
+		log_debug("%s: unknown '%u'", __func__, option);
+		break;
+	}
 }
 
 /* APC string started. */
diff --git a/screen.c b/screen.c
index a3261c0..d3aa957 100644
--- a/screen.c
+++ b/screen.c
@@ -41,6 +41,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
 	else
 		s->title = xstrdup("");
 
+	s->ccolour = xstrdup("");
 	s->tabs = NULL;
 
 	screen_reinit(s);
@@ -72,6 +73,7 @@ screen_free(struct screen *s)
 	if (s->tabs != NULL)
 		xfree(s->tabs);
 	xfree(s->title);
+	xfree(s->ccolour);
 	grid_destroy(s->grid);
 }
 
@@ -90,6 +92,14 @@ screen_reset_tabs(struct screen *s)
 		bit_set(s->tabs, i);
 }
 
+/* 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)
diff --git a/server-client.c b/server-client.c
index d38e312..f22b95c 100644
--- a/server-client.c
+++ b/server-client.c
@@ -472,6 +472,7 @@ server_client_reset_state(struct client *c)
 		mode &= ~MODE_MOUSE_UTF8;
 
 	/* Set the terminal mode and reset attributes. */
+	tty_update_cursor_colour(&c->tty, s->ccolour);
 	tty_update_mode(&c->tty, mode);
 	tty_reset(&c->tty);
 }
diff --git a/tmux.h b/tmux.h
index 49e2d97..7d57c68 100644
--- a/tmux.h
+++ b/tmux.h
@@ -700,6 +700,7 @@ struct screen {
 
 	u_int		 cx;		/* cursor x */
 	u_int		 cy;		/* cursor y */
+	char		*ccolour;	/* cursor colour string */
 
 	u_int		 rupper;	/* scroll region top */
 	u_int		 rlower;	/* scroll region bottom */
@@ -991,6 +992,7 @@ struct tty {
 
 	u_int		 cx;
 	u_int		 cy;
+	char *		 ccolour;
 
 	int		 mode;
 
@@ -1399,6 +1401,7 @@ int	tty_resize(struct tty *);
 void	tty_start_tty(struct tty *);
 void	tty_stop_tty(struct tty *);
 void	tty_set_title(struct tty *, const char *);
+void	tty_update_cursor_colour(struct tty *, const char *);
 void	tty_update_mode(struct tty *, int);
 void	tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
 int	tty_open(struct tty *, const char *, char **);
@@ -1811,6 +1814,7 @@ void	 screen_init(struct screen *, u_int, u_int, u_int);
 void	 screen_reinit(struct screen *);
 void	 screen_free(struct screen *);
 void	 screen_reset_tabs(struct screen *);
+void	 screen_set_cursor_colour(struct screen *, const char *);
 void	 screen_set_title(struct screen *, const char *);
 void	 screen_resize(struct screen *, u_int, u_int);
 void	 screen_set_selection(struct screen *,
diff --git a/tty.c b/tty.c
index 8f0103a..059489b 100644
--- a/tty.c
+++ b/tty.c
@@ -66,6 +66,7 @@ tty_init(struct tty *tty, int fd, char *term)
 	if ((path = ttyname(fd)) == NULL)
 		fatalx("ttyname failed");
 	tty->path = xstrdup(path);
+	tty->ccolour = xstrdup("");
 
 	tty->flags = 0;
 	tty->term_flags = 0;
@@ -277,6 +278,7 @@ tty_free(struct tty *tty)
 {
 	tty_close(tty);
 
+	xfree(tty->ccolour);
 	if (tty->path != NULL)
 		xfree(tty->path);
 	if (tty->termname != NULL)
@@ -380,6 +382,28 @@ tty_set_title(struct tty *tty, const char *title)
 }
 
 void
+tty_update_cursor_colour(struct tty *tty, const char *ccolour)
+{
+	if (!strcmp(ccolour, tty->ccolour))
+		return;
+
+	if (strstr(tty->termname, "xterm") == NULL &&
+	    strstr(tty->termname, "rxvt") == NULL &&
+	    strcmp(tty->termname, "screen") != 0)
+		return;
+
+	if (*ccolour == 0) {
+		tty_puts(tty, "\033]112\007");
+	} else {
+		tty_puts(tty, "\033]12;");
+		tty_puts(tty, ccolour);
+		tty_puts(tty, "\007");
+	}
+	xfree(tty->ccolour);
+	tty->ccolour = xstrdup(ccolour);
+}
+
+void
 tty_update_mode(struct tty *tty, int mode)
 {
 	int	changed;
@@ -477,6 +501,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy)
 	const struct grid_utf8	*gu;
 	u_int			 i, sx;
 
+	tty_update_cursor_colour(tty, s->ccolour);
 	tty_update_mode(tty, tty->mode & ~MODE_CURSOR);
 
 	sx = screen_size_x(s);
@@ -517,6 +542,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy)
 	}
 
 	if (sx >= tty->sx) {
+		tty_update_cursor_colour(tty, s->ccolour);
 		tty_update_mode(tty, tty->mode);
 		return;
 	}
@@ -529,6 +555,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy)
 		for (i = sx; i < screen_size_x(s); i++)
 			tty_putc(tty, ' ');
 	}
+	tty_update_cursor_colour(tty, s->ccolour);
 	tty_update_mode(tty, tty->mode);
 }
 
