Support X11 colour names and some other variations for OSC 10/11, also

add OSC 110 and 111. GitHub issue 2567.
This commit is contained in:
nicm
2021-02-15 09:39:37 +00:00
parent 632636dba5
commit 6642706f7b
5 changed files with 721 additions and 54 deletions

135
input.c
View File

@ -138,6 +138,8 @@ static void input_osc_10(struct input_ctx *, const char *);
static void input_osc_11(struct input_ctx *, const char *);
static void input_osc_52(struct input_ctx *, const char *);
static void input_osc_104(struct input_ctx *, const char *);
static void input_osc_110(struct input_ctx *, const char *);
static void input_osc_111(struct input_ctx *, const char *);
/* Transition entry/exit handlers. */
static void input_clear(struct input_ctx *);
@ -2304,6 +2306,12 @@ input_exit_osc(struct input_ctx *ictx)
case 104:
input_osc_104(ictx, p);
break;
case 110:
input_osc_110(ictx, p);
break;
case 111:
input_osc_111(ictx, p);
break;
case 112:
if (*p == '\0') /* no arguments allowed */
screen_set_cursor_colour(sctx->s, "");
@ -2422,50 +2430,41 @@ input_top_bit_set(struct input_ctx *ictx)
/* Parse colour from OSC. */
static int
input_osc_parse_colour(const char *p, u_int *r, u_int *g, u_int *b)
input_osc_parse_colour(const char *p)
{
u_int rsize, gsize, bsize;
const char *cp, *s = p;
double c, m, y, k = 0;
u_int r, g, b;
size_t len = strlen(p);
int colour = -1;
char *copy;
if (sscanf(p, "rgb:%x/%x/%x", r, g, b) != 3)
return (0);
p += 4;
cp = strchr(p, '/');
rsize = cp - p;
if (rsize == 1)
(*r) = (*r) | ((*r) << 4);
else if (rsize == 3)
(*r) >>= 4;
else if (rsize == 4)
(*r) >>= 8;
else if (rsize != 2)
return (0);
p = cp + 1;
cp = strchr(p, '/');
gsize = cp - p;
if (gsize == 1)
(*g) = (*g) | ((*g) << 4);
else if (gsize == 3)
(*g) >>= 4;
else if (gsize == 4)
(*g) >>= 8;
else if (gsize != 2)
return (0);
bsize = strlen(cp + 1);
if (bsize == 1)
(*b) = (*b) | ((*b) << 4);
else if (bsize == 3)
(*b) >>= 4;
else if (bsize == 4)
(*b) >>= 8;
else if (bsize != 2)
return (0);
log_debug("%s: %s = %02x%02x%02x", __func__, s, *r, *g, *b);
return (1);
if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
(len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
colour = colour_join_rgb(r, g, b);
else if ((len == 18 &&
sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
(len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
y >= 0 && y <= 1 && k >= 0 && k <= 1) {
colour = colour_join_rgb(
(1 - c) * (1 - k) * 255,
(1 - m) * (1 - k) * 255,
(1 - y) * (1 - k) * 255);
} else {
while (*p == ' ')
p++;
while (len != 0 && p[len - 1] == ' ')
len--;
copy = xstrndup(p, len);
colour = colour_byname(copy);
free(copy);
}
log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
return (colour);
}
/* Reply to a colour request. */
@ -2493,7 +2492,7 @@ input_osc_4(struct input_ctx *ictx, const char *p)
struct window_pane *wp = ictx->wp;
char *copy, *s, *next = NULL;
long idx;
u_int r, g, b;
int c;
if (wp == NULL)
return;
@ -2507,12 +2506,12 @@ input_osc_4(struct input_ctx *ictx, const char *p)
goto bad;
s = strsep(&next, ";");
if (!input_osc_parse_colour(s, &r, &g, &b)) {
if ((c = input_osc_parse_colour(s)) == -1) {
s = next;
continue;
}
window_pane_set_palette(wp, idx, colour_join_rgb(r, g, b));
window_pane_set_palette(wp, idx, c);
s = next;
}
@ -2530,7 +2529,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
struct grid_cell defaults;
u_int r, g, b;
int c;
if (wp == NULL)
return;
@ -2541,9 +2540,9 @@ input_osc_10(struct input_ctx *ictx, const char *p)
return;
}
if (!input_osc_parse_colour(p, &r, &g, &b))
if ((c = input_osc_parse_colour(p)) == -1)
goto bad;
wp->fg = colour_join_rgb(r, g, b);
wp->fg = c;
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
return;
@ -2552,13 +2551,29 @@ bad:
log_debug("bad OSC 10: %s", p);
}
/* Handle the OSC 110 sequence for resetting background colour. */
static void
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);
}
/* Handle the OSC 11 sequence for setting and querying background colour. */
static void
input_osc_11(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
struct grid_cell defaults;
u_int r, g, b;
int c;
if (wp == NULL)
return;
@ -2569,9 +2584,9 @@ input_osc_11(struct input_ctx *ictx, const char *p)
return;
}
if (!input_osc_parse_colour(p, &r, &g, &b))
goto bad;
wp->bg = colour_join_rgb(r, g, b);
if ((c = input_osc_parse_colour(p)) == -1)
goto bad;
wp->bg = c;
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
return;
@ -2580,6 +2595,22 @@ bad:
log_debug("bad OSC 11: %s", p);
}
/* Handle the OSC 111 sequence for resetting background colour. */
static void
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);
}
/* Handle the OSC 52 sequence for setting the clipboard. */
static void
input_osc_52(struct input_ctx *ictx, const char *p)