mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 18:28:56 +00:00
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:
parent
01fd4b997e
commit
7eea3d7ab8
@ -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
112
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
135
input.c
135
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) {
|
||||
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;
|
||||
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:
|
||||
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) {
|
||||
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:
|
||||
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) {
|
||||
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:
|
||||
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;
|
||||
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:
|
||||
if (bad)
|
||||
log_debug("bad OSC 104: %s", p);
|
||||
if (redraw)
|
||||
screen_write_fullredraw(&ictx->ctx);
|
||||
free(copy);
|
||||
}
|
||||
|
@ -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,
|
||||
|
19
options.c
19
options.c
@ -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
19
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);
|
||||
|
@ -803,7 +803,8 @@ 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 screen *s = wp->screen;
|
||||
struct colour_palette *palette = &wp->palette;
|
||||
struct grid_cell defaults;
|
||||
u_int i, j, top, x, y, width;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,16 +180,22 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->wp != NULL &&
|
||||
(~ctx->flags & SCREEN_WRITE_SYNC) &&
|
||||
@ -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
14
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 [<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
|
||||
|
36
tmux.h
36
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;
|
||||
@ -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 *);
|
||||
|
66
tty.c
66
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 (~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;
|
||||
|
||||
|
70
window.c
70
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,
|
||||
|
Loading…
Reference in New Issue
Block a user