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.
This commit is contained in:
nicm 2021-08-11 20:49:55 +00:00
parent 01fd4b997e
commit 7eea3d7ab8
12 changed files with 352 additions and 239 deletions

View File

@ -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--) {

112
colour.c
View File

@ -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);
}
}

165
input.c
View File

@ -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);
}

View File

@ -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,

View File

@ -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);

19
popup.c
View File

@ -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);

View File

@ -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);
}
}

View File

@ -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,

14
tmux.1
View File

@ -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 [<prefix>]" Ta "" Ta ""
.It Li "copy-end-of-line-and-cancel [<prefix>]" Ta "D" Ta "C-k"
.It Li "copy-end-of-line-and-cancel [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-end-of-line [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-end-of-line-and-cancel [<command>] [<prefix>]" Ta "D" Ta "C-k"
.It Li "copy-line [<prefix>]" Ta "" Ta ""
.It Li "copy-line-and-cancel [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-line [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-line-and-cancel [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-no-clear [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-and-cancel [<command>] [<prefix>]" 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

46
tmux.h
View File

@ -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 *);

74
tty.c
View File

@ -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;

View File

@ -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,