rcfile: support #rgb format for specifying colors in 256-color terminals

Most terminal emulators support a palette of 216 indexed colors:
the 6x6x6 color cube pioneered by Xterm.  But as an index gives
little indication about what kind of color it produces, allow the
user to specify the color with three hex digits instead, one for
the level of red, green, and blue each, in the format #rgb.

One hex digit allows for sixteen values, but as there are only
six levels available, only 0, 4, 8, a, c, and e are significant
-- other values get reduced to the nearest lower one.

This fulfills https://savannah.gnu.org/bugs/?56445.
Requested-by: Peter Liscovius, Erik Lundin, Owen Maresh, Dave Lemonby

Signed-off-by: Brad Town <brad@bradtown.com>
This commit is contained in:
Brad Town 2021-11-14 10:04:51 -08:00 committed by Benno Schulenberg
parent 0941185fcf
commit 8d6b468cdc
1 changed files with 25 additions and 0 deletions

View File

@ -990,6 +990,19 @@ void parse_includes(char *ptr)
free(expanded);
}
/* Return the index of the color that is closest to the given RGB levels,
* assuming that the terminal uses the 6x6x6 color cube of xterm-256color. */
short closest_index_color(short r, short g, short b)
{
if (COLORS != 256)
return THE_DEFAULT;
/* Translation table, from 16 intended levels to 6 available levels. */
static const short level[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
return (36 * level[r] + 6 * level[g] + level[b] + 16);
}
#define COLORCOUNT 20
const char hues[COLORCOUNT][8] = { "red", "green", "blue",
@ -1024,6 +1037,18 @@ short color_to_short(const char *colorname, bool *vivid, bool *thick)
*thick = FALSE;
}
if (colorname[0] == '#' && strlen(colorname) == 4) {
unsigned short r, g, b;
if (*vivid) {
jot_error(N_("Color '%s' takes no prefix"), colorname);
return BAD_COLOR;
}
if (sscanf(colorname, "#%1hX%1hX%1hX", &r, &g, &b) == 3)
return closest_index_color(r, g, b);
}
for (int index = 0; index < COLORCOUNT; index++)
if (strcmp(colorname, hues[index]) == 0) {
if (index > 7 && *vivid) {