> -static unsigned int defaultcs = 256;
>> +unsigned int defaultfg = 255;
>> +unsigned int defaultbg = 254;
>> +unsigned int defaultcs = 256;

> The values in the config are changed here. Is it intended? If so, why?

The colours 0 and 7 are distinct and can be set independently from the
foreground and background colours in most terminals. I modified defaultbg
and
defaultfg to reflect this. In retrospect, I probably should have made them >
255 to avoid conflicting with legitimate palette colours. I have done so in
the
amended patch.

>> +     n = sprintf(buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
num, r, r, g, g, b, b);

> I prefer snprintf here, just in case. The arguments for sprintf are too
long and
> should be wrapped.

Ok.

>> +                     else if (xsetcolorname(defaultbg, p))
>> +                             fprintf(stderr, "erresc: invalid
background color %d\n", p);

> The argument p is not int. The compiler (clang) also gives a warning
about it.

Oops. I'm not sure why my gcc didn't produce a warning.

> Case 10 should be ordered before case 11.

Ok.

>               case 104: /* color reset, here p = NULL */
>                       j = (narg > 1) ? atoi(strescseq.args[1]) : -1;

> The variable j should be checked and also the xgetcolor and/or functions
using
> it should have range checks. It seems dc.col can be out-of-bounds with
some
> input. I also noticed a crash here while testing.

Ok.

>> +void xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char
*b);

> xgetcolor should be below xstrdup and as a separate line.

Will do.

Thanks for reviewing the patch :). I have attached an amended copy below.
Let
me know if anything else requires attention.

Regards,
Raheman

On Sat, Dec 11, 2021 at 7:01 AM Hiltjo Posthuma <[email protected]>
wrote:

