From 9ab02993c3906049965c10319fc6baf403ef4456 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 24 Feb 2022 13:24:00 +0100 Subject: [PATCH] Add support for OSC color sequences Ref. - https://git.suckless.org/st/commit/8e310303903792c010d03c046ba75f8b18f7d3a7.html - https://git.suckless.org/st/commit/273db5ceaf392e68c2faf8f7dec14ea2e25e980d.html --- st.c | 79 +++++++++++++++++++++++++++++++++++++++++++++--------------- st.h | 3 +++ x.c | 13 ++++++++++ 3 files changed, 76 insertions(+), 19 deletions(-) diff --git a/st.c b/st.c index c89c05d..5d6f0e2 100644 --- a/st.c +++ b/st.c @@ -168,6 +168,8 @@ static void readcolonargs(char **, int, int[][CAR_PER_ARG]); #endif // UNDERCURL_PATCH static void csiparse(void); static void csireset(void); +static void osc4_color_response(int num); +static void osc_color_response(int index, int num); static int eschandle(uchar); static void strdump(void); static void strhandle(void); @@ -2393,6 +2395,42 @@ csireset(void) memset(&csiescseq, 0, sizeof(csiescseq)); } +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + void strhandle(void) { @@ -2443,44 +2481,45 @@ strhandle(void) } } return; - case 10: /* foreground set */ - #if OSC_10_11_12_2_PATCH + case 10: if (narg < 2) break; p = strescseq.args[1]; - if (xsetcolorname(defaultfg, p)) - fprintf(stderr, "erresc: invalid foreground color %d\n", p); + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); else redraw(); - break; return; - #endif // OSC_10_11_12_2_PATCH - case 11: /* background set */ - #if OSC_10_11_12_2_PATCH + case 11: if (narg < 2) break; p = strescseq.args[1]; - if (xsetcolorname(defaultbg, p)) - fprintf(stderr, "erresc: invalid background color %d\n", p); + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); else redraw(); - break; return; - #endif // OSC_10_11_12_2_PATCH - case 12: /* cursor color */ - #if OSC_10_11_12_2_PATCH + case 12: if (narg < 2) break; p = strescseq.args[1]; - if (xsetcolorname(defaultcs, p)) - fprintf(stderr, "erresc: invalid cursor color %d\n", p); + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); else redraw(); - break; - #endif // OSC_10_11_12_2_PATCH + return; case 4: /* color set */ if ((par == 4 && narg < 3) || narg < 2) break; @@ -2496,7 +2535,9 @@ strhandle(void) else j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { + if (!strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index aa5df46..3badccf 100644 --- a/st.h +++ b/st.h @@ -325,6 +325,9 @@ size_t utf8encode(Rune, char *); void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); + +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + #if BOXDRAW_PATCH int isboxdraw(Rune); ushort boxdrawindex(const Glyph *); diff --git a/x.c b/x.c index 52c7348..c0abc32 100644 --- a/x.c +++ b/x.c @@ -934,6 +934,19 @@ xloadcols(void) } #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + int xsetcolorname(int x, const char *name) {