From 1db1a6bb4ec66f82490f1bf5fdd40614ef7f0002 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 1 Nov 2021 09:34:49 +0000 Subject: [PATCH] Add a cursor-colour option, from Alexis Hildebrandt in GitHub issue 2959. --- usr.bin/tmux/input.c | 49 ++++++++++++++++++++++++++++++------ usr.bin/tmux/options-table.c | 10 +++++++- usr.bin/tmux/options.c | 11 ++++++-- usr.bin/tmux/screen.c | 11 ++++---- usr.bin/tmux/tmux.1 | 7 ++++-- usr.bin/tmux/tmux.h | 9 ++++--- usr.bin/tmux/tty.c | 45 +++++++++++++++++++++------------ 7 files changed, 104 insertions(+), 38 deletions(-) diff --git a/usr.bin/tmux/input.c b/usr.bin/tmux/input.c index 8e0e89d12cf..90f0bf7bc0a 100644 --- a/usr.bin/tmux/input.c +++ b/usr.bin/tmux/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.193 2021/10/05 12:46:02 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.194 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -137,10 +137,12 @@ static void input_reset_cell(struct input_ctx *); static void input_osc_4(struct input_ctx *, const char *); static void input_osc_10(struct input_ctx *, const char *); static void input_osc_11(struct input_ctx *, const char *); +static void input_osc_12(struct input_ctx *, const char *); static void input_osc_52(struct input_ctx *, const char *); static void input_osc_104(struct input_ctx *, const char *); static void input_osc_110(struct input_ctx *, const char *); static void input_osc_111(struct input_ctx *, const char *); +static void input_osc_112(struct input_ctx *, const char *); /* Transition entry/exit handlers. */ static void input_clear(struct input_ctx *); @@ -2310,8 +2312,7 @@ input_exit_osc(struct input_ctx *ictx) input_osc_11(ictx, p); break; case 12: - if (utf8_isvalid(p) && *p != '?') /* ? is colour request */ - screen_set_cursor_colour(sctx->s, p); + input_osc_12(ictx, p); break; case 52: input_osc_52(ictx, p); @@ -2326,8 +2327,7 @@ input_exit_osc(struct input_ctx *ictx) input_osc_111(ictx, p); break; case 112: - if (*p == '\0') /* no arguments allowed */ - screen_set_cursor_colour(sctx->s, ""); + input_osc_112(ictx, p); break; default: log_debug("%s: unknown '%u'", __func__, option); @@ -2489,7 +2489,9 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) u_char r, g, b; const char *end; - if (c == 8 || (~c & COLOUR_FLAG_RGB)) + if (c != -1) + c = colour_force_rgb(c); + if (c == -1) return; colour_split_rgb(c, &r, &g, &b); @@ -2564,7 +2566,7 @@ input_osc_10(struct input_ctx *ictx, const char *p) } } -/* Handle the OSC 110 sequence for resetting background colour. */ +/* Handle the OSC 110 sequence for resetting foreground colour. */ static void input_osc_110(struct input_ctx *ictx, const char *p) { @@ -2624,6 +2626,39 @@ input_osc_111(struct input_ctx *ictx, const char *p) } } +/* Handle the OSC 12 sequence for setting and querying cursor colour. */ +static void +input_osc_12(struct input_ctx *ictx, const char *p) +{ + struct window_pane *wp = ictx->wp; + int c; + + if (strcmp(p, "?") == 0) { + if (wp != NULL) { + c = ictx->ctx.s->ccolour; + if (c == -1) + c = ictx->ctx.s->default_ccolour; + input_osc_colour_reply(ictx, 12, c); + } + return; + } + + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 12: %s", p); + return; + } + screen_set_cursor_colour(ictx->ctx.s, c); +} + +/* Handle the OSC 112 sequence for resetting cursor colour. */ +static void +input_osc_112(struct input_ctx *ictx, const char *p) +{ + if (*p == '\0') /* no arguments allowed */ + screen_set_cursor_colour(ictx->ctx.s, -1); +} + + /* Handle the OSC 52 sequence for setting the clipboard. */ static void input_osc_52(struct input_ctx *ictx, const char *p) diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c index c435480f021..d0511e2f40e 100644 --- a/usr.bin/tmux/options-table.c +++ b/usr.bin/tmux/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.152 2021/10/14 13:19:01 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.153 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -188,6 +188,7 @@ const struct options_name_map options_other_names[] = { { "display-panes-color", "display-panes-colour" }, { "display-panes-active-color", "display-panes-active-colour" }, { "clock-mode-color", "clock-mode-colour" }, + { "cursor-color", "cursor-colour" }, { "pane-colors", "pane-colours" }, { NULL, NULL } }; @@ -235,6 +236,13 @@ const struct options_table_entry options_table[] = { "If empty, no command is run." }, + { .name = "cursor-colour", + .type = OPTIONS_TABLE_COLOUR, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, + .default_num = -1, + .text = "Colour of the cursor." + }, + { .name = "default-terminal", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, diff --git a/usr.bin/tmux/options.c b/usr.bin/tmux/options.c index 10bb1f3cb89..a4af7cdc76a 100644 --- a/usr.bin/tmux/options.c +++ b/usr.bin/tmux/options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options.c,v 1.65 2021/10/14 13:19:01 nicm Exp $ */ +/* $OpenBSD: options.c,v 1.66 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -1106,15 +1106,22 @@ options_push_changes(const char *name) struct session *s; struct window *w; struct window_pane *wp; + int c; if (strcmp(name, "automatic-rename") == 0) { RB_FOREACH(w, windows, &windows) { if (w->active == NULL) continue; - if (options_get_number(w->options, "automatic-rename")) + if (options_get_number(w->options, name)) w->active->flags |= PANE_CHANGED; } } + if (strcmp(name, "cursor-colour") == 0) { + RB_FOREACH(wp, window_pane_tree, &all_window_panes) { + c = options_get_number(wp->options, name); + wp->screen->default_ccolour = c; + } + } if (strcmp(name, "key-table") == 0) { TAILQ_FOREACH(loop, &clients, entry) server_client_set_key_table(loop, NULL); diff --git a/usr.bin/tmux/screen.c b/usr.bin/tmux/screen.c index 21d9d13b298..0ac7f6230a6 100644 --- a/usr.bin/tmux/screen.c +++ b/usr.bin/tmux/screen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen.c,v 1.76 2021/10/05 12:46:02 nicm Exp $ */ +/* $OpenBSD: screen.c,v 1.77 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -82,7 +82,8 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->path = NULL; s->cstyle = SCREEN_CURSOR_DEFAULT; - s->ccolour = xstrdup(""); + s->ccolour = -1; + s->default_ccolour = -1; s->tabs = NULL; s->sel = NULL; @@ -126,7 +127,6 @@ screen_free(struct screen *s) free(s->tabs); free(s->path); free(s->title); - free(s->ccolour); if (s->write_list != NULL) screen_write_free_list(s); @@ -190,10 +190,9 @@ screen_set_cursor_style(struct screen *s, u_int style) /* Set screen cursor colour. */ void -screen_set_cursor_colour(struct screen *s, const char *colour) +screen_set_cursor_colour(struct screen *s, int colour) { - free(s->ccolour); - s->ccolour = xstrdup(colour); + s->ccolour = colour; } /* Set screen title. */ diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index d0107c43a01..141461dd930 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.867 2021/10/25 21:21:16 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.868 2021/11/01 09:34:49 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: October 25 2021 $ +.Dd $Mdocdate: November 1 2021 $ .Dt TMUX 1 .Os .Sh NAME @@ -4416,6 +4416,9 @@ The alternate screen feature preserves the contents of the window when an interactive application starts and restores it on exit, so that any output visible before the application starts reappears unchanged after it exits. .Pp +.It Ic cursor-colour Ar colour +Set the colour of the cursor. +.Pp .It Ic pane-colours[] Ar colour The default colour palette. Each entry in the array defines the colour diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 9c663077c57..0c7ddd2fdd9 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1152 2021/10/28 18:54:33 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1153 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -779,7 +779,8 @@ struct screen { u_int cy; /* cursor y */ enum screen_cursor_style cstyle; /* cursor style */ - char *ccolour; /* cursor colour */ + int ccolour; /* cursor colour */ + int default_ccolour; u_int rupper; /* scroll region top */ u_int rlower; /* scroll region bottom */ @@ -1276,7 +1277,7 @@ struct tty { u_int cx; u_int cy; enum screen_cursor_style cstyle; - char *ccolour; + int ccolour; int oflag; u_int oox; @@ -2793,7 +2794,7 @@ void screen_reinit(struct screen *); void screen_free(struct screen *); void screen_reset_tabs(struct screen *); void screen_set_cursor_style(struct screen *, u_int); -void screen_set_cursor_colour(struct screen *, const char *); +void screen_set_cursor_colour(struct screen *, int); int screen_set_title(struct screen *, const char *); void screen_set_path(struct screen *, const char *); void screen_push_title(struct screen *); diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index 480f40204fb..12c0ff332e2 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.409 2021/10/28 18:57:06 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.410 2021/11/01 09:34:49 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -38,7 +38,7 @@ static int tty_client_ready(struct client *); static void tty_set_italics(struct tty *); static int tty_try_colour(struct tty *, int, const char *); -static void tty_force_cursor_colour(struct tty *, const char *); +static void tty_force_cursor_colour(struct tty *, int); static void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_cursor_pane_unless_wrap(struct tty *, @@ -105,7 +105,7 @@ tty_init(struct tty *tty, struct client *c) tty->client = c; tty->cstyle = SCREEN_CURSOR_DEFAULT; - tty->ccolour = xstrdup(""); + tty->ccolour = -1; if (tcgetattr(c->fd, &tty->tio) != 0) return (-1); @@ -341,8 +341,8 @@ tty_start_tty(struct tty *tty) tty->flags |= TTY_STARTED; tty_invalidate(tty); - if (*tty->ccolour != '\0') - tty_force_cursor_colour(tty, ""); + if (tty->ccolour != -1) + tty_force_cursor_colour(tty, -1); tty->mouse_drag_flag = 0; tty->mouse_drag_update = NULL; @@ -406,7 +406,7 @@ tty_stop_tty(struct tty *tty) } if (tty->mode & MODE_BRACKETPASTE) tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP)); - if (*tty->ccolour != '\0') + if (tty->ccolour != -1) tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); @@ -451,7 +451,6 @@ void tty_free(struct tty *tty) { tty_close(tty); - free(tty->ccolour); } void @@ -650,24 +649,38 @@ tty_set_title(struct tty *tty, const char *title) } static void -tty_force_cursor_colour(struct tty *tty, const char *ccolour) +tty_force_cursor_colour(struct tty *tty, int c) { - if (*ccolour == '\0') + u_char r, g, b; + char s[13] = ""; + + if (c != -1) + c = colour_force_rgb(c); + if (c == tty->ccolour) + return; + if (c == -1) tty_putcode(tty, TTYC_CR); - else - tty_putcode_ptr1(tty, TTYC_CS, ccolour); - free(tty->ccolour); - tty->ccolour = xstrdup(ccolour); + else { + colour_split_rgb(c, &r, &g, &b); + xsnprintf(s, sizeof s, "rgb:%02hhx/%02hhx/%02hhx", r, g, b); + tty_putcode_ptr1(tty, TTYC_CS, s); + } + tty->ccolour = c; } static void tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) { - enum screen_cursor_style cstyle; + enum screen_cursor_style cstyle; + int ccolour; /* Set cursor colour if changed. */ - if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) - tty_force_cursor_colour(tty, s->ccolour); + if (s != NULL) { + ccolour = s->ccolour; + if (s->ccolour == -1) + ccolour = s->default_ccolour; + tty_force_cursor_colour(tty, ccolour); + } /* If cursor is off, set as invisible. */ if (~mode & MODE_CURSOR) { -- 2.20.1