> Hi,
>
> Some comments below:
>
> On Fri, Dec 10, 2021 at 05:53:40PM -0500, Raheman Vaiya wrote:
> > The attached patch adds full support for the OSC 10/11/12/4 control
> > sequences.
> > These are used by programs like vim and theme.sh to query and set
> terminal
> > colours and are supported by most major terminals (e.g alacrittty, kitty,
> > libvte). I submitted a patch to the wiki some time ago, but it didn't
>
> xterm supports it too.
>
> > include
> > support for query sequences. I am posting it here because I feel it would
> > be a
> > good candidate for inclusion into st itself.
> >
> > You can test it using https://github.com/lemnos/theme.sh by running
> >
> > theme.sh zenburn
> > theme.sh -p
> >
> > Don't hesitate to let me know if I have made any grievous errors :P.
> >
> > Regards,
> > Raheman
>
> > diff --git a/config.def.h b/config.def.h
> > index 6f05dce..3932e83 100644
> > --- a/config.def.h
> > +++ b/config.def.h
> > @@ -127,9 +127,9 @@ static const char *colorname[] = {
> >   * Default colors (colorname index)
> >   * foreground, background, cursor, reverse cursor
> >   */
> > -unsigned int defaultfg = 7;
> > -unsigned int defaultbg = 0;
> > -static unsigned int defaultcs = 256;
> > +unsigned int defaultfg = 255;
> > +unsigned int defaultbg = 254;
> > +unsigned int defaultcs = 256;
> >  static unsigned int defaultrcs = 257;
>
> The values in the config are changed here. Is it intended? If so, why?
>
> >
> >  /*
> > diff --git a/st.c b/st.c
> > index a9338e1..a469512 100644
> > --- a/st.c
> > +++ b/st.c
> > @@ -1842,6 +1842,32 @@ csireset(void)
> >       memset(&csiescseq, 0, sizeof(csiescseq));
> >  }
> >
> > +void
> > +osc4_color_response(int num)
> > +{
> > +     int n;
> > +     char buf[32];
> > +     unsigned char r,g,b;
> > +
> > +     xgetcolor(num, &r,&g,&b);
> > +     n = sprintf(buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
> num, r, r, g, g, b, b);
> > +
>
> I prefer snprintf here, just in case. The arguments for sprintf are too
> long and
> should be wrapped.
>
> > +     ttywrite(buf, n, 1);
> > +}
> > +
> > +void
> > +osc_color_response(int index, int num)
> > +{
> > +     int n;
> > +     char buf[32];
> > +     unsigned char r,g,b;
> > +
> > +     xgetcolor(index, &r,&g,&b);
> > +     n = sprintf(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)
> >  {
> > @@ -1880,6 +1906,45 @@ strhandle(void)
> >                               }
> >                       }
> >                       return;
> > +             case 11:
> > +                     if (narg < 2)
> > +                             break;
> > +
> > +                     p = strescseq.args[1];
> > +
> > +                     if(!strcmp(p, "?"))
> > +                             osc_color_response(defaultbg, 11);
> > +                     else if (xsetcolorname(defaultbg, p))
> > +                             fprintf(stderr, "erresc: invalid
> background color %d\n", p);
>
> The argument p is not int. The compiler (clang) also gives a warning about
> it.
>
> > +                     else
> > +                             redraw();
> > +                     break;
> > +             case 12:
> > +                     if (narg < 2)
> > +                             break;
> > +
> > +                     p = strescseq.args[1];
> > +
> > +                     if(!strcmp(p, "?"))
> > +                             osc_color_response(defaultcs, 12);
> > +                     else if (xsetcolorname(defaultcs, p))
> > +                             fprintf(stderr, "erresc: invalid cursor
> color %d\n", p);
> > +                     else
> > +                             redraw();
> > +                     break;
> > +             case 10:
>
> Case 10 should be ordered before case 11.
>
> > +                     if (narg < 2)
> > +                             break;
> > +
> > +                     p = strescseq.args[1];
> > +
> > +                     if(!strcmp(p, "?"))
> > +                             osc_color_response(defaultfg, 10);
> > +                     else if (xsetcolorname(defaultfg, p))
> > +                             fprintf(stderr, "erresc: invalid
> foreground color %d\n", p);
> > +                     else
> > +                             redraw();
> > +                     break;
> >               case 4: /* color set */
> >                       if (narg < 3)
> >                               break;
> > @@ -1887,7 +1952,10 @@ strhandle(void)
> >                       /* FALLTHROUGH */
> >               case 104: /* color reset, here p = NULL */
> >                       j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
>
> The variable j should be checked and also the xgetcolor and/or functions
> using
> it should have range checks. It seems dc.col can be out-of-bounds with some
> input. I also noticed a crash here while testing.
>
> > -                     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 fa2eddf..47d76ca 100644
> > --- a/st.h
> > +++ b/st.h
> > @@ -107,6 +107,7 @@ char *getsel(void);
> >
> >  size_t utf8encode(Rune, char *);
> >
> > +void xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char
> *b);
>
> xgetcolor should be below xstrdup and as a separate line.
>
> >  void *xmalloc(size_t);
> >  void *xrealloc(void *, size_t);
> >  char *xstrdup(const char *);
> > @@ -123,3 +124,4 @@ extern char *termname;
> >  extern unsigned int tabspaces;
> >  extern unsigned int defaultfg;
> >  extern unsigned int defaultbg;
> > +extern unsigned int defaultcs;
> > diff --git a/x.c b/x.c
> > index 89786b8..3761fd0 100644
> > --- a/x.c
> > +++ b/x.c
> > @@ -799,6 +799,14 @@ xloadcols(void)
> >       loaded = 1;
> >  }
> >
> > +void
> > +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b)
> > +{
> > +     *r = dc.col[x].color.red >> 8;
> > +     *g = dc.col[x].color.green >> 8;
> > +     *b = dc.col[x].color.blue >> 8;
> > +}
> > +
> >  int
> >  xsetcolorname(int x, const char *name)
> >  {
>
> This patch needs a bit more care and testing to be able to accept it.
>
> Thanks for your efforts,
>
> --
> Kind regards,
> Hiltjo
>
>
diff --git a/config.def.h b/config.def.h
index 6f05dce..91ab8ca 100644
--- a/config.def.h
+++ b/config.def.h
@@ -120,6 +120,8 @@ static const char *colorname[] = {
 	/* more colors can be added after 255 to use with DefaultXX */
 	"#cccccc",
 	"#555555",
+	"gray90", /* default foreground colour */
+	"black", /* default background colour */
 };
 
 
@@ -127,9 +129,9 @@ static const char *colorname[] = {
  * Default colors (colorname index)
  * foreground, background, cursor, reverse cursor
  */
-unsigned int defaultfg = 7;
-unsigned int defaultbg = 0;
-static unsigned int defaultcs = 256;
+unsigned int defaultfg = 258;
+unsigned int defaultbg = 259;
+unsigned int defaultcs = 256;
 static unsigned int defaultrcs = 257;
 
 /*
diff --git a/st.c b/st.c
index a9338e1..ad5c8e8 100644
--- a/st.c
+++ b/st.c
@@ -1842,6 +1842,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)
 {
@@ -1880,6 +1916,45 @@ strhandle(void)
 				}
 			}
 			return;
+		case 10:
+			if (narg < 2)
+				break;
+
+			p = strescseq.args[1];
+
+			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;
+		case 11:
+			if (narg < 2)
+				break;
+
+			p = strescseq.args[1];
+
+			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;
+		case 12:
+			if (narg < 2)
+				break;
+
+			p = strescseq.args[1];
+
+			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;
 		case 4: /* color set */
 			if (narg < 3)
 				break;
@@ -1887,7 +1962,10 @@ strhandle(void)
 			/* FALLTHROUGH */
 		case 104: /* color reset, here p = NULL */
 			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 fa2eddf..519b9bd 100644
--- a/st.h
+++ b/st.h
@@ -111,6 +111,8 @@ 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);
+
 /* config.h globals */
 extern char *utmp;
 extern char *scroll;
@@ -123,3 +125,4 @@ extern char *termname;
 extern unsigned int tabspaces;
 extern unsigned int defaultfg;
 extern unsigned int defaultbg;
+extern unsigned int defaultcs;
diff --git a/x.c b/x.c
index 89786b8..8a16faa 100644
--- a/x.c
+++ b/x.c
@@ -799,6 +799,19 @@ xloadcols(void)
 	loaded = 1;
 }
 
+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)
 {

Reply via email to