From 7eea3d7ab850bb8fbeeccbb4b0fe84b9274965af Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 11 Aug 2021 20:49:55 +0000 Subject: [PATCH] Break the colour palette into a struct rather than just a single array and use that to support the OSC palette-setting sequences in popups. Also add a pane-colours array option to specify the defaults. GitHub issue 2815. --- cmd-send-keys.c | 3 +- colour.c | 112 ++++++++++++++++++++++++++++++++ input.c | 165 +++++++++++++++++++++++------------------------- options-table.c | 9 +++ options.c | 21 +++++- popup.c | 19 ++++-- screen-redraw.c | 18 +++--- screen-write.c | 40 +++++++----- tmux.1 | 14 +++- tmux.h | 46 ++++++++------ tty.c | 74 ++++++++++------------ window.c | 70 ++++---------------- 12 files changed, 352 insertions(+), 239 deletions(-) diff --git a/cmd-send-keys.c b/cmd-send-keys.c index b362fab5..c51d413b 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -197,8 +197,9 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) } if (args_has(args, 'R')) { - window_pane_reset_palette(wp); + colour_palette_clear(&wp->palette); input_reset(wp->ictx, 1); + wp->flags |= (PANE_STYLECHANGED|PANE_REDRAW); } for (; np != 0; np--) { diff --git a/colour.c b/colour.c index 1d1729ca..7aa7620a 100644 --- a/colour.c +++ b/colour.c @@ -944,3 +944,115 @@ colour_byname(const char *name) } return (-1); } + +/* Initialize palette. */ +void +colour_palette_init(struct colour_palette *p) +{ + p->fg = 8; + p->bg = 8; + p->palette = NULL; + p->default_palette = NULL; +} + +/* Clear palette. */ +void +colour_palette_clear(struct colour_palette *p) +{ + p->fg = 8; + p->bg = 8; + if (p != NULL) { + free(p->palette); + p->palette = NULL; + } +} + +/* Free a palette. */ +void +colour_palette_free(struct colour_palette *p) +{ + if (p != NULL) { + free(p->palette); + p->palette = NULL; + free(p->default_palette); + p->default_palette = NULL; + } +} + +/* Get a colour from a palette. */ +int +colour_palette_get(struct colour_palette *p, int c) +{ + if (p == NULL) + return (-1); + + if (c >= 90 && c <= 97) + c = 8 + c - 90; + else if (c & COLOUR_FLAG_256) + c &= ~COLOUR_FLAG_256; + else if (c >= 8) + return (-1); + + if (p->palette != NULL && p->palette[c] != -1) + return (p->palette[c]); + if (p->default_palette != NULL && p->default_palette[c] != -1) + return (p->default_palette[c]); + return (-1); +} + +/* Set a colour in a palette. */ +int +colour_palette_set(struct colour_palette *p, int n, int c) +{ + u_int i; + + if (p == NULL || n > 255) + return (0); + + if (c == -1 && p->palette == NULL) + return (0); + + if (c != -1 && p->palette == NULL) { + if (p->palette == NULL) + p->palette = xcalloc(256, sizeof *p->palette); + for (i = 0; i < 256; i++) + p->palette[i] = -1; + } + p->palette[n] = c; + return (1); +} + +/* Build palette defaults from an option. */ +void +colour_palette_from_option(struct colour_palette *p, struct options *oo) +{ + struct options_entry *o; + struct options_array_item *a; + u_int i, n; + int c; + + if (p == NULL) + return; + + o = options_get(oo, "pane-colours"); + if ((a = options_array_first(o)) == NULL) { + if (p->default_palette != NULL) { + free(p->default_palette); + p->default_palette = NULL; + } + return; + } + if (p->default_palette == NULL) + p->default_palette = xcalloc(256, sizeof *p->default_palette); + for (i = 0; i < 256; i++) + p->default_palette[i] = -1; + while (a != NULL) { + n = options_array_item_index(a); + if (n < 256) { + c = options_array_item_value(a)->number; + p->default_palette[n] = c; + } + a = options_array_next(a); + } + +} diff --git a/input.c b/input.c index b599f27d..49ed68b7 100644 --- a/input.c +++ b/input.c @@ -77,6 +77,7 @@ struct input_ctx { struct window_pane *wp; struct bufferevent *event; struct screen_write_ctx ctx; + struct colour_palette *palette; struct input_cell cell; @@ -797,13 +798,15 @@ input_restore_state(struct input_ctx *ictx) /* Initialise input parser. */ struct input_ctx * -input_init(struct window_pane *wp, struct bufferevent *bev) +input_init(struct window_pane *wp, struct bufferevent *bev, + struct colour_palette *palette) { struct input_ctx *ictx; ictx = xcalloc(1, sizeof *ictx); ictx->wp = wp; ictx->event = bev; + ictx->palette = palette; ictx->input_space = INPUT_BUF_START; ictx->input_buf = xmalloc(INPUT_BUF_START); @@ -1252,7 +1255,6 @@ static int input_esc_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - struct window_pane *wp = ictx->wp; struct screen *s = sctx->s; struct input_table_entry *entry; @@ -1269,10 +1271,10 @@ input_esc_dispatch(struct input_ctx *ictx) switch (entry->type) { case INPUT_ESC_RIS: - if (wp != NULL) - window_pane_reset_palette(wp); + colour_palette_clear(ictx->palette); input_reset_cell(ictx); screen_write_reset(sctx); + screen_write_fullredraw(sctx); break; case INPUT_ESC_IND: screen_write_linefeed(sctx, 0, ictx->cell.cell.bg); @@ -1874,11 +1876,11 @@ input_csi_dispatch_winops(struct input_ctx *ictx) case 0: case 2: screen_pop_title(sctx->s); - if (wp != NULL) { - notify_pane("pane-title-changed", wp); - server_redraw_window_borders(wp->window); - server_status_window(wp->window); - } + if (wp == NULL) + break; + notify_pane("pane-title-changed", wp); + server_redraw_window_borders(wp->window); + server_status_window(wp->window); break; } break; @@ -2498,37 +2500,35 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) static void input_osc_4(struct input_ctx *ictx, const char *p) { - struct window_pane *wp = ictx->wp; - char *copy, *s, *next = NULL; - long idx; - int c; - - if (wp == NULL) - return; + char *copy, *s, *next = NULL; + long idx; + int c, bad = 0, redraw = 0; copy = s = xstrdup(p); while (s != NULL && *s != '\0') { idx = strtol(s, &next, 10); - if (*next++ != ';') - goto bad; - if (idx < 0 || idx >= 0x100) - goto bad; + if (*next++ != ';') { + bad = 1; + break; + } + if (idx < 0 || idx >= 256) { + bad = 1; + break; + } s = strsep(&next, ";"); if ((c = input_osc_parse_colour(s)) == -1) { s = next; continue; } - - window_pane_set_palette(wp, idx, c); + if (colour_palette_set(ictx->palette, idx, c)) + redraw = 1; s = next; } - - free(copy); - return; - -bad: - log_debug("bad OSC 4: %s", p); + if (bad) + log_debug("bad OSC 4: %s", p); + if (redraw) + screen_write_fullredraw(&ictx->ctx); free(copy); } @@ -2540,24 +2540,22 @@ input_osc_10(struct input_ctx *ictx, const char *p) struct grid_cell defaults; int c; - if (wp == NULL) - return; - if (strcmp(p, "?") == 0) { - tty_default_colours(&defaults, wp); - input_osc_colour_reply(ictx, 10, defaults.fg); + if (wp != NULL) { + tty_default_colours(&defaults, wp); + input_osc_colour_reply(ictx, 10, defaults.fg); + } return; } - if ((c = input_osc_parse_colour(p)) == -1) - goto bad; - wp->fg = c; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); - - return; - -bad: - log_debug("bad OSC 10: %s", p); + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 10: %s", p); + return; + } + ictx->palette->fg = c; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); } /* Handle the OSC 110 sequence for resetting background colour. */ @@ -2566,14 +2564,12 @@ input_osc_110(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; - if (wp == NULL) - return; - if (*p != '\0') return; - - wp->fg = 8; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); + ictx->palette->fg = 8; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); } /* Handle the OSC 11 sequence for setting and querying background colour. */ @@ -2584,24 +2580,22 @@ input_osc_11(struct input_ctx *ictx, const char *p) struct grid_cell defaults; int c; - if (wp == NULL) - return; - if (strcmp(p, "?") == 0) { - tty_default_colours(&defaults, wp); - input_osc_colour_reply(ictx, 11, defaults.bg); + if (wp != NULL) { + tty_default_colours(&defaults, wp); + input_osc_colour_reply(ictx, 11, defaults.bg); + } return; } - if ((c = input_osc_parse_colour(p)) == -1) - goto bad; - wp->bg = c; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); - - return; - -bad: - log_debug("bad OSC 11: %s", p); + if ((c = input_osc_parse_colour(p)) == -1) { + log_debug("bad OSC 11: %s", p); + return; + } + ictx->palette->bg = c; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); } /* Handle the OSC 111 sequence for resetting background colour. */ @@ -2610,14 +2604,12 @@ input_osc_111(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; - if (wp == NULL) - return; - if (*p != '\0') return; - - wp->bg = 8; - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); + ictx->palette->bg = 8; + if (wp != NULL) + wp->flags |= PANE_STYLECHANGED; + screen_write_fullredraw(&ictx->ctx); } /* Handle the OSC 52 sequence for setting the clipboard. */ @@ -2692,34 +2684,35 @@ input_osc_52(struct input_ctx *ictx, const char *p) static void input_osc_104(struct input_ctx *ictx, const char *p) { - struct window_pane *wp = ictx->wp; - char *copy, *s; - long idx; - - if (wp == NULL) - return; + char *copy, *s; + long idx; + int bad = 0, redraw = 0; if (*p == '\0') { - window_pane_reset_palette(wp); + colour_palette_clear(ictx->palette); + screen_write_fullredraw(&ictx->ctx); return; } copy = s = xstrdup(p); while (*s != '\0') { idx = strtol(s, &s, 10); - if (*s != '\0' && *s != ';') - goto bad; - if (idx < 0 || idx >= 0x100) - goto bad; - - window_pane_unset_palette(wp, idx); + if (*s != '\0' && *s != ';') { + bad = 1; + break; + } + if (idx < 0 || idx >= 256) { + bad = 1; + break; + } + if (colour_palette_set(ictx->palette, idx, -1)) + redraw = 1; if (*s == ';') s++; } - free(copy); - return; - -bad: - log_debug("bad OSC 104: %s", p); + if (bad) + log_debug("bad OSC 104: %s", p); + if (redraw) + screen_write_fullredraw(&ictx->ctx); free(copy); } diff --git a/options-table.c b/options-table.c index e0ae993a..2a6f262a 100644 --- a/options-table.c +++ b/options-table.c @@ -185,6 +185,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" }, + { "pane-colors", "pane-colours" }, { NULL, NULL } }; @@ -973,6 +974,14 @@ const struct options_table_entry options_table[] = { .text = "Style of the pane status lines." }, + { .name = "pane-colours", + .type = OPTIONS_TABLE_COLOUR, + .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, + .default_str = "", + .flags = OPTIONS_TABLE_IS_ARRAY, + .text = "The default colour palette for colours zero to 255." + }, + { .name = "remain-on-exit", .type = OPTIONS_TABLE_CHOICE, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, diff --git a/options.c b/options.c index 52f4f67e..23c83c07 100644 --- a/options.c +++ b/options.c @@ -402,7 +402,7 @@ options_array_clear(struct options_entry *o) return; RB_FOREACH_SAFE(a, options_array, &o->value.array, a1) - options_array_free(o, a); + options_array_free(o, a); } union options_value * @@ -425,6 +425,7 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, struct options_array_item *a; char *new; struct cmd_parse_result *pr; + long long number; if (!OPTIONS_IS_ARRAY(o)) { if (cause != NULL) @@ -479,6 +480,20 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, return (0); } + if (o->tableentry->type == OPTIONS_TABLE_COLOUR) { + if ((number = colour_fromstring(value)) == -1) { + xasprintf(cause, "bad colour: %s", value); + return (-1); + } + a = options_array_item(o, idx); + if (a == NULL) + a = options_array_new(o, idx); + else + options_value_free(o, &a->value); + a->value.number = number; + return (0); + } + if (cause != NULL) *cause = xstrdup("wrong array type"); return (-1); @@ -1113,6 +1128,10 @@ options_push_changes(const char *name) RB_FOREACH(wp, window_pane_tree, &all_window_panes) wp->flags |= PANE_STYLECHANGED; } + if (strcmp(name, "pane-colours") == 0) { + RB_FOREACH(wp, window_pane_tree, &all_window_panes) + colour_palette_from_option(&wp->palette, wp->options); + } if (strcmp(name, "pane-border-status") == 0) { RB_FOREACH(w, windows, &windows) layout_fix_panes(w, NULL); diff --git a/popup.c b/popup.c index dbddc66e..57ce80be 100644 --- a/popup.c +++ b/popup.c @@ -33,6 +33,7 @@ struct popup_data { int flags; struct screen s; + struct colour_palette palette; struct job *job; struct input_ctx *ictx; int status; @@ -101,6 +102,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) { struct popup_data *pd = ctx->arg; + ttyctx->palette = &pd->palette; ttyctx->redraw_cb = popup_redraw_cb; ttyctx->set_client_cb = popup_set_client_cb; ttyctx->arg = pd; @@ -136,6 +138,8 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) struct screen s; struct screen_write_ctx ctx; u_int i, px = pd->px, py = pd->py; + struct colour_palette *palette = &pd->palette; + struct grid_cell gc; screen_init(&s, pd->sx, pd->sy, 0); screen_write_start(&ctx, &s); @@ -150,11 +154,13 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) } screen_write_stop(&ctx); + memcpy(&gc, &grid_default_cell, sizeof gc); + gc.fg = pd->palette.fg; + gc.bg = pd->palette.bg; + c->overlay_check = NULL; - for (i = 0; i < pd->sy; i++){ - tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, - &grid_default_cell, NULL); - } + for (i = 0; i < pd->sy; i++) + tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette); c->overlay_check = popup_check_cb; } @@ -180,6 +186,7 @@ popup_free_cb(struct client *c) input_free(pd->ictx); screen_free(&pd->s); + colour_palette_free(&pd->palette); free(pd); } @@ -389,6 +396,8 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, pd->status = 128 + SIGHUP; screen_init(&pd->s, sx - 2, sy - 2, 0); + colour_palette_init(&pd->palette); + colour_palette_from_option(&pd->palette, global_w_options); pd->px = px; pd->py = py; @@ -403,7 +412,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, pd->job = job_run(shellcmd, argc, argv, s, cwd, popup_job_update_cb, popup_job_complete_cb, NULL, pd, JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, pd->sx - 2, pd->sy - 2); - pd->ictx = input_init(NULL, job_get_event(pd->job)); + pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd); diff --git a/screen-redraw.c b/screen-redraw.c index 4c4135a8..3df57383 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -800,12 +800,13 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx) static void screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) { - struct client *c = ctx->c; - struct window *w = c->session->curw->window; - struct tty *tty = &c->tty; - struct screen *s; - struct grid_cell defaults; - u_int i, j, top, x, y, width; + struct client *c = ctx->c; + struct window *w = c->session->curw->window; + struct tty *tty = &c->tty; + struct screen *s = wp->screen; + struct colour_palette *palette = &wp->palette; + struct grid_cell defaults; + u_int i, j, top, x, y, width; log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id); @@ -815,8 +816,6 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) top = ctx->statuslines; else top = 0; - - s = wp->screen; for (j = 0; j < wp->sy; j++) { if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy) continue; @@ -849,7 +848,6 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) __func__, c->name, wp->id, i, j, x, y, width); tty_default_colours(&defaults, wp); - tty_draw_line(tty, s, i, j, width, x, y, &defaults, - wp->palette); + tty_draw_line(tty, s, i, j, width, x, y, &defaults, palette); } } diff --git a/screen-write.c b/screen-write.c index b04155c3..a11b4771 100644 --- a/screen-write.c +++ b/screen-write.c @@ -171,15 +171,6 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, memset(ttyctx, 0, sizeof *ttyctx); - if (ctx->wp != NULL) { - tty_default_colours(&ttyctx->defaults, ctx->wp); - ttyctx->palette = ctx->wp->palette; - } else { - memcpy(&ttyctx->defaults, &grid_default_cell, - sizeof ttyctx->defaults); - ttyctx->palette = NULL; - } - ttyctx->s = s; ttyctx->sx = screen_size_x(s); ttyctx->sy = screen_size_y(s); @@ -189,15 +180,21 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, ttyctx->orlower = s->rlower; ttyctx->orupper = s->rupper; - if (ctx->init_ctx_cb != NULL) + memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults); + if (ctx->init_ctx_cb != NULL) { ctx->init_ctx_cb(ctx, ttyctx); - else { + if (ttyctx->palette != NULL) { + ttyctx->defaults.fg = ttyctx->palette->fg; + ttyctx->defaults.bg = ttyctx->palette->bg; + } + } else { ttyctx->redraw_cb = screen_write_redraw_cb; - if (ctx->wp == NULL) - ttyctx->set_client_cb = NULL; - else + if (ctx->wp != NULL) { + tty_default_colours(&ttyctx->defaults, ctx->wp); + ttyctx->palette = &ctx->wp->palette; ttyctx->set_client_cb = screen_write_set_client_cb; - ttyctx->arg = ctx->wp; + ttyctx->arg = ctx->wp; + } } if (ctx->wp != NULL && @@ -680,6 +677,7 @@ screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny) memcpy(&gc, &grid_default_cell, sizeof gc); gc.attr |= GRID_ATTR_CHARSET; + gc.flags |= GRID_FLAG_NOPALETTE; screen_write_putc(ctx, &gc, 'l'); for (i = 1; i < nx - 1; i++) @@ -1423,6 +1421,18 @@ screen_write_clearhistory(struct screen_write_ctx *ctx) grid_clear_history(ctx->s->grid); } +/* Force a full redraw. */ +void +screen_write_fullredraw(struct screen_write_ctx *ctx) +{ + struct tty_ctx ttyctx; + + screen_write_collect_flush(ctx, 0, __func__); + + screen_write_initctx(ctx, &ttyctx, 1); + ttyctx.redraw_cb(&ttyctx); +} + /* Trim collected items. */ static struct screen_write_citem * screen_write_collect_trim(struct screen_write_ctx *ctx, u_int y, u_int x, diff --git a/tmux.1 b/tmux.1 index 95f1ba41..a22de76c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1677,9 +1677,13 @@ The following commands are supported in copy mode: .It Li "cancel" Ta "q" Ta "Escape" .It Li "clear-selection" Ta "Escape" Ta "C-g" .It Li "copy-end-of-line []" Ta "" Ta "" -.It Li "copy-end-of-line-and-cancel []" Ta "D" Ta "C-k" +.It Li "copy-end-of-line-and-cancel []" Ta "" Ta "" +.It Li "copy-pipe-end-of-line [] []" Ta "" Ta "" +.It Li "copy-pipe-end-of-line-and-cancel [] []" Ta "D" Ta "C-k" .It Li "copy-line []" Ta "" Ta "" .It Li "copy-line-and-cancel []" Ta "" Ta "" +.It Li "copy-pipe-line [] []" Ta "" Ta "" +.It Li "copy-pipe-line-and-cancel [] []" Ta "" Ta "" .It Li "copy-pipe [] []" Ta "" Ta "" .It Li "copy-pipe-no-clear [] []" Ta "" Ta "" .It Li "copy-pipe-and-cancel [] []" Ta "" Ta "" @@ -4143,7 +4147,6 @@ see the .Sx STYLES section. Attributes are ignored. -.Pp .It Ic pane-base-index Ar index Like .Ic base-index , @@ -4301,6 +4304,13 @@ 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 pane-colours[] Ar colour +The default colour palette. +Each entry in the array defines the colour +.Nm +uses when the colour with that index is requested. +The index may be from zero to 255. +.Pp .It Xo Ic remain-on-exit .Op Ic on | off | failed .Xc diff --git a/tmux.h b/tmux.h index 42f03bd6..a3f7fdd9 100644 --- a/tmux.h +++ b/tmux.h @@ -652,6 +652,15 @@ enum utf8_state { /* Special colours. */ #define COLOUR_DEFAULT(c) ((c) == 8 || (c) == 9) +/* Replacement palette. */ +struct colour_palette { + int fg; + int bg; + + int *palette; + int *default_palette; +}; + /* Grid attributes. Anything above 0xff is stored in an extended cell. */ #define GRID_ATTR_BRIGHT 0x1 #define GRID_ATTR_DIM 0x2 @@ -989,9 +998,6 @@ struct window_pane { u_int xoff; u_int yoff; - int fg; - int bg; - int flags; #define PANE_REDRAW 0x1 #define PANE_DROP 0x2 @@ -1029,7 +1035,7 @@ struct window_pane { struct grid_cell cached_gc; struct grid_cell cached_active_gc; - int *palette; + struct colour_palette palette; int pipe_fd; struct bufferevent *pipe_event; @@ -1427,7 +1433,7 @@ struct tty_ctx { /* The default colours and palette. */ struct grid_cell defaults; - int *palette; + struct colour_palette *palette; /* Containing region (usually window) offset and size. */ int bigger; @@ -1827,11 +1833,11 @@ RB_HEAD(key_tables, key_table); /* Option data. */ RB_HEAD(options_array, options_array_item); union options_value { - char *string; - long long number; - struct style style; - struct options_array array; - struct cmd_list *cmdlist; + char *string; + long long number; + struct style style; + struct options_array array; + struct cmd_list *cmdlist; }; /* Option table entries. */ @@ -2165,7 +2171,7 @@ void tty_update_window_offset(struct window *); void tty_update_client_offset(struct client *); void tty_raw(struct tty *, const char *); void tty_attributes(struct tty *, const struct grid_cell *, - const struct grid_cell *, int *); + const struct grid_cell *, struct colour_palette *); void tty_reset(struct tty *); void tty_region_off(struct tty *); void tty_margin_off(struct tty *); @@ -2181,7 +2187,7 @@ void tty_puts(struct tty *, const char *); void tty_putc(struct tty *, u_char); void tty_putn(struct tty *, const void *, size_t, u_int); void tty_cell(struct tty *, const struct grid_cell *, - const struct grid_cell *, int *); + const struct grid_cell *, struct colour_palette *); int tty_init(struct tty *, struct client *); void tty_resize(struct tty *); void tty_set_size(struct tty *, u_int, u_int, u_int, u_int); @@ -2191,7 +2197,7 @@ void tty_stop_tty(struct tty *); void tty_set_title(struct tty *, const char *); void tty_update_mode(struct tty *, int, struct screen *); void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int, - u_int, u_int, const struct grid_cell *, int *); + u_int, u_int, const struct grid_cell *, struct colour_palette *); void tty_sync_start(struct tty *); void tty_sync_end(struct tty *); int tty_open(struct tty *, char **); @@ -2573,7 +2579,8 @@ void recalculate_sizes(void); void recalculate_sizes_now(int); /* input.c */ -struct input_ctx *input_init(struct window_pane *, struct bufferevent *); +struct input_ctx *input_init(struct window_pane *, struct bufferevent *, + struct colour_palette *); void input_free(struct input_ctx *); void input_reset(struct input_ctx *, int); struct evbuffer *input_pending(struct input_ctx *); @@ -2598,6 +2605,12 @@ int colour_fromstring(const char *s); int colour_256toRGB(int); int colour_256to16(int); int colour_byname(const char *); +void colour_palette_init(struct colour_palette *); +void colour_palette_clear(struct colour_palette *); +void colour_palette_free(struct colour_palette *); +int colour_palette_get(struct colour_palette *, int); +int colour_palette_set(struct colour_palette *, int, int); +void colour_palette_from_option(struct colour_palette *, struct options *); /* attributes.c */ const char *attributes_tostring(int); @@ -2737,6 +2750,7 @@ void screen_write_clearendofscreen(struct screen_write_ctx *, u_int); void screen_write_clearstartofscreen(struct screen_write_ctx *, u_int); void screen_write_clearscreen(struct screen_write_ctx *, u_int); void screen_write_clearhistory(struct screen_write_ctx *); +void screen_write_fullredraw(struct screen_write_ctx *); void screen_write_collect_end(struct screen_write_ctx *); void screen_write_collect_add(struct screen_write_ctx *, const struct grid_cell *); @@ -2834,10 +2848,6 @@ struct window_pane *window_pane_find_by_id_str(const char *); struct window_pane *window_pane_find_by_id(u_int); int window_pane_destroy_ready(struct window_pane *); void window_pane_resize(struct window_pane *, u_int, u_int); -void window_pane_set_palette(struct window_pane *, u_int, int); -void window_pane_unset_palette(struct window_pane *, u_int); -void window_pane_reset_palette(struct window_pane *); -int window_pane_get_palette(struct window_pane *, int); int window_pane_set_mode(struct window_pane *, struct window_pane *, const struct window_mode *, struct cmd_find_state *, struct args *); diff --git a/tty.c b/tty.c index 61b38eec..6cebe051 100644 --- a/tty.c +++ b/tty.c @@ -45,9 +45,12 @@ static void tty_cursor_pane_unless_wrap(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_invalidate(struct tty *); static void tty_colours(struct tty *, const struct grid_cell *); -static void tty_check_fg(struct tty *, int *, struct grid_cell *); -static void tty_check_bg(struct tty *, int *, struct grid_cell *); -static void tty_check_us(struct tty *, int *, struct grid_cell *); +static void tty_check_fg(struct tty *, struct colour_palette *, + struct grid_cell *); +static void tty_check_bg(struct tty *, struct colour_palette *, + struct grid_cell *); +static void tty_check_us(struct tty *, struct colour_palette *, + struct grid_cell *); static void tty_colours_fg(struct tty *, const struct grid_cell *); static void tty_colours_bg(struct tty *, const struct grid_cell *); static void tty_colours_us(struct tty *, const struct grid_cell *); @@ -66,7 +69,7 @@ static void tty_emulate_repeat(struct tty *, enum tty_code_code, static void tty_repeat_space(struct tty *, u_int); static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int); static void tty_default_attributes(struct tty *, const struct grid_cell *, - int *, u_int); + struct colour_palette *, u_int); static int tty_check_overlay(struct tty *, u_int, u_int); #define tty_use_margin(tty) \ @@ -939,27 +942,6 @@ tty_update_client_offset(struct client *c) c->flags |= (CLIENT_REDRAWWINDOW|CLIENT_REDRAWSTATUS); } -/* Get a palette entry. */ -static int -tty_get_palette(int *palette, int c) -{ - int new; - - if (palette == NULL) - return (-1); - - new = -1; - if (c < 8) - new = palette[c]; - else if (c >= 90 && c <= 97) - new = palette[8 + c - 90]; - else if (c & COLOUR_FLAG_256) - new = palette[c & ~COLOUR_FLAG_256]; - if (new == 0) - return (-1); - return (new); -} - /* * Is the region large enough to be worth redrawing once later rather than * probably several times now? Currently yes if it is more than 50% of the @@ -1341,7 +1323,8 @@ tty_check_overlay(struct tty *tty, u_int px, u_int py) void tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, - u_int atx, u_int aty, const struct grid_cell *defaults, int *palette) + u_int atx, u_int aty, const struct grid_cell *defaults, + struct colour_palette *palette) { struct grid *gd = s->grid; struct grid_cell gc, last; @@ -1356,6 +1339,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx, atx, aty); + log_debug("%s: defaults: fg=%d, bg=%d", __func__, defaults->fg, + defaults->bg); /* * py is the line in the screen to draw. @@ -2061,7 +2046,7 @@ tty_cmd_syncstart(struct tty *tty, __unused const struct tty_ctx *ctx) void tty_cell(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, int *palette) + const struct grid_cell *defaults, struct colour_palette *palette) { const struct grid_cell *gcp; @@ -2381,17 +2366,19 @@ out: void tty_attributes(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, int *palette) + const struct grid_cell *defaults, struct colour_palette *palette) { struct grid_cell *tc = &tty->cell, gc2; int changed; /* Copy cell and update default colours. */ memcpy(&gc2, gc, sizeof gc2); - if (gc2.fg == 8) - gc2.fg = defaults->fg; - if (gc2.bg == 8) - gc2.bg = defaults->bg; + if (~gc->flags & GRID_FLAG_NOPALETTE) { + if (gc2.fg == 8) + gc2.fg = defaults->fg; + if (gc2.bg == 8) + gc2.bg = defaults->bg; + } /* Ignore cell if it is the same as the last one. */ if (gc2.attr == tty->last_cell.attr && @@ -2533,13 +2520,14 @@ tty_colours(struct tty *tty, const struct grid_cell *gc) if (!COLOUR_DEFAULT(gc->bg) && gc->bg != tc->bg) tty_colours_bg(tty, gc); - /* Set the underscore color. */ + /* Set the underscore colour. */ if (gc->us != tc->us) tty_colours_us(tty, gc); } static void -tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_fg(struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2554,7 +2542,7 @@ tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) c = gc->fg; if (c < 8 && gc->attr & GRID_ATTR_BRIGHT) c += 90; - if ((c = tty_get_palette(palette, c)) != -1) + if ((c = colour_palette_get(palette, c)) != -1) gc->fg = c; } @@ -2595,7 +2583,8 @@ tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) } static void -tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_bg(struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2603,7 +2592,7 @@ tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = tty_get_palette(palette, gc->bg)) != -1) + if ((c = colour_palette_get(palette, gc->bg)) != -1) gc->bg = c; } @@ -2646,13 +2635,14 @@ tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) } static void -tty_check_us(__unused struct tty *tty, int *palette, struct grid_cell *gc) +tty_check_us(__unused struct tty *tty, struct colour_palette *palette, + struct grid_cell *gc) { int c; /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = tty_get_palette(palette, gc->us)) != -1) + if ((c = colour_palette_get(palette, gc->us)) != -1) gc->us = c; } @@ -2793,8 +2783,8 @@ static void tty_window_default_style(struct grid_cell *gc, struct window_pane *wp) { memcpy(gc, &grid_default_cell, sizeof *gc); - gc->fg = wp->fg; - gc->bg = wp->bg; + gc->fg = wp->palette.fg; + gc->bg = wp->palette.bg; } void @@ -2831,7 +2821,7 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) static void tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, - int *palette, u_int bg) + struct colour_palette *palette, u_int bg) { struct grid_cell gc; diff --git a/window.c b/window.c index aa448e1f..f94acfcb 100644 --- a/window.c +++ b/window.c @@ -478,6 +478,14 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify) return (1); } +static int +window_pane_get_palette(struct window_pane *wp, int c) +{ + if (wp == NULL) + return (-1); + return (colour_palette_get(&wp->palette, c)); +} + void window_redraw_active_switch(struct window *w, struct window_pane *wp) { @@ -855,9 +863,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->fd = -1; - wp->fg = 8; - wp->bg = 8; - TAILQ_INIT(&wp->modes); TAILQ_INIT (&wp->resize_queue); @@ -867,6 +872,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->pipe_fd = -1; + colour_palette_init(&wp->palette); screen_init(&wp->base, sx, sy, hlimit); wp->screen = &wp->base; @@ -916,7 +922,7 @@ window_pane_destroy(struct window_pane *wp) free((void *)wp->cwd); free(wp->shell); cmd_free_argv(wp->argc, wp->argv); - free(wp->palette); + colour_palette_free(&wp->palette); free(wp); } @@ -968,7 +974,7 @@ window_pane_set_event(struct window_pane *wp) wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, window_pane_error_callback, wp); - wp->ictx = input_init(wp, wp->event); + wp->ictx = input_init(wp, wp->event, &wp->palette); bufferevent_enable(wp->event, EV_READ|EV_WRITE); } @@ -1000,60 +1006,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) wme->mode->resize(wme, sx, sy); } -void -window_pane_set_palette(struct window_pane *wp, u_int n, int colour) -{ - if (n > 0xff) - return; - - if (wp->palette == NULL) - wp->palette = xcalloc(0x100, sizeof *wp->palette); - - wp->palette[n] = colour; - wp->flags |= PANE_REDRAW; -} - -void -window_pane_unset_palette(struct window_pane *wp, u_int n) -{ - if (n > 0xff || wp->palette == NULL) - return; - - wp->palette[n] = 0; - wp->flags |= PANE_REDRAW; -} - -void -window_pane_reset_palette(struct window_pane *wp) -{ - if (wp->palette == NULL) - return; - - free(wp->palette); - wp->palette = NULL; - wp->flags |= PANE_REDRAW; -} - -int -window_pane_get_palette(struct window_pane *wp, int c) -{ - int new; - - if (wp == NULL || wp->palette == NULL) - return (-1); - - new = -1; - if (c < 8) - new = wp->palette[c]; - else if (c >= 90 && c <= 97) - new = wp->palette[8 + c - 90]; - else if (c & COLOUR_FLAG_256) - new = wp->palette[c & ~COLOUR_FLAG_256]; - if (new == 0) - return (-1); - return (new); -} - int window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, const struct window_mode *mode, struct cmd_find_state *fs,