[dev] [PATCH] Add RGB color definition

From: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
Date: Fri, 19 Jul 2013 20:51:33 +0200

From: "Roberto E. Vargas Caballero" <k0ga_AT_shike2.com>

It is impossible allocate all the RGB colors using a static
array, so it is necessary move DC.col into a pointer and use
dinamic memory.

Since the color definition is not used to much is not a bad idea
use realloc each time. It means the color definition arry will
increase its size until user resets the terminal.

If this sequence is used a lot we should check if the color
is already defined and look for a way ef releasing colors
not used (and maybe a better allocation scheme).
---
 st.c | 124 +++++++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 84 insertions(+), 40 deletions(-)
diff --git a/st.c b/st.c
index 947373f..3f693d9 100644
--- a/st.c
+++ b/st.c
_AT_@ -306,7 +306,7 @@ typedef struct {
 
 /* Drawing Context */
 typedef struct {
-	Colour col[LEN(colorname) < 256 ? 256 : LEN(colorname)];
+	Colour *col;
 	Font font, bfont, ifont, ibfont;
 	GC gc;
 } DC;
_AT_@ -354,7 +354,7 @@ static void tsetdirtattr(int);
 static void tsetmode(bool, bool, int *, int);
 static void tfulldirt(void);
 static void techo(char *, int);
-
+static int tdefcolor(int *, int *, int);
 static inline bool match(uint, uint);
 static void ttynew(void);
 static void ttyread(void);
_AT_@ -366,6 +366,8 @@ static void xhints(void);
 static void xclear(int, int, int, int);
 static void xdrawcursor(void);
 static void xinit(void);
+
+static int xnewcolor(uint, uint, uint);
 static void xloadcols(void);
 static int xsetcolorname(int, const char *);
 static int xloadfont(Font *, FcPattern *);
_AT_@ -451,6 +453,7 @@ static int oldbutton = 3; /* button event on startup: 3 = release */
 
 static char *usedfont = NULL;
 static int usedfontsize = 0;
+static size_t numcolours;
 
 /* Font Ring Cache */
 enum {
_AT_@ -1618,9 +1621,57 @@ tdeleteline(int n) {
 	tscrollup(term.c.y, n);
 }
 
+int
+tdefcolor(int *attr, int *npar, int l) {
+	int idx = -1;
+	uint r, g, b;
+
+	switch (attr[*npar + 1]) {
+	case 2: /* direct colour in RGB space */
+		if (*npar + 4 >= l) {
+			fprintf(stderr,
+				"erresc(38): Incorrect number of parameters (%d)\n",
+				*npar);
+			break;
+		}
+		r = attr[*npar + 2];
+		g = attr[*npar + 3];
+		b = attr[*npar + 4];
+		*npar += 4;
+		if(!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255))
+			fprintf(stderr, "erresc: bad rgb color (%d,%d,%d)\n",
+				r, g, b);
+		else
+			idx = xnewcolor(r, g, b);
+		break;
+	case 5: /* indexed colour */
+		if (*npar + 2 >= l) {
+			fprintf(stderr,
+				"erresc(38): Incorrect number of parameters (%d)\n",
+				*npar);
+			break;
+		}
+		*npar += 2;
+		if(!BETWEEN(attr[*npar], 0, 255))
+			fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]);
+		else
+			idx = attr[*npar];
+		break;
+	case 0: /* implemented defined (only foreground) */
+	case 1: /* transparent */
+	case 3: /* direct colour in CMY space */
+	case 4: /* direct colour in CMYK space */
+	default:
+		fprintf(stderr,
+		        "erresc(38): gfx attr %d unknown\n", attr[*npar]);
+	}
+
+	return idx;
+}
+
 void
 tsetattr(int *attr, int l) {
-	int i;
+	int i, idx;
 
 	for(i = 0; i < l; i++) {
 		switch(attr[i]) {
_AT_@ -1665,39 +1716,15 @@ tsetattr(int *attr, int l) {
 			term.c.attr.mode &= ~ATTR_REVERSE;
 			break;
 		case 38:
-			if(i + 2 < l && attr[i + 1] == 5) {
-				i += 2;
-				if(BETWEEN(attr[i], 0, 255)) {
-					term.c.attr.fg = attr[i];
-				} else {
-					fprintf(stderr,
-						"erresc: bad fgcolor %d\n",
-						attr[i]);
-				}
-			} else {
-				fprintf(stderr,
-					"erresc(38): gfx attr %d unknown\n",
-					attr[i]);
-			}
+			if ((idx = tdefcolor(attr, &i, l)) >= 0)
+				term.c.attr.fg = idx;
 			break;
 		case 39:
 			term.c.attr.fg = defaultfg;
 			break;
 		case 48:
-			if(i + 2 < l && attr[i + 1] == 5) {
-				i += 2;
-				if(BETWEEN(attr[i], 0, 255)) {
-					term.c.attr.bg = attr[i];
-				} else {
-					fprintf(stderr,
-						"erresc: bad bgcolor %d\n",
-						attr[i]);
-				}
-			} else {
-				fprintf(stderr,
-					"erresc(48): gfx attr %d unknown\n",
-					attr[i]);
-			}
+			if ((idx = tdefcolor(attr, &i, l)) >= 0)
+				term.c.attr.bg = idx;
 			break;
 		case 49:
 			term.c.attr.bg = defaultbg;
_AT_@ -2396,6 +2423,7 @@ tputc(char *c, int len) {
 				treset();
 				term.esc = 0;
 				xresettitle();
+				xloadcols();
 				break;
 			case '=': /* DECPAM -- Application keypad */
 				term.mode |= MODE_APPKEYPAD;
_AT_@ -2553,41 +2581,57 @@ sixd_to_16bit(int x) {
 	return x == 0 ? 0 : 0x3737 + 0x2828 * x;
 }
 
+int
+xnewcolor(uint r, uint g, uint b) {
+	XRenderColor color = { .alpha = 0xffff };
+
+	dc.col = xrealloc(dc.col, (numcolours+1) * sizeof(*dc.col));
+	color.red = r << 8;
+	color.green = g << 8;
+	color.blue = b << 8;
+	if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[numcolours]))
+		die("Could not allocate color %d\n", numcolours);
+	return numcolours++;
+}
+
 void
 xloadcols(void) {
 	int i, r, g, b;
 	XRenderColor color = { .alpha = 0xffff };
+	Colour *cp;
+
+	for (cp = dc.col; cp < dc.col + numcolours; ++cp)
+		XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
+
+	free(dc.col);
+	numcolours = LEN(colorname) < 256 ? 256 : LEN(colorname);
+	dc.col = xmalloc(numcolours * sizeof(*dc.col));
 
 	/* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */
 	for(i = 0; i < LEN(colorname); i++) {
 		if(!colorname[i])
 			continue;
-		if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.col[i])) {
+		if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.col[i]))
 			die("Could not allocate color '%s'\n", colorname[i]);
-		}
 	}
 
 	/* load colors [16-255] ; same colors as xterm */
 	for(i = 16, r = 0; r < 6; r++) {
 		for(g = 0; g < 6; g++) {
-			for(b = 0; b < 6; b++) {
+			for(b = 0; b < 6; b++, i++) {
 				color.red = sixd_to_16bit(r);
 				color.green = sixd_to_16bit(g);
 				color.blue = sixd_to_16bit(b);
-				if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i])) {
+				if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i]))
 					die("Could not allocate color %d\n", i);
-				}
-				i++;
 			}
 		}
 	}
 
 	for(r = 0; r < 24; r++, i++) {
 		color.red = color.green = color.blue = 0x0808 + 0x0a0a * r;
-		if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color,
-					&dc.col[i])) {
+		if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i]))
 			die("Could not allocate color %d\n", i);
-		}
 	}
 }
 
-- 
1.8.3.2
Received on Fri Jul 19 2013 - 20:51:33 CEST

This archive was generated by hypermail 2.3.0 : Fri Jul 19 2013 - 21:00:06 CEST