aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2011-01-08 00:48:54 +0000
committerNicholas Marriott <nicm@openbsd.org>2011-01-08 00:48:54 +0000
commit703160b5d6b64e45a684894260693c60b5524d51 (patch)
treec0b268e884da23938b84209499945432f542f6f7
parent64f02dab7cab4848a00da4aca39dd307b1ce792c (diff)
downloadrtmux-703160b5d6b64e45a684894260693c60b5524d51.tar.gz
rtmux-703160b5d6b64e45a684894260693c60b5524d51.tar.bz2
rtmux-703160b5d6b64e45a684894260693c60b5524d51.zip
Accept colours of the hex form #ffffff and translate to the nearest from
the xterm(1) 256-colour set.
-rw-r--r--Makefile4
-rw-r--r--colour.c119
-rw-r--r--tmux.17
3 files changed, 124 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index 4c48ccdb..c103d766 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,7 @@ CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CDIAGFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
-LDADD= -lutil -lcurses -levent
-DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT}
+LDADD= -lutil -lcurses -levent -lm
+DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT} ${LIBM}
.include <bsd.prog.mk>
diff --git a/colour.c b/colour.c
index 5e31f815..3530686a 100644
--- a/colour.c
+++ b/colour.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <ctype.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -28,6 +30,101 @@
* of the 256 colour palette.
*/
+/* An RGB colour. */
+struct colour_rgb {
+ u_char r;
+ u_char g;
+ u_char b;
+};
+
+/* 256 colour RGB table, generated on first use. */
+struct colour_rgb *colour_rgb_256;
+
+void colour_rgb_generate256(void);
+double colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
+int colour_rgb_find(struct colour_rgb *);
+
+/* Generate 256 colour RGB table. */
+void
+colour_rgb_generate256(void)
+{
+ struct colour_rgb *rgb;
+ u_int i, r, g, b;
+
+ /*
+ * Allocate the table. The first 16 colours are often changed by users
+ * and terminals so don't include them.
+ */
+ colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);
+
+ /* Add the colours first. */
+ r = g = b = 0;
+ for (i = 240; i > 24; i--) {
+ rgb = &colour_rgb_256[240 - i];
+
+ if (r != 0)
+ rgb->r = (r * 40) + 55;
+ if (g != 0)
+ rgb->g = (g * 40) + 55;
+ if (b != 0)
+ rgb->b = (b * 40) + 55;
+
+ b++;
+ if (b > 5) {
+ b = 0;
+ g++;
+ }
+ if (g > 5) {
+ g = 0;
+ r++;
+ }
+ }
+
+ /* Then add the greys. */
+ for (i = 24; i > 0; i--) {
+ rgb = &colour_rgb_256[240 - i];
+
+ rgb->r = 8 + (24 - i) * 10;
+ rgb->g = 8 + (24 - i) * 10;
+ rgb->b = 8 + (24 - i) * 10;
+ }
+}
+
+/* Get colour RGB distance. */
+double
+colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
+{
+ int r, g, b;
+
+ r = rgb1->r - rgb2->r;
+ g = rgb1->g - rgb2->g;
+ b = rgb1->b - rgb2->b;
+ return (sqrt(r * r + g * g + b * b));
+}
+
+/* Work out the nearest colour from the 256 colour set. */
+int
+colour_rgb_find(struct colour_rgb *rgb)
+{
+ double distance, lowest;
+ u_int colour, i;
+
+ if (colour_rgb_256 == NULL)
+ colour_rgb_generate256();
+
+ colour = 16;
+ lowest = INFINITY;
+ for (i = 0; i < 240; i++) {
+ distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
+ if (distance < lowest) {
+ lowest = distance;
+ colour = 16 + i;
+ }
+ }
+ return (colour);
+}
+
+/* Set grid cell foreground colour. */
void
colour_set_fg(struct grid_cell *gc, int c)
{
@@ -36,6 +133,7 @@ colour_set_fg(struct grid_cell *gc, int c)
gc->fg = c;
}
+/* Set grid cell background colour. */
void
colour_set_bg(struct grid_cell *gc, int c)
{
@@ -44,6 +142,7 @@ colour_set_bg(struct grid_cell *gc, int c)
gc->bg = c;
}
+/* Convert colour to a string. */
const char *
colour_tostring(int c)
{
@@ -77,11 +176,25 @@ colour_tostring(int c)
return (NULL);
}
+/* Convert colour from string. */
int
colour_fromstring(const char *s)
{
- const char *errstr;
- int n;
+ const char *errstr;
+ const char *cp;
+ struct colour_rgb rgb;
+ int n;
+
+ if (*s == '#' && strlen(s) == 7) {
+ for (cp = s + 1; isxdigit((u_char) *cp); cp++)
+ ;
+ if (*cp != '\0')
+ return (-1);
+ n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b);
+ if (n != 3)
+ return (-1);
+ return (colour_rgb_find(&rgb) | 0x100);
+ }
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
@@ -111,6 +224,7 @@ colour_fromstring(const char *s)
return (-1);
}
+/* Convert 256 colour palette to 16. */
u_char
colour_256to16(u_char c)
{
@@ -136,6 +250,7 @@ colour_256to16(u_char c)
return (table[c]);
}
+/* Convert 256 colour palette to 88. */
u_char
colour_256to88(u_char c)
{
diff --git a/tmux.1 b/tmux.1
index 64ca5ed3..95ebfb45 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1793,8 +1793,11 @@ is one of:
.Ic colour0
to
.Ic colour255
-from the 256-colour palette, or
-.Ic default .
+from the 256-colour set,
+.Ic default ,
+or a hexadecimal RGB string such as
+.Ql #ffffff ,
+which chooses the closest match from the default 256-colour set.
.It Ic message-fg Ar colour
Set status line message foreground colour.
.It Ic message-limit Ar number