summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2011-05-20 19:03:58 +0000
committerNicholas Marriott <nicm@openbsd.org>2011-05-20 19:03:58 +0000
commit944b5e6fa04e014501f465e3898315c84d10bd9e (patch)
tree84bf7b9489fc4105d7c5a4c59df7058c867a19fe
parent96e7f33da3078facc504c6c66d42956bc44b2e54 (diff)
Support xterm(1) cursor colour change sequences through terminfo(5) Cc
(set) and Cr (reset) extensions. Originally by Sean Estabrooks, tweaked by me and Ailin Nemui.
-rw-r--r--input.c36
-rw-r--r--options-table.c5
-rw-r--r--screen.c10
-rw-r--r--server-client.c2
-rw-r--r--tmux.19
-rw-r--r--tmux.h12
-rw-r--r--tty-term.c8
-rw-r--r--tty.c34
8 files changed, 101 insertions, 15 deletions
diff --git a/input.c b/input.c
index 3da950d5..86d34b74 100644
--- a/input.c
+++ b/input.c
@@ -1445,17 +1445,39 @@ 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);
+ 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, 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. */
diff --git a/options-table.c b/options-table.c
index 8a611460..c84c56a1 100644
--- a/options-table.c
+++ b/options-table.c
@@ -366,13 +366,14 @@ const struct options_table_entry session_options_table[] = {
{ .name = "terminal-overrides",
.type = OPTIONS_TABLE_STRING,
.default_str = "*88col*:colors=88,*256col*:colors=256"
- ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
+ ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
+ ":Cc=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
},
{ .name = "update-environment",
.type = OPTIONS_TABLE_STRING,
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
- "SSH_CONNECTION WINDOWID XAUTHORITY"
+ "SSH_CONNECTION WINDOWID XAUTHORITY"
},
diff --git a/screen.c b/screen.c
index abfbe100..5e3be88c 100644
--- a/screen.c
+++ b/screen.c
@@ -40,6 +40,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);
@@ -71,6 +72,7 @@ screen_free(struct screen *s)
if (s->tabs != NULL)
xfree(s->tabs);
xfree(s->title);
+ xfree(s->ccolour);
grid_destroy(s->grid);
}
@@ -89,6 +91,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 8b2ea00f..f4dd1fb2 100644
--- a/server-client.c
+++ b/server-client.c
@@ -521,7 +521,7 @@ server_client_reset_state(struct client *c)
mode &= ~MODE_MOUSE_UTF8;
/* Set the terminal mode and reset attributes. */
- tty_update_mode(&c->tty, mode);
+ tty_update_mode(&c->tty, mode, s);
tty_reset(&c->tty);
}
diff --git a/tmux.1 b/tmux.1
index c6a286a8..dbe54d52 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2832,6 +2832,15 @@ See the
option above and the
.Xr xterm 1
man page.
+.It Em Cc, Cr
+The first takes one string argument and is used to set the cursor colour;
+the second takes no arguments and restores the default cursor colour.
+If they present, a sequence such as this may be used to change the
+cursor colour from inside
+.Nm :
+.Bd -literal -offset indent
+$ printf '\e033]12;red\e033\e\e'
+.Ed
.El
.Sh FILES
.Bl -tag -width "/etc/tmux.confXXX" -compact
diff --git a/tmux.h b/tmux.h
index 3056ac94..0444b56d 100644
--- a/tmux.h
+++ b/tmux.h
@@ -183,10 +183,12 @@ enum tty_code_code {
TTYC_BEL, /* bell, bl */
TTYC_BLINK, /* enter_blink_mode, mb */
TTYC_BOLD, /* enter_bold_mode, md */
+ TTYC_CC, /* set colour cursor, Cc */
TTYC_CIVIS, /* cursor_invisible, vi */
TTYC_CLEAR, /* clear_screen, cl */
TTYC_CNORM, /* cursor_normal, ve */
TTYC_COLORS, /* max_colors, Co */
+ TTYC_CR, /* restore cursor colour, Cr */
TTYC_CSR, /* change_scroll_region, cs */
TTYC_CUB, /* parm_left_cursor, LE */
TTYC_CUB1, /* cursor_left, le */
@@ -714,6 +716,8 @@ 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 */
@@ -1010,6 +1014,7 @@ struct tty {
u_int cx;
u_int cy;
+ char *ccolour;
int mode;
@@ -1414,6 +1419,7 @@ void tty_cursor(struct tty *, u_int, u_int);
void tty_putcode(struct tty *, enum tty_code_code);
void tty_putcode1(struct tty *, enum tty_code_code, int);
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
+void tty_putcode_ptr1(struct tty *, enum tty_code_code, const void *);
void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *, const void *);
void tty_puts(struct tty *, const char *);
void tty_putc(struct tty *, u_char);
@@ -1423,7 +1429,8 @@ 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_mode(struct tty *, int);
+void tty_update_mode(struct tty *, int, struct screen *);
+void tty_force_cursor_colour(struct tty *, const char *);
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
int tty_open(struct tty *, const char *, char **);
void tty_close(struct tty *);
@@ -1459,6 +1466,8 @@ const char *tty_term_string(struct tty_term *, enum tty_code_code);
const char *tty_term_string1(struct tty_term *, enum tty_code_code, int);
const char *tty_term_string2(
struct tty_term *, enum tty_code_code, int, int);
+const char *tty_term_ptr1(
+ struct tty_term *, enum tty_code_code, const void *);
const char *tty_term_ptr2(
struct tty_term *, enum tty_code_code, const void *, const void *);
int tty_term_number(struct tty_term *, enum tty_code_code);
@@ -1841,6 +1850,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-term.c b/tty-term.c
index 7ad4628f..7083e2ab 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -38,10 +38,12 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ 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_CSR, TTYCODE_STRING, "csr" },
{ TTYC_CUB, TTYCODE_STRING, "cub" },
{ TTYC_CUB1, TTYCODE_STRING, "cub1" },
@@ -494,6 +496,12 @@ tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
}
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), a));
+}
+
+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), a, b));
diff --git a/tty.c b/tty.c
index 04503b60..5f3ada8e 100644
--- a/tty.c
+++ b/tty.c
@@ -69,6 +69,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;
@@ -210,6 +211,8 @@ tty_start_tty(struct tty *tty)
tty->mode = MODE_CURSOR;
tty->flags |= TTY_STARTED;
+
+ tty_force_cursor_colour(tty, "");
}
void
@@ -241,6 +244,7 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
+ tty_raw(tty, tty_term_string(tty->term, TTYC_CR));
tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM));
if (tty_term_has(tty->term, TTYC_KMOUS))
@@ -280,6 +284,7 @@ tty_free(struct tty *tty)
{
tty_close(tty);
+ xfree(tty->ccolour);
if (tty->path != NULL)
xfree(tty->path);
if (tty->termname != NULL)
@@ -315,6 +320,13 @@ tty_putcode2(struct tty *tty, enum tty_code_code code, int a, int b)
}
void
+tty_putcode_ptr1(struct tty *tty, enum tty_code_code code, const void *a)
+{
+ if (a != NULL)
+ tty_puts(tty, tty_term_ptr1(tty->term, code, a));
+}
+
+void
tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a, const void *b)
{
if (a != NULL && b != NULL)
@@ -389,10 +401,24 @@ tty_set_title(struct tty *tty, const char *title)
}
void
-tty_update_mode(struct tty *tty, int mode)
+tty_force_cursor_colour(struct tty *tty, const char *ccolour)
+{
+ if (*ccolour == '\0')
+ tty_putcode(tty, TTYC_CR);
+ else
+ tty_putcode_ptr1(tty, TTYC_CC, ccolour);
+ xfree(tty->ccolour);
+ tty->ccolour = xstrdup(ccolour);
+}
+
+void
+tty_update_mode(struct tty *tty, int mode, struct screen *s)
{
int changed;
+ if (strcmp(s->ccolour, tty->ccolour))
+ tty_force_cursor_colour(tty, s->ccolour);
+
if (tty->flags & TTY_NOCURSOR)
mode &= ~MODE_CURSOR;
@@ -486,7 +512,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_mode(tty, tty->mode & ~MODE_CURSOR);
+ tty_update_mode(tty, tty->mode & ~MODE_CURSOR, s);
sx = screen_size_x(s);
if (sx > s->grid->linedata[s->grid->hsize + py].cellsize)
@@ -526,7 +552,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_mode(tty, tty->mode);
+ tty_update_mode(tty, tty->mode, s);
return;
}
tty_reset(tty);
@@ -538,7 +564,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_mode(tty, tty->mode);
+ tty_update_mode(tty, tty->mode, s);
}
void