mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Handle the RGB colour escape sequence (\033[38;2;<r>;<g>;<b>m and 48;2)
like xterm(1) does, by mapping to the nearest in the 256 colour palette.
This commit is contained in:
		
							
								
								
									
										26
									
								
								colour.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								colour.c
									
									
									
									
									
								
							@@ -281,12 +281,11 @@ const struct colour_rgb colour_to_256[] = {
 | 
			
		||||
	{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int	colour_rgb_cmp(const void *, const void *);
 | 
			
		||||
int	colour_rgb_find(struct colour_rgb *);
 | 
			
		||||
int	colour_cmp_rgb(const void *, const void *);
 | 
			
		||||
 | 
			
		||||
/* Compare function for bsearch(). */
 | 
			
		||||
int
 | 
			
		||||
colour_rgb_cmp(const void *lhs0, const void *rhs0)
 | 
			
		||||
colour_cmp_rgb(const void *lhs0, const void *rhs0)
 | 
			
		||||
{
 | 
			
		||||
	const struct colour_rgb *lhs = lhs0, *rhs = rhs0;
 | 
			
		||||
 | 
			
		||||
@@ -310,23 +309,22 @@ colour_rgb_cmp(const void *lhs0, const void *rhs0)
 | 
			
		||||
 | 
			
		||||
/* Work out the nearest colour from the 256 colour set. */
 | 
			
		||||
int
 | 
			
		||||
colour_rgb_find(struct colour_rgb *rgb)
 | 
			
		||||
colour_find_rgb(u_char r, u_char g, u_char b)
 | 
			
		||||
{
 | 
			
		||||
	struct colour_rgb	*found;
 | 
			
		||||
	struct colour_rgb	rgb = { .r = r, .g = g, .b = b }, *found;
 | 
			
		||||
	u_int			distance, lowest, colour, i;
 | 
			
		||||
	int			 r, g, b;
 | 
			
		||||
 | 
			
		||||
	found = bsearch(rgb, colour_to_256, nitems(colour_to_256),
 | 
			
		||||
	    sizeof colour_to_256[0], colour_rgb_cmp);
 | 
			
		||||
	found = bsearch(&rgb, colour_to_256, nitems(colour_to_256),
 | 
			
		||||
	    sizeof colour_to_256[0], colour_cmp_rgb);
 | 
			
		||||
	if (found != NULL)
 | 
			
		||||
		return (16 + found->i);
 | 
			
		||||
 | 
			
		||||
	colour = 16;
 | 
			
		||||
	lowest = UINT_MAX;
 | 
			
		||||
	for (i = 0; i < 240; i++) {
 | 
			
		||||
		r = colour_from_256[i].r - rgb->r;
 | 
			
		||||
		g = colour_from_256[i].g - rgb->g;
 | 
			
		||||
		b = colour_from_256[i].b - rgb->b;
 | 
			
		||||
		r = colour_from_256[i].r - rgb.r;
 | 
			
		||||
		g = colour_from_256[i].g - rgb.g;
 | 
			
		||||
		b = colour_from_256[i].b - rgb.b;
 | 
			
		||||
 | 
			
		||||
		distance = r * r + g * g + b * b;
 | 
			
		||||
		if (distance < lowest) {
 | 
			
		||||
@@ -411,18 +409,18 @@ colour_fromstring(const char *s)
 | 
			
		||||
{
 | 
			
		||||
	const char	*errstr;
 | 
			
		||||
	const char	*cp;
 | 
			
		||||
	struct colour_rgb	 rgb;
 | 
			
		||||
	int		 n;
 | 
			
		||||
	u_char		 r, g, b;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
 | 
			
		||||
		if (n != 3)
 | 
			
		||||
			return (-1);
 | 
			
		||||
		return (colour_rgb_find(&rgb) | 0x100);
 | 
			
		||||
		return (colour_find_rgb(r, g, b) | 0x100);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										91
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								input.c
									
									
									
									
									
								
							@@ -126,6 +126,8 @@ void	input_csi_dispatch_rm_private(struct input_ctx *);
 | 
			
		||||
void	input_csi_dispatch_sm(struct input_ctx *);
 | 
			
		||||
void	input_csi_dispatch_sm_private(struct input_ctx *);
 | 
			
		||||
void	input_csi_dispatch_winops(struct input_ctx *);
 | 
			
		||||
void	input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
 | 
			
		||||
void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
 | 
			
		||||
void	input_csi_dispatch_sgr(struct input_ctx *);
 | 
			
		||||
int	input_dcs_dispatch(struct input_ctx *);
 | 
			
		||||
int	input_utf8_open(struct input_ctx *);
 | 
			
		||||
@@ -1609,13 +1611,71 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle CSI SGR for 256 colours. */
 | 
			
		||||
void
 | 
			
		||||
input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*gc = &ictx->cell.cell;
 | 
			
		||||
	int			 c;
 | 
			
		||||
 | 
			
		||||
	(*i)++;
 | 
			
		||||
	c = input_get(ictx, *i, 0, -1);
 | 
			
		||||
	if (c == -1) {
 | 
			
		||||
		if (fgbg == 38) {
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
			gc->fg = 8;
 | 
			
		||||
		} else if (fgbg == 48) {
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
			gc->bg = 8;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (fgbg == 38) {
 | 
			
		||||
			gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
			gc->fg = c;
 | 
			
		||||
		} else if (fgbg == 48) {
 | 
			
		||||
			gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
			gc->bg = c;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle CSI SGR for RGB colours. */
 | 
			
		||||
void
 | 
			
		||||
input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*gc = &ictx->cell.cell;
 | 
			
		||||
	int			 c, r, g, b;
 | 
			
		||||
 | 
			
		||||
	(*i)++;
 | 
			
		||||
	r = input_get(ictx, *i, 0, -1);
 | 
			
		||||
	if (r == -1 || r > 255)
 | 
			
		||||
		return;
 | 
			
		||||
	(*i)++;
 | 
			
		||||
	g = input_get(ictx, *i, 0, -1);
 | 
			
		||||
	if (g == -1 || g > 255)
 | 
			
		||||
		return;
 | 
			
		||||
	(*i)++;
 | 
			
		||||
	b = input_get(ictx, *i, 0, -1);
 | 
			
		||||
	if (b == -1 || b > 255)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	c = colour_find_rgb(r, g, b);
 | 
			
		||||
	if (fgbg == 38) {
 | 
			
		||||
		gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
		gc->fg = c;
 | 
			
		||||
	} else if (fgbg == 48) {
 | 
			
		||||
		gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
		gc->bg = c;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle CSI SGR. */
 | 
			
		||||
void
 | 
			
		||||
input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*gc = &ictx->cell.cell;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
	int			 n, m;
 | 
			
		||||
	int			 n;
 | 
			
		||||
 | 
			
		||||
	if (ictx->param_list_len == 0) {
 | 
			
		||||
		memcpy(gc, &grid_default_cell, sizeof *gc);
 | 
			
		||||
@@ -1627,28 +1687,13 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
 | 
			
		||||
		if (n == 38 || n == 48) {
 | 
			
		||||
			i++;
 | 
			
		||||
			if (input_get(ictx, i, 0, -1) != 5)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			i++;
 | 
			
		||||
			m = input_get(ictx, i, 0, -1);
 | 
			
		||||
			if (m == -1) {
 | 
			
		||||
				if (n == 38) {
 | 
			
		||||
					gc->flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
					gc->fg = 8;
 | 
			
		||||
				} else if (n == 48) {
 | 
			
		||||
					gc->flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
					gc->bg = 8;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			} else {
 | 
			
		||||
				if (n == 38) {
 | 
			
		||||
					gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
					gc->fg = m;
 | 
			
		||||
				} else if (n == 48) {
 | 
			
		||||
					gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
					gc->bg = m;
 | 
			
		||||
				}
 | 
			
		||||
			switch (input_get(ictx, i, 0, -1)) {
 | 
			
		||||
			case 2:
 | 
			
		||||
				input_csi_dispatch_sgr_rgb(ictx, n, &i);
 | 
			
		||||
				break;
 | 
			
		||||
			case 5:
 | 
			
		||||
				input_csi_dispatch_sgr_256(ictx, n, &i);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1953,6 +1953,7 @@ char	*xterm_keys_lookup(int);
 | 
			
		||||
int	 xterm_keys_find(const char *, size_t, size_t *, int *);
 | 
			
		||||
 | 
			
		||||
/* colour.c */
 | 
			
		||||
int	 colour_find_rgb(u_char, u_char, u_char);
 | 
			
		||||
void	 colour_set_fg(struct grid_cell *, int);
 | 
			
		||||
void	 colour_set_bg(struct grid_cell *, int);
 | 
			
		||||
const char *colour_tostring(int);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user