mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		
							
								
								
									
										41
									
								
								colour.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								colour.c
									
									
									
									
									
								
							@@ -67,7 +67,7 @@ colour_find_rgb(u_char r, u_char g, u_char b)
 | 
			
		||||
 | 
			
		||||
	/* If we have hit the colour exactly, return early. */
 | 
			
		||||
	if (cr == r && cg == g && cb == b)
 | 
			
		||||
		return (16 + (36 * qr) + (6 * qg) + qb);
 | 
			
		||||
		return ((16 + (36 * qr) + (6 * qg) + qb) | COLOUR_FLAG_256);
 | 
			
		||||
 | 
			
		||||
	/* Work out the closest grey (average of RGB). */
 | 
			
		||||
	grey_avg = (r + g + b) / 3;
 | 
			
		||||
@@ -83,25 +83,25 @@ colour_find_rgb(u_char r, u_char g, u_char b)
 | 
			
		||||
		idx = 232 + grey_idx;
 | 
			
		||||
	else
 | 
			
		||||
		idx = 16 + (36 * qr) + (6 * qg) + qb;
 | 
			
		||||
	return (idx);
 | 
			
		||||
	return (idx | COLOUR_FLAG_256);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set grid cell foreground colour. */
 | 
			
		||||
void
 | 
			
		||||
colour_set_fg(struct grid_cell *gc, int c)
 | 
			
		||||
/* Join RGB into a colour. */
 | 
			
		||||
int
 | 
			
		||||
colour_join_rgb(u_char r, u_char g, u_char b)
 | 
			
		||||
{
 | 
			
		||||
	if (c & 0x100)
 | 
			
		||||
		gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
	gc->fg = c;
 | 
			
		||||
	return ((((int)((r) & 0xff)) << 16) |
 | 
			
		||||
	    (((int)((g) & 0xff)) << 8) |
 | 
			
		||||
	    (((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set grid cell background colour. */
 | 
			
		||||
/* Split colour into RGB. */
 | 
			
		||||
void
 | 
			
		||||
colour_set_bg(struct grid_cell *gc, int c)
 | 
			
		||||
colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
 | 
			
		||||
{
 | 
			
		||||
	if (c & 0x100)
 | 
			
		||||
		gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
	gc->bg = c;
 | 
			
		||||
	*r = (c >> 16) & 0xff;
 | 
			
		||||
	*g = (c >> 8) & 0xff;
 | 
			
		||||
	*b = c & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert colour to a string. */
 | 
			
		||||
@@ -109,9 +109,16 @@ const char *
 | 
			
		||||
colour_tostring(int c)
 | 
			
		||||
{
 | 
			
		||||
	static char	s[32];
 | 
			
		||||
	u_char		r, g, b;
 | 
			
		||||
 | 
			
		||||
	if (c & 0x100) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "colour%d", c & ~0x100);
 | 
			
		||||
	if (c & COLOUR_FLAG_RGB) {
 | 
			
		||||
		colour_split_rgb(c, &r, &g, &b);
 | 
			
		||||
		xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
 | 
			
		||||
		return (s);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (c & COLOUR_FLAG_256) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "colour%u", c & 0xff);
 | 
			
		||||
		return (s);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -171,14 +178,14 @@ colour_fromstring(const char *s)
 | 
			
		||||
		n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
 | 
			
		||||
		if (n != 3)
 | 
			
		||||
			return (-1);
 | 
			
		||||
		return (colour_find_rgb(r, g, b) | 0x100);
 | 
			
		||||
		return (colour_join_rgb(r, g, b));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
 | 
			
		||||
		n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
 | 
			
		||||
		if (errstr != NULL)
 | 
			
		||||
			return (-1);
 | 
			
		||||
		return (n | 0x100);
 | 
			
		||||
		return (n | COLOUR_FLAG_256);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								grid.c
									
									
									
									
									
								
							@@ -37,14 +37,12 @@
 | 
			
		||||
 | 
			
		||||
/* Default grid cell data. */
 | 
			
		||||
const struct grid_cell grid_default_cell = {
 | 
			
		||||
	0, 0, { .fg = 8 }, { .bg = 8 }, { { ' ' }, 0, 1, 1 }
 | 
			
		||||
	0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
 | 
			
		||||
};
 | 
			
		||||
const struct grid_cell_entry grid_default_entry = {
 | 
			
		||||
	0, { .data = { 0, 8, 8, ' ' } }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int	grid_check_y(struct grid *, u_int);
 | 
			
		||||
 | 
			
		||||
void	grid_reflow_copy(struct grid_line *, u_int, struct grid_line *l,
 | 
			
		||||
	    u_int, u_int);
 | 
			
		||||
void	grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
 | 
			
		||||
@@ -64,7 +62,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check grid y position. */
 | 
			
		||||
int
 | 
			
		||||
static int
 | 
			
		||||
grid_check_y(struct grid *gd, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	if ((py) >= (gd)->hsize + (gd)->sy) {
 | 
			
		||||
@@ -74,6 +72,21 @@ grid_check_y(struct grid *gd, u_int py)
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Compare grid cells. Return 1 if equal, 0 if not. */
 | 
			
		||||
int
 | 
			
		||||
grid_cells_equal(const struct grid_cell *gca, const struct grid_cell *gcb)
 | 
			
		||||
{
 | 
			
		||||
	if (gca->fg != gcb->fg || gca->bg != gcb->bg)
 | 
			
		||||
		return (0);
 | 
			
		||||
	if (gca->attr != gcb->attr || gca->flags != gcb->flags)
 | 
			
		||||
		return (0);
 | 
			
		||||
	if (gca->data.width != gcb->data.width)
 | 
			
		||||
		return (0);
 | 
			
		||||
	if (gca->data.size != gcb->data.size)
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create a new grid. */
 | 
			
		||||
struct grid *
 | 
			
		||||
grid_create(u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
@@ -131,7 +144,7 @@ grid_compare(struct grid *ga, struct grid *gb)
 | 
			
		||||
		for (xx = 0; xx < gla->cellsize; xx++) {
 | 
			
		||||
			grid_get_cell(ga, xx, yy, &gca);
 | 
			
		||||
			grid_get_cell(gb, xx, yy, &gcb);
 | 
			
		||||
			if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0)
 | 
			
		||||
			if (!grid_cells_equal(&gca, &gcb))
 | 
			
		||||
				return (1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -270,10 +283,14 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
 | 
			
		||||
	gc->flags = gce->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
	gc->attr = gce->data.attr;
 | 
			
		||||
	gc->fg = gce->data.fg;
 | 
			
		||||
	if (gce->flags & GRID_FLAG_FG256)
 | 
			
		||||
		gc->fg |= COLOUR_FLAG_256;
 | 
			
		||||
	gc->bg = gce->data.bg;
 | 
			
		||||
	if (gce->flags & GRID_FLAG_BG256)
 | 
			
		||||
		gc->bg |= COLOUR_FLAG_256;
 | 
			
		||||
	utf8_set(&gc->data, gce->data.data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -297,9 +314,12 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
 | 
			
		||||
	extended = (gce->flags & GRID_FLAG_EXTENDED);
 | 
			
		||||
	if (!extended && (gc->data.size != 1 || gc->data.width != 1))
 | 
			
		||||
		extended = 1;
 | 
			
		||||
	if (!extended && (gc->flags & (GRID_FLAG_FGRGB|GRID_FLAG_BGRGB)))
 | 
			
		||||
	if (!extended && ((gc->fg & COLOUR_FLAG_RGB) ||
 | 
			
		||||
	    (gc->bg & COLOUR_FLAG_RGB)))
 | 
			
		||||
		extended = 1;
 | 
			
		||||
	if (extended) {
 | 
			
		||||
		gl->flags |= GRID_LINE_EXTENDED;
 | 
			
		||||
 | 
			
		||||
		if (~gce->flags & GRID_FLAG_EXTENDED) {
 | 
			
		||||
			gl->extddata = xreallocarray(gl->extddata,
 | 
			
		||||
			    gl->extdsize + 1, sizeof *gl->extddata);
 | 
			
		||||
@@ -314,10 +334,14 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
 | 
			
		||||
	gce->flags = gc->flags;
 | 
			
		||||
	gce->data.attr = gc->attr;
 | 
			
		||||
	gce->data.fg = gc->fg;
 | 
			
		||||
	gce->data.bg = gc->bg;
 | 
			
		||||
	gce->data.fg = gc->fg & 0xff;
 | 
			
		||||
	if (gc->fg & COLOUR_FLAG_256)
 | 
			
		||||
		gce->flags |= GRID_FLAG_FG256;
 | 
			
		||||
	gce->data.bg = gc->bg & 0xff;
 | 
			
		||||
	if (gc->bg & COLOUR_FLAG_256)
 | 
			
		||||
		gce->flags |= GRID_FLAG_BG256;
 | 
			
		||||
	gce->data.data = gc->data.data[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -446,18 +470,20 @@ size_t
 | 
			
		||||
grid_string_cells_fg(const struct grid_cell *gc, int *values)
 | 
			
		||||
{
 | 
			
		||||
	size_t	n;
 | 
			
		||||
	u_char	r, g, b;
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FG256) {
 | 
			
		||||
	if (gc->fg & COLOUR_FLAG_256) {
 | 
			
		||||
		values[n++] = 38;
 | 
			
		||||
		values[n++] = 5;
 | 
			
		||||
		values[n++] = gc->fg;
 | 
			
		||||
	} else if (gc->flags & GRID_FLAG_FGRGB) {
 | 
			
		||||
		values[n++] = gc->fg & 0xff;
 | 
			
		||||
	} else if (gc->fg & COLOUR_FLAG_RGB) {
 | 
			
		||||
		values[n++] = 38;
 | 
			
		||||
		values[n++] = 2;
 | 
			
		||||
		values[n++] = gc->fg_rgb.r;
 | 
			
		||||
		values[n++] = gc->fg_rgb.g;
 | 
			
		||||
		values[n++] = gc->fg_rgb.b;
 | 
			
		||||
		colour_split_rgb(gc->fg, &r, &g, &b);
 | 
			
		||||
		values[n++] = r;
 | 
			
		||||
		values[n++] = g;
 | 
			
		||||
		values[n++] = b;
 | 
			
		||||
	} else {
 | 
			
		||||
		switch (gc->fg) {
 | 
			
		||||
		case 0:
 | 
			
		||||
@@ -493,18 +519,20 @@ size_t
 | 
			
		||||
grid_string_cells_bg(const struct grid_cell *gc, int *values)
 | 
			
		||||
{
 | 
			
		||||
	size_t	n;
 | 
			
		||||
	u_char	r, g, b;
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BG256) {
 | 
			
		||||
	if (gc->bg & COLOUR_FLAG_256) {
 | 
			
		||||
		values[n++] = 48;
 | 
			
		||||
		values[n++] = 5;
 | 
			
		||||
		values[n++] = gc->bg;
 | 
			
		||||
	} else if (gc->flags & GRID_FLAG_BGRGB) {
 | 
			
		||||
		values[n++] = gc->bg & 0xff;
 | 
			
		||||
	} else if (gc->bg & COLOUR_FLAG_RGB) {
 | 
			
		||||
		values[n++] = 48;
 | 
			
		||||
		values[n++] = 2;
 | 
			
		||||
		values[n++] = gc->bg_rgb.r;
 | 
			
		||||
		values[n++] = gc->bg_rgb.g;
 | 
			
		||||
		values[n++] = gc->bg_rgb.b;
 | 
			
		||||
		colour_split_rgb(gc->bg, &r, &g, &b);
 | 
			
		||||
		values[n++] = r;
 | 
			
		||||
		values[n++] = g;
 | 
			
		||||
		values[n++] = b;
 | 
			
		||||
	} else {
 | 
			
		||||
		switch (gc->bg) {
 | 
			
		||||
		case 0:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								input.c
									
									
									
									
									
								
							@@ -1628,23 +1628,15 @@ input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
 | 
			
		||||
	(*i)++;
 | 
			
		||||
	c = input_get(ictx, *i, 0, -1);
 | 
			
		||||
	if (c == -1) {
 | 
			
		||||
		if (fgbg == 38) {
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
		if (fgbg == 38)
 | 
			
		||||
			gc->fg = 8;
 | 
			
		||||
		} else if (fgbg == 48) {
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
 | 
			
		||||
		else if (fgbg == 48)
 | 
			
		||||
			gc->bg = 8;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (fgbg == 38) {
 | 
			
		||||
			gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_FGRGB;
 | 
			
		||||
			gc->fg = c;
 | 
			
		||||
		} else if (fgbg == 48) {
 | 
			
		||||
			gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_BGRGB;
 | 
			
		||||
			gc->bg = c;
 | 
			
		||||
		}
 | 
			
		||||
		if (fgbg == 38)
 | 
			
		||||
			gc->fg = c | COLOUR_FLAG_256;
 | 
			
		||||
		else if (fgbg == 48)
 | 
			
		||||
			gc->bg = c | COLOUR_FLAG_256;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1668,19 +1660,10 @@ input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
 | 
			
		||||
	if (b == -1 || b > 255)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (fgbg == 38) {
 | 
			
		||||
		gc->flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
		gc->flags |= GRID_FLAG_FGRGB;
 | 
			
		||||
		gc->fg_rgb.r = r;
 | 
			
		||||
		gc->fg_rgb.g = g;
 | 
			
		||||
		gc->fg_rgb.b = b;
 | 
			
		||||
	} else if (fgbg == 48) {
 | 
			
		||||
		gc->flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
		gc->flags |= GRID_FLAG_BGRGB;
 | 
			
		||||
		gc->bg_rgb.r = r;
 | 
			
		||||
		gc->bg_rgb.g = g;
 | 
			
		||||
		gc->bg_rgb.b = b;
 | 
			
		||||
	}
 | 
			
		||||
	if (fgbg == 38)
 | 
			
		||||
		gc->fg = colour_join_rgb(r, g, b);
 | 
			
		||||
	else if (fgbg == 48)
 | 
			
		||||
		gc->bg = colour_join_rgb(r, g, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle CSI SGR. */
 | 
			
		||||
@@ -1761,11 +1744,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
		case 35:
 | 
			
		||||
		case 36:
 | 
			
		||||
		case 37:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
			gc->fg = n - 30;
 | 
			
		||||
			break;
 | 
			
		||||
		case 39:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
			gc->fg = 8;
 | 
			
		||||
			break;
 | 
			
		||||
		case 40:
 | 
			
		||||
@@ -1776,11 +1757,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
		case 45:
 | 
			
		||||
		case 46:
 | 
			
		||||
		case 47:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
 | 
			
		||||
			gc->bg = n - 40;
 | 
			
		||||
			break;
 | 
			
		||||
		case 49:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
 | 
			
		||||
			gc->bg = 8;
 | 
			
		||||
			break;
 | 
			
		||||
		case 90:
 | 
			
		||||
@@ -1791,7 +1770,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
		case 95:
 | 
			
		||||
		case 96:
 | 
			
		||||
		case 97:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
			gc->fg = n;
 | 
			
		||||
			break;
 | 
			
		||||
		case 100:
 | 
			
		||||
@@ -1802,7 +1780,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
 | 
			
		||||
		case 105:
 | 
			
		||||
		case 106:
 | 
			
		||||
		case 107:
 | 
			
		||||
			gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
 | 
			
		||||
			gc->bg = n - 10;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -552,9 +552,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
 | 
			
		||||
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	if (w->active == wp)
 | 
			
		||||
		colour_set_bg(&gc, active_colour);
 | 
			
		||||
		gc.bg = active_colour;
 | 
			
		||||
	else
 | 
			
		||||
		colour_set_bg(&gc, colour);
 | 
			
		||||
		gc.bg = colour;
 | 
			
		||||
	tty_attributes(tty, &gc, wp);
 | 
			
		||||
	for (ptr = buf; *ptr != '\0'; ptr++) {
 | 
			
		||||
		if (*ptr < '0' || *ptr > '9')
 | 
			
		||||
@@ -579,9 +579,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
 | 
			
		||||
draw_text:
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	if (w->active == wp)
 | 
			
		||||
		colour_set_fg(&gc, active_colour);
 | 
			
		||||
		gc.fg = active_colour;
 | 
			
		||||
	else
 | 
			
		||||
		colour_set_fg(&gc, colour);
 | 
			
		||||
		gc.fg = colour;
 | 
			
		||||
	tty_attributes(tty, &gc, wp);
 | 
			
		||||
	tty_puts(tty, buf);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										264
									
								
								screen-write.c
									
									
									
									
									
								
							
							
						
						
									
										264
									
								
								screen-write.c
									
									
									
									
									
								
							@@ -27,6 +27,7 @@ static void	screen_write_initctx(struct screen_write_ctx *,
 | 
			
		||||
		    struct tty_ctx *);
 | 
			
		||||
static void	screen_write_save_last(struct screen_write_ctx *,
 | 
			
		||||
		    struct tty_ctx *);
 | 
			
		||||
static void	screen_write_flush(struct screen_write_ctx *);
 | 
			
		||||
 | 
			
		||||
static int	screen_write_overwrite(struct screen_write_ctx *,
 | 
			
		||||
		    struct grid_cell *, u_int);
 | 
			
		||||
@@ -34,25 +35,103 @@ static int	screen_write_combine(struct screen_write_ctx *,
 | 
			
		||||
		    const struct utf8_data *);
 | 
			
		||||
 | 
			
		||||
static const struct grid_cell screen_write_pad_cell = {
 | 
			
		||||
	GRID_FLAG_PADDING, 0, { .fg = 8 }, { .bg = 8 }, { { 0 }, 0, 0, 0 }
 | 
			
		||||
	GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Initialise writing with a window. */
 | 
			
		||||
#define screen_dirty_bit(s, x, y) (((y) * screen_size_x(s)) + (x))
 | 
			
		||||
#define screen_dirty_clear(s, sx, sy, ex, ey)			\
 | 
			
		||||
	do {							\
 | 
			
		||||
		if (s->dirty != NULL) {				\
 | 
			
		||||
			bit_nclear(s->dirty,			\
 | 
			
		||||
			    screen_dirty_bit(s, sx, sy),	\
 | 
			
		||||
			    screen_dirty_bit(s, ex, ey));	\
 | 
			
		||||
		}						\
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/* Initialize writing with a window. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
 | 
			
		||||
    struct screen *s)
 | 
			
		||||
{
 | 
			
		||||
	u_int		 size;
 | 
			
		||||
	char		 tmp[16];
 | 
			
		||||
	const char	*cp = tmp;
 | 
			
		||||
 | 
			
		||||
	ctx->wp = wp;
 | 
			
		||||
	if (wp != NULL && s == NULL)
 | 
			
		||||
		ctx->s = wp->screen;
 | 
			
		||||
	else
 | 
			
		||||
		ctx->s = s;
 | 
			
		||||
 | 
			
		||||
	size = screen_size_x(ctx->s) * screen_size_y(ctx->s);
 | 
			
		||||
	if (ctx->s->dirtysize != size) {
 | 
			
		||||
		free(ctx->s->dirty);
 | 
			
		||||
		ctx->s->dirty = NULL;
 | 
			
		||||
		ctx->s->dirtysize = size;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->dirty = 0;
 | 
			
		||||
 | 
			
		||||
	ctx->cells = ctx->written = ctx->skipped = 0;
 | 
			
		||||
 | 
			
		||||
	if (wp == NULL)
 | 
			
		||||
		cp = "no pane";
 | 
			
		||||
	else
 | 
			
		||||
		snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
 | 
			
		||||
	log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
 | 
			
		||||
	    screen_size_y(ctx->s), cp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Finish writing. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_stop(__unused struct screen_write_ctx *ctx)
 | 
			
		||||
screen_write_stop(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	screen_write_flush(ctx);
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: %u of %u written (dirty %u, skipped %u)", __func__,
 | 
			
		||||
	    ctx->written, ctx->cells, ctx->cells - ctx->written, ctx->skipped);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Flush outstanding cell writes. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_flush(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
	u_int		 x, y, offset, cx, cy, dirty;
 | 
			
		||||
	struct grid_cell gc;
 | 
			
		||||
 | 
			
		||||
	if (ctx->dirty == 0)
 | 
			
		||||
		return;
 | 
			
		||||
	dirty = 0;
 | 
			
		||||
 | 
			
		||||
	cx = s->cx;
 | 
			
		||||
	cy = s->cy;
 | 
			
		||||
 | 
			
		||||
	offset = 0;
 | 
			
		||||
	for (y = 0; y < screen_size_y(s); y++) {
 | 
			
		||||
		for (x = 0; x < screen_size_x(s); x++) {
 | 
			
		||||
			offset++;
 | 
			
		||||
			if (!bit_test(s->dirty, offset - 1))
 | 
			
		||||
				continue;
 | 
			
		||||
			bit_clear(s->dirty, offset - 1);
 | 
			
		||||
 | 
			
		||||
			screen_write_cursormove(ctx, x, y);
 | 
			
		||||
			grid_view_get_cell(s->grid, x, y, &gc);
 | 
			
		||||
 | 
			
		||||
			screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
			ttyctx.cell = &gc;
 | 
			
		||||
			tty_write(tty_cmd_cell, &ttyctx);
 | 
			
		||||
			ctx->written++;
 | 
			
		||||
 | 
			
		||||
			if (++dirty == ctx->dirty)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		if (dirty == ctx->dirty)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s->cx = cx;
 | 
			
		||||
	s->cy = cy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Reset screen state. */
 | 
			
		||||
@@ -382,7 +461,6 @@ screen_write_save_last(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
 | 
			
		||||
		if (~gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	ttyctx->last_width = xx;
 | 
			
		||||
	memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -517,9 +595,12 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
 | 
			
		||||
	struct tty_ctx	 	 ttyctx;
 | 
			
		||||
	struct grid_cell       	 gc;
 | 
			
		||||
	u_int			 xx, yy;
 | 
			
		||||
	u_int		 	 sx = screen_size_x(s), sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);
 | 
			
		||||
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	utf8_set(&gc.data, 'E');
 | 
			
		||||
 | 
			
		||||
@@ -532,7 +613,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
 | 
			
		||||
	s->cy = 0;
 | 
			
		||||
 | 
			
		||||
	s->rupper = 0;
 | 
			
		||||
 | 
			
		||||
	s->rlower = screen_size_y(s) - 1;
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_alignmenttest, &ttyctx);
 | 
			
		||||
@@ -553,6 +633,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
	if (nx == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	screen_write_flush(ctx);
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cx <= screen_size_x(s) - 1)
 | 
			
		||||
@@ -577,6 +658,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
	if (nx == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	screen_write_flush(ctx);
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cx <= screen_size_x(s) - 1)
 | 
			
		||||
@@ -603,8 +685,11 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cx <= screen_size_x(s) - 1)
 | 
			
		||||
	if (s->cx <= screen_size_x(s) - 1) {
 | 
			
		||||
		screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
 | 
			
		||||
	} else
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	ttyctx.num = nx;
 | 
			
		||||
	tty_write(tty_cmd_clearcharacter, &ttyctx);
 | 
			
		||||
@@ -626,6 +711,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
		if (ny == 0)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
		grid_view_insert_lines(s->grid, s->cy, ny);
 | 
			
		||||
@@ -640,6 +726,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
	if (ny == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	screen_write_flush(ctx);
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cy < s->rupper || s->cy > s->rlower)
 | 
			
		||||
@@ -667,6 +754,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
		if (ny == 0)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
		grid_view_delete_lines(s->grid, s->cy, ny);
 | 
			
		||||
@@ -681,6 +769,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
 | 
			
		||||
	if (ny == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	screen_write_flush(ctx);
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cy < s->rupper || s->cy > s->rlower)
 | 
			
		||||
@@ -697,11 +786,18 @@ void
 | 
			
		||||
screen_write_clearline(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct tty_ctx		 ttyctx;
 | 
			
		||||
	u_int			 sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
 | 
			
		||||
	gl = &s->grid->linedata[s->grid->hsize + s->cy];
 | 
			
		||||
	if (gl->cellsize != 0) {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, sx, 1);
 | 
			
		||||
	} else
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_clearline, &ttyctx);
 | 
			
		||||
}
 | 
			
		||||
@@ -711,15 +807,18 @@ void
 | 
			
		||||
screen_write_clearendofline(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct tty_ctx		 ttyctx;
 | 
			
		||||
	u_int		 sx;
 | 
			
		||||
	u_int			 sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	if (s->cx <= sx - 1)
 | 
			
		||||
	gl = &s->grid->linedata[s->grid->hsize + s->cy];
 | 
			
		||||
	if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
 | 
			
		||||
		screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
 | 
			
		||||
	} else
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_clearendofline, &ttyctx);
 | 
			
		||||
}
 | 
			
		||||
@@ -730,16 +829,17 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
	u_int		 sx;
 | 
			
		||||
	u_int		 sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	if (s->cx > sx - 1)
 | 
			
		||||
	if (s->cx > sx - 1) {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, sx, 1);
 | 
			
		||||
	else
 | 
			
		||||
	} else {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_clearstartofline, &ttyctx);
 | 
			
		||||
}
 | 
			
		||||
@@ -768,9 +868,10 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	if (s->cy == s->rupper)
 | 
			
		||||
	if (s->cy == s->rupper) {
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
 | 
			
		||||
	else if (s->cy > 0)
 | 
			
		||||
	} else if (s->cy > 0)
 | 
			
		||||
		s->cy--;
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_reverseindex, &ttyctx);
 | 
			
		||||
@@ -805,6 +906,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct tty_ctx	 	 ttyctx;
 | 
			
		||||
	u_int			 sx = screen_size_x(s), sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
@@ -814,9 +916,11 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
 | 
			
		||||
	else
 | 
			
		||||
		gl->flags &= ~GRID_LINE_WRAPPED;
 | 
			
		||||
 | 
			
		||||
	if (s->cy == s->rlower)
 | 
			
		||||
	if (s->cy == s->rlower) {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->rupper, sx - 1, s->rupper);
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
 | 
			
		||||
	else if (s->cy < screen_size_y(s) - 1)
 | 
			
		||||
	} else if (s->cy < sy - 1)
 | 
			
		||||
		s->cy++;
 | 
			
		||||
 | 
			
		||||
	ttyctx.num = wrapped;
 | 
			
		||||
@@ -838,19 +942,20 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
	u_int		 sx, sy;
 | 
			
		||||
	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
	sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	/* Scroll into history if it is enabled and clearing entire screen. */
 | 
			
		||||
	if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
 | 
			
		||||
	if (s->cy == 0 && s->grid->flags & GRID_HISTORY) {
 | 
			
		||||
		screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);
 | 
			
		||||
		grid_view_clear_history(s->grid);
 | 
			
		||||
	else {
 | 
			
		||||
		if (s->cx <= sx - 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		if (s->cx <= sx - 1) {
 | 
			
		||||
			screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
 | 
			
		||||
			grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
 | 
			
		||||
		}
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -863,18 +968,21 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
	u_int		 sx;
 | 
			
		||||
	u_int		 sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	sx = screen_size_x(s);
 | 
			
		||||
 | 
			
		||||
	if (s->cy > 0)
 | 
			
		||||
	if (s->cy > 0) {
 | 
			
		||||
		screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, 0, sx, s->cy);
 | 
			
		||||
	if (s->cx > sx - 1)
 | 
			
		||||
	}
 | 
			
		||||
	if (s->cx > sx - 1) {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, sx, 1);
 | 
			
		||||
	else
 | 
			
		||||
	} else {
 | 
			
		||||
		screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tty_write(tty_cmd_clearstartofscreen, &ttyctx);
 | 
			
		||||
}
 | 
			
		||||
@@ -885,11 +993,12 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
	u_int		 sx = screen_size_x(s);
 | 
			
		||||
	u_int		 sy = screen_size_y(s);
 | 
			
		||||
	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);
 | 
			
		||||
 | 
			
		||||
	/* Scroll into history if it is enabled. */
 | 
			
		||||
	if (s->grid->flags & GRID_HISTORY)
 | 
			
		||||
		grid_view_clear_history(s->grid);
 | 
			
		||||
@@ -918,8 +1027,13 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	struct grid		*gd = s->grid;
 | 
			
		||||
	struct tty_ctx		 ttyctx;
 | 
			
		||||
	u_int		 	 width, xx, last;
 | 
			
		||||
	u_int			 sx = screen_size_x(s), sy = screen_size_y(s);
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct grid_cell 	 tmp_gc, now_gc;
 | 
			
		||||
	int			 insert, skip, selected;
 | 
			
		||||
	struct grid_cell_entry	*gce;
 | 
			
		||||
	int			 insert, skip, selected, wrapped = 0;
 | 
			
		||||
 | 
			
		||||
	ctx->cells++;
 | 
			
		||||
 | 
			
		||||
	/* Ignore padding. */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
@@ -930,10 +1044,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	 * If this is a wide character and there is no room on the screen, for
 | 
			
		||||
	 * the entire character, don't print it.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(s->mode & MODE_WRAP)
 | 
			
		||||
	    && (width > 1 && (width > screen_size_x(s) ||
 | 
			
		||||
		(s->cx != screen_size_x(s)
 | 
			
		||||
		 && s->cx > screen_size_x(s) - width))))
 | 
			
		||||
	if (!(s->mode & MODE_WRAP) && (width > 1 &&
 | 
			
		||||
	    (width > sx || (s->cx != sx && s->cx > sx - width))))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -952,8 +1064,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	/* If in insert mode, make space for the cells. */
 | 
			
		||||
	if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) {
 | 
			
		||||
		xx = screen_size_x(s) - s->cx - width;
 | 
			
		||||
	if ((s->mode & MODE_INSERT) && s->cx <= sx - width) {
 | 
			
		||||
		xx = sx - s->cx - width;
 | 
			
		||||
		grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
 | 
			
		||||
		insert = 1;
 | 
			
		||||
	} else
 | 
			
		||||
@@ -961,20 +1073,26 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	skip = !insert;
 | 
			
		||||
 | 
			
		||||
	/* Check this will fit on the current line and wrap if not. */
 | 
			
		||||
	if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
 | 
			
		||||
	if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		screen_write_save_last(ctx, &ttyctx);
 | 
			
		||||
		screen_write_linefeed(ctx, 1);
 | 
			
		||||
		s->cx = 0;	/* carriage return */
 | 
			
		||||
		skip = 0;
 | 
			
		||||
		wrapped = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Sanity check cursor position. */
 | 
			
		||||
	if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1)
 | 
			
		||||
	if (s->cx > sx - width || s->cy > sy - 1)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Handle overwriting of UTF-8 characters. */
 | 
			
		||||
	gl = &s->grid->linedata[s->grid->hsize + s->cy];
 | 
			
		||||
	if (gl->flags & GRID_LINE_EXTENDED) {
 | 
			
		||||
		grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
 | 
			
		||||
		if (screen_write_overwrite(ctx, &now_gc, width))
 | 
			
		||||
			skip = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the new character is UTF-8 wide, fill in padding cells. Have
 | 
			
		||||
@@ -986,8 +1104,25 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If no change, do not draw. */
 | 
			
		||||
	if (skip)
 | 
			
		||||
		skip = (memcmp(&now_gc, gc, sizeof now_gc) == 0);
 | 
			
		||||
	if (skip) {
 | 
			
		||||
		if (s->cx >= gl->cellsize)
 | 
			
		||||
			skip = grid_cells_equal(gc, &grid_default_cell);
 | 
			
		||||
		else {
 | 
			
		||||
			gce = &gl->celldata[s->cx];
 | 
			
		||||
			if (gce->flags & GRID_FLAG_EXTENDED)
 | 
			
		||||
				skip = 0;
 | 
			
		||||
			else if (gc->flags != (gce->flags & ~GRID_FLAG_EXTENDED))
 | 
			
		||||
				skip = 0;
 | 
			
		||||
			else if (gc->attr != gce->data.attr)
 | 
			
		||||
				skip = 0;
 | 
			
		||||
			else if (gc->fg != gce->data.fg)
 | 
			
		||||
				skip = 0;
 | 
			
		||||
			else if (gc->bg != gce->data.bg)
 | 
			
		||||
				skip = 0;
 | 
			
		||||
			else if (gc->data.width != 1 || gce->data.data != gc->data.data[0])
 | 
			
		||||
				skip = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Update the selection the flag and set the cell. */
 | 
			
		||||
	selected = screen_check_selection(s, s->cx, s->cy);
 | 
			
		||||
@@ -1009,21 +1144,19 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	 * replace it.
 | 
			
		||||
	 */
 | 
			
		||||
	last = !(s->mode & MODE_WRAP);
 | 
			
		||||
	if (s->cx <= screen_size_x(s) - last - width)
 | 
			
		||||
	if (s->cx <= sx - last - width)
 | 
			
		||||
		s->cx += width;
 | 
			
		||||
	else
 | 
			
		||||
		s->cx = screen_size_x(s) - last;
 | 
			
		||||
		s->cx = sx - last;
 | 
			
		||||
 | 
			
		||||
	/* Create space for character in insert mode. */
 | 
			
		||||
	if (insert) {
 | 
			
		||||
		if (!wrapped)
 | 
			
		||||
			screen_write_flush(ctx);
 | 
			
		||||
		ttyctx.num = width;
 | 
			
		||||
		tty_write(tty_cmd_insertcharacter, &ttyctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Save last cell if it will be needed. */
 | 
			
		||||
	if (!skip && ctx->wp != NULL && ttyctx.ocx > ctx->wp->sx - width)
 | 
			
		||||
		screen_write_save_last(ctx, &ttyctx);
 | 
			
		||||
 | 
			
		||||
	/* Write to the screen. */
 | 
			
		||||
	if (selected) {
 | 
			
		||||
		memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
 | 
			
		||||
@@ -1031,16 +1164,35 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
		tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
 | 
			
		||||
		tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
 | 
			
		||||
		tmp_gc.flags = gc->flags;
 | 
			
		||||
		tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB);
 | 
			
		||||
		tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
		tmp_gc.flags |= s->sel.cell.flags &
 | 
			
		||||
		    (GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
		screen_write_flush(ctx);
 | 
			
		||||
		ttyctx.cell = &tmp_gc;
 | 
			
		||||
		tty_write(tty_cmd_cell, &ttyctx);
 | 
			
		||||
		ctx->written++;
 | 
			
		||||
	} else if (!skip) {
 | 
			
		||||
		if (wrapped) {
 | 
			
		||||
			ttyctx.cell = gc;
 | 
			
		||||
			tty_write(tty_cmd_cell, &ttyctx);
 | 
			
		||||
			ctx->written++;
 | 
			
		||||
		} else {
 | 
			
		||||
			/*
 | 
			
		||||
			 * If wp is NULL, we are not updating the terminal and
 | 
			
		||||
			 * don't care about actually writing the cells
 | 
			
		||||
			 * (tty_write will just return). So don't even bother
 | 
			
		||||
			 * allocating the dirty array.
 | 
			
		||||
			 */
 | 
			
		||||
			if (ctx->wp != NULL && s->dirty == NULL) {
 | 
			
		||||
				log_debug("%s: allocating %u bits", __func__,
 | 
			
		||||
				    s->dirtysize);
 | 
			
		||||
				s->dirty = bit_alloc(s->dirtysize);
 | 
			
		||||
			}
 | 
			
		||||
			if (s->dirty != NULL) {
 | 
			
		||||
				bit_set(s->dirty, screen_dirty_bit(s,
 | 
			
		||||
				    ttyctx.ocx, ttyctx.ocy));
 | 
			
		||||
				ctx->dirty++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		ctx->skipped++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Combine a UTF-8 zero-width character onto the previous. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								screen.c
									
									
									
									
									
								
							@@ -38,6 +38,9 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
 | 
			
		||||
	s->ccolour = xstrdup("");
 | 
			
		||||
	s->tabs = NULL;
 | 
			
		||||
 | 
			
		||||
	s->dirty = NULL;
 | 
			
		||||
	s->dirtysize = 0;
 | 
			
		||||
 | 
			
		||||
	screen_reinit(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -64,6 +67,7 @@ screen_reinit(struct screen *s)
 | 
			
		||||
void
 | 
			
		||||
screen_free(struct screen *s)
 | 
			
		||||
{
 | 
			
		||||
	free(s->dirty);
 | 
			
		||||
	free(s->tabs);
 | 
			
		||||
	free(s->title);
 | 
			
		||||
	free(s->ccolour);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								style.c
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								style.c
									
									
									
									
									
								
							@@ -33,7 +33,8 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
 | 
			
		||||
	char			tmp[32];
 | 
			
		||||
	int			val;
 | 
			
		||||
	size_t			end;
 | 
			
		||||
	u_char			fg, bg, attr, flags;
 | 
			
		||||
	int			fg, bg;
 | 
			
		||||
	u_char			attr, flags;
 | 
			
		||||
 | 
			
		||||
	if (*in == '\0')
 | 
			
		||||
		return (0);
 | 
			
		||||
@@ -56,38 +57,20 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
 | 
			
		||||
			fg = defgc->fg;
 | 
			
		||||
			bg = defgc->bg;
 | 
			
		||||
			attr = defgc->attr;
 | 
			
		||||
			flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			flags |=
 | 
			
		||||
			    defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			flags = defgc->flags;
 | 
			
		||||
		} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
 | 
			
		||||
			if ((val = colour_fromstring(tmp + 3)) == -1)
 | 
			
		||||
				goto error;
 | 
			
		||||
			if (*in == 'f' || *in == 'F') {
 | 
			
		||||
				if (val != 8) {
 | 
			
		||||
					if (val & 0x100) {
 | 
			
		||||
						flags |= GRID_FLAG_FG256;
 | 
			
		||||
						val &= ~0x100;
 | 
			
		||||
					} else
 | 
			
		||||
						flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
				if (val != 8)
 | 
			
		||||
					fg = val;
 | 
			
		||||
				} else {
 | 
			
		||||
				else
 | 
			
		||||
					fg = defgc->fg;
 | 
			
		||||
					flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
					flags |= defgc->flags & GRID_FLAG_FG256;
 | 
			
		||||
				}
 | 
			
		||||
			} else if (*in == 'b' || *in == 'B') {
 | 
			
		||||
				if (val != 8) {
 | 
			
		||||
					if (val & 0x100) {
 | 
			
		||||
						flags |= GRID_FLAG_BG256;
 | 
			
		||||
						val &= ~0x100;
 | 
			
		||||
					} else
 | 
			
		||||
						flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
				if (val != 8)
 | 
			
		||||
					bg = val;
 | 
			
		||||
				} else {
 | 
			
		||||
				else
 | 
			
		||||
					bg = defgc->bg;
 | 
			
		||||
					flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
					flags |= defgc->flags & GRID_FLAG_BG256;
 | 
			
		||||
				}
 | 
			
		||||
			} else
 | 
			
		||||
				goto error;
 | 
			
		||||
		} else if (strcasecmp(tmp, "none") == 0)
 | 
			
		||||
@@ -120,27 +103,19 @@ error:
 | 
			
		||||
const char *
 | 
			
		||||
style_tostring(struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	int		 c, off = 0, comma = 0;
 | 
			
		||||
	int		 off = 0, comma = 0;
 | 
			
		||||
	static char	 s[256];
 | 
			
		||||
 | 
			
		||||
	*s = '\0';
 | 
			
		||||
 | 
			
		||||
	if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
 | 
			
		||||
		if (gc->flags & GRID_FLAG_FG256)
 | 
			
		||||
			c = gc->fg | 0x100;
 | 
			
		||||
		else
 | 
			
		||||
			c = gc->fg;
 | 
			
		||||
		off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
 | 
			
		||||
	if (gc->fg != 8) {
 | 
			
		||||
		off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg));
 | 
			
		||||
		comma = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
 | 
			
		||||
		if (gc->flags & GRID_FLAG_BG256)
 | 
			
		||||
			c = gc->bg | 0x100;
 | 
			
		||||
		else
 | 
			
		||||
			c = gc->bg;
 | 
			
		||||
	if (gc->bg != 8) {
 | 
			
		||||
		off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
 | 
			
		||||
		    comma ? "," : "", colour_tostring(c));
 | 
			
		||||
		    comma ? "," : "", colour_tostring(gc->bg));
 | 
			
		||||
		comma = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -177,9 +152,9 @@ style_update_new(struct options *oo, const char *name, const char *newname)
 | 
			
		||||
	value = o->num;
 | 
			
		||||
 | 
			
		||||
	if (strstr(name, "-bg") != NULL)
 | 
			
		||||
		colour_set_bg(gc, value);
 | 
			
		||||
		gc->bg = value;
 | 
			
		||||
	else if (strstr(name, "-fg") != NULL)
 | 
			
		||||
		colour_set_fg(gc, value);
 | 
			
		||||
		gc->fg = value;
 | 
			
		||||
	else if (strstr(name, "-attr") != NULL)
 | 
			
		||||
		gc->attr = value;
 | 
			
		||||
}
 | 
			
		||||
@@ -189,23 +164,15 @@ void
 | 
			
		||||
style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	char	newname[128];
 | 
			
		||||
	int	c, size;
 | 
			
		||||
	int	size;
 | 
			
		||||
 | 
			
		||||
	size = strrchr(name, '-') - name;
 | 
			
		||||
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BG256)
 | 
			
		||||
		c = gc->bg | 0x100;
 | 
			
		||||
	else
 | 
			
		||||
		c = gc->bg;
 | 
			
		||||
	xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
 | 
			
		||||
	options_set_number(oo, newname, c);
 | 
			
		||||
	options_set_number(oo, newname, gc->bg);
 | 
			
		||||
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FG256)
 | 
			
		||||
		c = gc->fg | 0x100;
 | 
			
		||||
	else
 | 
			
		||||
		c = gc->fg;
 | 
			
		||||
	xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
 | 
			
		||||
	options_set_number(oo, newname, c);
 | 
			
		||||
	options_set_number(oo, newname, gc->fg);
 | 
			
		||||
 | 
			
		||||
	xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
 | 
			
		||||
	options_set_number(oo, newname, gc->attr);
 | 
			
		||||
@@ -219,14 +186,8 @@ style_apply(struct grid_cell *gc, struct options *oo, const char *name)
 | 
			
		||||
 | 
			
		||||
	memcpy(gc, &grid_default_cell, sizeof *gc);
 | 
			
		||||
	gcp = options_get_style(oo, name);
 | 
			
		||||
	if (gcp->flags & GRID_FLAG_FG256)
 | 
			
		||||
		colour_set_fg(gc, gcp->fg | 0x100);
 | 
			
		||||
	else
 | 
			
		||||
		colour_set_fg(gc, gcp->fg);
 | 
			
		||||
	if (gcp->flags & GRID_FLAG_BG256)
 | 
			
		||||
		colour_set_bg(gc, gcp->bg | 0x100);
 | 
			
		||||
	else
 | 
			
		||||
		colour_set_bg(gc, gcp->bg);
 | 
			
		||||
	gc->fg = gcp->fg;
 | 
			
		||||
	gc->bg = gcp->bg;
 | 
			
		||||
	gc->attr |= gcp->attr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -237,18 +198,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
 | 
			
		||||
	struct grid_cell	*gcp;
 | 
			
		||||
 | 
			
		||||
	gcp = options_get_style(oo, name);
 | 
			
		||||
	if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) {
 | 
			
		||||
		if (gcp->flags & GRID_FLAG_FG256)
 | 
			
		||||
			colour_set_fg(gc, gcp->fg | 0x100);
 | 
			
		||||
		else
 | 
			
		||||
			colour_set_fg(gc, gcp->fg);
 | 
			
		||||
	}
 | 
			
		||||
	if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
 | 
			
		||||
		if (gcp->flags & GRID_FLAG_BG256)
 | 
			
		||||
			colour_set_bg(gc, gcp->bg | 0x100);
 | 
			
		||||
		else
 | 
			
		||||
			colour_set_bg(gc, gcp->bg);
 | 
			
		||||
	}
 | 
			
		||||
	if (gcp->fg != 8)
 | 
			
		||||
		gc->fg = gcp->fg;
 | 
			
		||||
	if (gcp->bg != 8)
 | 
			
		||||
		gc->bg = gcp->bg;
 | 
			
		||||
	if (gcp->attr != 0)
 | 
			
		||||
		gc->attr |= gcp->attr;
 | 
			
		||||
}
 | 
			
		||||
@@ -257,10 +210,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
 | 
			
		||||
int
 | 
			
		||||
style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
 | 
			
		||||
{
 | 
			
		||||
	return gc1->fg == gc2->fg &&
 | 
			
		||||
	return (gc1->fg == gc2->fg &&
 | 
			
		||||
	    gc1->bg == gc2->bg &&
 | 
			
		||||
	    (gc1->flags & ~GRID_FLAG_PADDING) ==
 | 
			
		||||
	    (gc2->flags & ~GRID_FLAG_PADDING) &&
 | 
			
		||||
	    (gc1->attr & ~GRID_ATTR_CHARSET) ==
 | 
			
		||||
		(gc2->attr & ~GRID_ATTR_CHARSET);
 | 
			
		||||
	    (gc2->attr & ~GRID_ATTR_CHARSET));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								tmux.h
									
									
									
									
									
								
							@@ -62,7 +62,7 @@ struct tmuxproc;
 | 
			
		||||
#define NAME_INTERVAL 500000
 | 
			
		||||
 | 
			
		||||
/* The maximum amount of data to hold from a pty (the event high watermark). */
 | 
			
		||||
#define READ_SIZE 128
 | 
			
		||||
#define READ_SIZE 4096
 | 
			
		||||
 | 
			
		||||
/* Attribute to make gcc check printf-like arguments. */
 | 
			
		||||
#define printflike(a, b) __attribute__ ((format (printf, a, b)))
 | 
			
		||||
@@ -627,6 +627,10 @@ enum utf8_state {
 | 
			
		||||
	UTF8_ERROR
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Colour flags. */
 | 
			
		||||
#define COLOUR_FLAG_256 0x01000000
 | 
			
		||||
#define COLOUR_FLAG_RGB 0x02000000
 | 
			
		||||
 | 
			
		||||
/* Grid attributes. */
 | 
			
		||||
#define GRID_ATTR_BRIGHT 0x1
 | 
			
		||||
#define GRID_ATTR_DIM 0x2
 | 
			
		||||
@@ -642,32 +646,18 @@ enum utf8_state {
 | 
			
		||||
#define GRID_FLAG_BG256 0x2
 | 
			
		||||
#define GRID_FLAG_PADDING 0x4
 | 
			
		||||
#define GRID_FLAG_EXTENDED 0x8
 | 
			
		||||
#define GRID_FLAG_FGRGB 0x10
 | 
			
		||||
#define GRID_FLAG_BGRGB 0x20
 | 
			
		||||
#define GRID_FLAG_SELECTED 0x40
 | 
			
		||||
#define GRID_FLAG_SELECTED 0x10
 | 
			
		||||
 | 
			
		||||
/* Grid line flags. */
 | 
			
		||||
#define GRID_LINE_WRAPPED 0x1
 | 
			
		||||
 | 
			
		||||
/* Grid cell RGB colours. */
 | 
			
		||||
struct grid_cell_rgb {
 | 
			
		||||
	u_char	r;
 | 
			
		||||
	u_char	g;
 | 
			
		||||
	u_char	b;
 | 
			
		||||
};
 | 
			
		||||
#define GRID_LINE_EXTENDED 0x2
 | 
			
		||||
 | 
			
		||||
/* Grid cell data. */
 | 
			
		||||
struct grid_cell {
 | 
			
		||||
	u_char			flags;
 | 
			
		||||
	u_char			attr;
 | 
			
		||||
	union {
 | 
			
		||||
		u_char		fg;
 | 
			
		||||
		struct grid_cell_rgb	fg_rgb;
 | 
			
		||||
	};
 | 
			
		||||
	union {
 | 
			
		||||
		u_char		bg;
 | 
			
		||||
		struct grid_cell_rgb	bg_rgb;
 | 
			
		||||
	};
 | 
			
		||||
	int			fg;
 | 
			
		||||
	int			bg;
 | 
			
		||||
	struct utf8_data	data;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
@@ -799,6 +789,9 @@ struct screen {
 | 
			
		||||
 | 
			
		||||
	bitstr_t		*tabs;
 | 
			
		||||
 | 
			
		||||
	bitstr_t		*dirty;
 | 
			
		||||
	u_int			 dirtysize;
 | 
			
		||||
 | 
			
		||||
	struct screen_sel	 sel;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -806,6 +799,11 @@ struct screen {
 | 
			
		||||
struct screen_write_ctx {
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct screen		*s;
 | 
			
		||||
	u_int			 dirty;
 | 
			
		||||
 | 
			
		||||
	u_int			 cells;
 | 
			
		||||
	u_int			 written;
 | 
			
		||||
	u_int			 skipped;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Screen size. */
 | 
			
		||||
@@ -1211,7 +1209,6 @@ struct tty_ctx {
 | 
			
		||||
 | 
			
		||||
	/* Saved last cell on line. */
 | 
			
		||||
	struct grid_cell last_cell;
 | 
			
		||||
	u_int		 last_width;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Saved message entry. */
 | 
			
		||||
@@ -1983,10 +1980,10 @@ int	 xterm_keys_find(const char *, size_t, size_t *, key_code *);
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
int	 colour_join_rgb(u_char, u_char, u_char);
 | 
			
		||||
void	 colour_split_rgb(int, u_char *, u_char *, u_char *);
 | 
			
		||||
const char *colour_tostring(int);
 | 
			
		||||
int	 colour_fromstring(const char *);
 | 
			
		||||
int	 colour_fromstring(const char *s);
 | 
			
		||||
u_char	 colour_256to16(u_char);
 | 
			
		||||
 | 
			
		||||
/* attributes.c */
 | 
			
		||||
@@ -1995,6 +1992,7 @@ int	 attributes_fromstring(const char *);
 | 
			
		||||
 | 
			
		||||
/* grid.c */
 | 
			
		||||
extern const struct grid_cell grid_default_cell;
 | 
			
		||||
int	 grid_cells_equal(const struct grid_cell *, const struct grid_cell *);
 | 
			
		||||
struct grid *grid_create(u_int, u_int, u_int);
 | 
			
		||||
void	 grid_destroy(struct grid *);
 | 
			
		||||
int	 grid_compare(struct grid *, struct grid *);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										276
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										276
									
								
								tty.c
									
									
									
									
									
								
							@@ -36,17 +36,10 @@ static int tty_log_fd = -1;
 | 
			
		||||
void	tty_read_callback(struct bufferevent *, void *);
 | 
			
		||||
void	tty_error_callback(struct bufferevent *, short, void *);
 | 
			
		||||
 | 
			
		||||
static int tty_same_fg(const struct grid_cell *, const struct grid_cell *);
 | 
			
		||||
static int tty_same_bg(const struct grid_cell *, const struct grid_cell *);
 | 
			
		||||
static int tty_same_colours(const struct grid_cell *, const struct grid_cell *);
 | 
			
		||||
static int tty_is_fg(const struct grid_cell *, int);
 | 
			
		||||
static int tty_is_bg(const struct grid_cell *, int);
 | 
			
		||||
 | 
			
		||||
static int tty_client_ready(struct client *, struct window_pane *);
 | 
			
		||||
 | 
			
		||||
void	tty_set_italics(struct tty *);
 | 
			
		||||
int	tty_try_256(struct tty *, u_char, const char *);
 | 
			
		||||
int	tty_try_rgb(struct tty *, const struct grid_cell_rgb *, const char *);
 | 
			
		||||
int	tty_try_colour(struct tty *, int, const char *);
 | 
			
		||||
 | 
			
		||||
void	tty_colours(struct tty *, const struct grid_cell *);
 | 
			
		||||
void	tty_check_fg(struct tty *, struct grid_cell *);
 | 
			
		||||
@@ -70,74 +63,6 @@ void	tty_default_colours(struct grid_cell *, const struct window_pane *);
 | 
			
		||||
#define tty_pane_full_width(tty, ctx) \
 | 
			
		||||
	((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_same_fg(const struct grid_cell *gc1, const struct grid_cell *gc2)
 | 
			
		||||
{
 | 
			
		||||
	int	flags1, flags2;
 | 
			
		||||
 | 
			
		||||
	flags1 = (gc1->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
 | 
			
		||||
	flags2 = (gc2->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
 | 
			
		||||
 | 
			
		||||
	if (flags1 != flags2)
 | 
			
		||||
	    return (0);
 | 
			
		||||
 | 
			
		||||
	if (flags1 & GRID_FLAG_FGRGB) {
 | 
			
		||||
		if (gc1->fg_rgb.r != gc2->fg_rgb.r)
 | 
			
		||||
			return (0);
 | 
			
		||||
		if (gc1->fg_rgb.g != gc2->fg_rgb.g)
 | 
			
		||||
			return (0);
 | 
			
		||||
		if (gc1->fg_rgb.b != gc2->fg_rgb.b)
 | 
			
		||||
			return (0);
 | 
			
		||||
		return (1);
 | 
			
		||||
	}
 | 
			
		||||
	return (gc1->fg == gc2->fg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_same_bg(const struct grid_cell *gc1, const struct grid_cell *gc2)
 | 
			
		||||
{
 | 
			
		||||
	int	flags1, flags2;
 | 
			
		||||
 | 
			
		||||
	flags1 = (gc1->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
 | 
			
		||||
	flags2 = (gc2->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
 | 
			
		||||
 | 
			
		||||
	if (flags1 != flags2)
 | 
			
		||||
	    return (0);
 | 
			
		||||
 | 
			
		||||
	if (flags1 & GRID_FLAG_BGRGB) {
 | 
			
		||||
		if (gc1->bg_rgb.r != gc2->bg_rgb.r)
 | 
			
		||||
			return (0);
 | 
			
		||||
		if (gc1->bg_rgb.g != gc2->bg_rgb.g)
 | 
			
		||||
			return (0);
 | 
			
		||||
		if (gc1->bg_rgb.b != gc2->bg_rgb.b)
 | 
			
		||||
			return (0);
 | 
			
		||||
		return (1);
 | 
			
		||||
	}
 | 
			
		||||
	return (gc1->bg == gc2->bg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_same_colours(const struct grid_cell *gc1, const struct grid_cell *gc2)
 | 
			
		||||
{
 | 
			
		||||
	return (tty_same_fg(gc1, gc2) && tty_same_bg(gc1, gc2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_is_fg(const struct grid_cell *gc, int c)
 | 
			
		||||
{
 | 
			
		||||
	if (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB))
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (gc->fg == c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_is_bg(const struct grid_cell *gc, int c)
 | 
			
		||||
{
 | 
			
		||||
	if (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB))
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (gc->bg == c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_create_log(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -679,7 +604,7 @@ tty_fake_bce(const struct tty *tty, const struct window_pane *wp)
 | 
			
		||||
	if (wp != NULL)
 | 
			
		||||
		tty_default_colours(&gc, wp);
 | 
			
		||||
 | 
			
		||||
	if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256))
 | 
			
		||||
	if (gc.bg == 8)
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (!tty_term_flag(tty->term, TTYC_BCE));
 | 
			
		||||
}
 | 
			
		||||
@@ -754,11 +679,6 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sx; i++) {
 | 
			
		||||
		grid_view_get_cell(s->grid, i, py, &gc);
 | 
			
		||||
		if (screen_check_selection(s, i, py)) {
 | 
			
		||||
			gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			gc.flags |= s->sel.cell.flags &
 | 
			
		||||
			    (GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
		}
 | 
			
		||||
		tty_cell(tty, &gc, wp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1255,7 +1175,7 @@ tty_reset(struct tty *tty)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*gc = &tty->cell;
 | 
			
		||||
 | 
			
		||||
	if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
 | 
			
		||||
	if (grid_cells_equal(gc, &grid_default_cell))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
 | 
			
		||||
@@ -1507,10 +1427,10 @@ void
 | 
			
		||||
tty_colours(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*tc = &tty->cell;
 | 
			
		||||
	int			 have_ax, fg_default, bg_default;
 | 
			
		||||
	int			 have_ax;
 | 
			
		||||
 | 
			
		||||
	/* No changes? Nothing is necessary. */
 | 
			
		||||
	if (tty_same_colours(gc, tc))
 | 
			
		||||
	if (gc->fg == tc->fg && gc->bg == tc->bg)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -1519,9 +1439,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
	 * case if only one is default need to fall onward to set the other
 | 
			
		||||
	 * colour.
 | 
			
		||||
	 */
 | 
			
		||||
	fg_default = tty_is_fg(gc, 8);
 | 
			
		||||
	bg_default = tty_is_bg(gc, 8);
 | 
			
		||||
	if (fg_default || bg_default) {
 | 
			
		||||
	if (gc->fg == 8 || gc->bg == 8) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * If don't have AX but do have op, send sgr0 (op can't
 | 
			
		||||
		 * actually be used because it is sometimes the same as sgr0
 | 
			
		||||
@@ -1533,58 +1451,54 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
		if (!have_ax && tty_term_has(tty->term, TTYC_OP))
 | 
			
		||||
			tty_reset(tty);
 | 
			
		||||
		else {
 | 
			
		||||
			if (fg_default && !tty_is_fg(tc, 8)) {
 | 
			
		||||
			if (gc->fg == 8 && tc->fg != 8) {
 | 
			
		||||
				if (have_ax)
 | 
			
		||||
					tty_puts(tty, "\033[39m");
 | 
			
		||||
				else if (!tty_is_fg(tc, 7))
 | 
			
		||||
				else if (tc->fg != 7)
 | 
			
		||||
					tty_putcode1(tty, TTYC_SETAF, 7);
 | 
			
		||||
				tc->fg = 8;
 | 
			
		||||
				tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
			}
 | 
			
		||||
			if (bg_default && !tty_is_bg(tc, 8)) {
 | 
			
		||||
			if (gc->bg == 8 && tc->bg != 8) {
 | 
			
		||||
				if (have_ax)
 | 
			
		||||
					tty_puts(tty, "\033[49m");
 | 
			
		||||
				else if (!tty_is_bg(tc, 0))
 | 
			
		||||
				else if (tc->bg != 0)
 | 
			
		||||
					tty_putcode1(tty, TTYC_SETAB, 0);
 | 
			
		||||
				tc->bg = 8;
 | 
			
		||||
				tc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set the foreground colour. */
 | 
			
		||||
	if (!fg_default && !tty_same_fg(gc, tc))
 | 
			
		||||
	if (gc->fg != 8 && gc->fg != tc->fg)
 | 
			
		||||
		tty_colours_fg(tty, gc);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Set the background colour. This must come after the foreground as
 | 
			
		||||
	 * tty_colour_fg() can call tty_reset().
 | 
			
		||||
	 */
 | 
			
		||||
	if (!bg_default && !tty_same_bg(gc, tc))
 | 
			
		||||
	if (gc->bg != 8 && gc->bg != tc->bg)
 | 
			
		||||
		tty_colours_bg(tty, gc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_check_fg(struct tty *tty, struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell_rgb	*rgb = &gc->fg_rgb;
 | 
			
		||||
	u_char	r, g, b;
 | 
			
		||||
	u_int	colours;
 | 
			
		||||
 | 
			
		||||
	/* Is this a 24-bit colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FGRGB) {
 | 
			
		||||
	if (gc->fg & COLOUR_FLAG_RGB) {
 | 
			
		||||
		/* Not a 24-bit terminal? Translate to 256-colour palette. */
 | 
			
		||||
		if (!tty_term_flag(tty->term, TTYC_TC)) {
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_FGRGB;
 | 
			
		||||
			gc->flags |= GRID_FLAG_FG256;
 | 
			
		||||
			gc->fg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			colour_split_rgb(gc->fg, &r, &g, &b);
 | 
			
		||||
			gc->fg = colour_find_rgb(r, g, b);
 | 
			
		||||
		} else
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
	colours = tty_term_number(tty->term, TTYC_COLORS);
 | 
			
		||||
 | 
			
		||||
	/* Is this a 256-colour colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FG256) {
 | 
			
		||||
	if (gc->fg & COLOUR_FLAG_256) {
 | 
			
		||||
		/* And not a 256 colour mode? */
 | 
			
		||||
		if (!(tty->term->flags & TERM_256COLOURS) &&
 | 
			
		||||
		    !(tty->term_flags & TERM_256COLOURS)) {
 | 
			
		||||
@@ -1597,7 +1511,6 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
 | 
			
		||||
					gc->attr |= GRID_ATTR_BRIGHT;
 | 
			
		||||
			} else
 | 
			
		||||
				gc->attr &= ~GRID_ATTR_BRIGHT;
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_FG256;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1612,24 +1525,22 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
 | 
			
		||||
void
 | 
			
		||||
tty_check_bg(struct tty *tty, struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell_rgb	*rgb = &gc->bg_rgb;
 | 
			
		||||
	u_char	r, g, b;
 | 
			
		||||
	u_int	colours;
 | 
			
		||||
 | 
			
		||||
	/* Is this a 24-bit colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BGRGB) {
 | 
			
		||||
	if (gc->bg & COLOUR_FLAG_RGB) {
 | 
			
		||||
		/* Not a 24-bit terminal? Translate to 256-colour palette. */
 | 
			
		||||
		if (!tty_term_flag(tty->term, TTYC_TC)) {
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_BGRGB;
 | 
			
		||||
			gc->flags |= GRID_FLAG_BG256;
 | 
			
		||||
			gc->bg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			colour_split_rgb(gc->bg, &r, &g, &b);
 | 
			
		||||
			gc->bg = colour_find_rgb(r, g, b);
 | 
			
		||||
		} else
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
	colours = tty_term_number(tty->term, TTYC_COLORS);
 | 
			
		||||
 | 
			
		||||
	/* Is this a 256-colour colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BG256) {
 | 
			
		||||
	if (gc->bg & COLOUR_FLAG_256) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * And not a 256 colour mode? Translate to 16-colour
 | 
			
		||||
		 * palette. Bold background doesn't exist portably, so just
 | 
			
		||||
@@ -1643,7 +1554,6 @@ tty_check_bg(struct tty *tty, struct grid_cell *gc)
 | 
			
		||||
				if (colours >= 16)
 | 
			
		||||
					gc->fg += 90;
 | 
			
		||||
			}
 | 
			
		||||
			gc->flags &= ~GRID_FLAG_BG256;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1657,137 +1567,111 @@ void
 | 
			
		||||
tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*tc = &tty->cell;
 | 
			
		||||
	u_char			 fg = gc->fg;
 | 
			
		||||
	char			 s[32];
 | 
			
		||||
 | 
			
		||||
	tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
 | 
			
		||||
 | 
			
		||||
	/* Is this a 24-bit colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FGRGB) {
 | 
			
		||||
		if (tty_try_rgb(tty, &gc->fg_rgb, "38") == 0)
 | 
			
		||||
			goto save_fg;
 | 
			
		||||
		/* Should not get here, already converted in tty_check_fg. */
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is this a 256-colour colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FG256) {
 | 
			
		||||
		if (tty_try_256(tty, fg, "38") == 0)
 | 
			
		||||
	/* Is this a 24-bit or 256-colour colour? */
 | 
			
		||||
	if (gc->fg & COLOUR_FLAG_RGB ||
 | 
			
		||||
	    gc->fg & COLOUR_FLAG_256) {
 | 
			
		||||
		if (tty_try_colour(tty, gc->fg, "38") == 0)
 | 
			
		||||
			goto save_fg;
 | 
			
		||||
		/* Should not get here, already converted in tty_check_fg. */
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is this an aixterm bright colour? */
 | 
			
		||||
	if (fg >= 90 && fg <= 97) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "\033[%dm", fg);
 | 
			
		||||
	if (gc->fg >= 90 && gc->fg <= 97) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
 | 
			
		||||
		tty_puts(tty, s);
 | 
			
		||||
		goto save_fg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Otherwise set the foreground colour. */
 | 
			
		||||
	tty_putcode1(tty, TTYC_SETAF, fg);
 | 
			
		||||
	tty_putcode1(tty, TTYC_SETAF, gc->fg);
 | 
			
		||||
 | 
			
		||||
save_fg:
 | 
			
		||||
	/* Save the new values in the terminal current cell. */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_FGRGB)
 | 
			
		||||
		memcpy(&tc->fg_rgb, &gc->fg_rgb, sizeof tc->fg_rgb);
 | 
			
		||||
	else
 | 
			
		||||
		tc->fg = fg;
 | 
			
		||||
	tc->flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_FG256);
 | 
			
		||||
	tc->flags |= (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
 | 
			
		||||
	tc->fg = gc->fg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell	*tc = &tty->cell;
 | 
			
		||||
	u_char			 bg = gc->bg;
 | 
			
		||||
	char			 s[32];
 | 
			
		||||
 | 
			
		||||
	/* Is this a 24-bit colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BGRGB) {
 | 
			
		||||
		if (tty_try_rgb(tty, &gc->bg_rgb, "48") == 0)
 | 
			
		||||
			goto save_bg;
 | 
			
		||||
		/* Should not get here, already converted in tty_check_bg. */
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is this a 256-colour colour? */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BG256) {
 | 
			
		||||
		if (tty_try_256(tty, bg, "48") == 0)
 | 
			
		||||
	/* Is this a 24-bit or 256-colour colour? */
 | 
			
		||||
	if (gc->bg & COLOUR_FLAG_RGB ||
 | 
			
		||||
	    gc->bg & COLOUR_FLAG_256) {
 | 
			
		||||
		if (tty_try_colour(tty, gc->bg, "48") == 0)
 | 
			
		||||
			goto save_bg;
 | 
			
		||||
		/* Should not get here, already converted in tty_check_bg. */
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is this an aixterm bright colour? */
 | 
			
		||||
	if (bg >= 90 && bg <= 97) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "\033[%dm", bg + 10);
 | 
			
		||||
	if (gc->bg >= 90 && gc->bg <= 97) {
 | 
			
		||||
		xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
 | 
			
		||||
		tty_puts(tty, s);
 | 
			
		||||
		goto save_bg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Otherwise set the background colour. */
 | 
			
		||||
	tty_putcode1(tty, TTYC_SETAB, bg);
 | 
			
		||||
	tty_putcode1(tty, TTYC_SETAB, gc->bg);
 | 
			
		||||
 | 
			
		||||
save_bg:
 | 
			
		||||
	/* Save the new values in the terminal current cell. */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_BGRGB)
 | 
			
		||||
		memcpy(&tc->bg_rgb, &gc->bg_rgb, sizeof tc->bg_rgb);
 | 
			
		||||
	else
 | 
			
		||||
		tc->bg = bg;
 | 
			
		||||
	tc->flags &= ~(GRID_FLAG_BGRGB|GRID_FLAG_BG256);
 | 
			
		||||
	tc->flags |= (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
 | 
			
		||||
	tc->bg = gc->bg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
tty_try_256(struct tty *tty, u_char colour, const char *type)
 | 
			
		||||
tty_try_colour(struct tty *tty, int colour, const char *type)
 | 
			
		||||
{
 | 
			
		||||
	u_char	r, g, b;
 | 
			
		||||
	char	s[32];
 | 
			
		||||
 | 
			
		||||
	if (colour & COLOUR_FLAG_256) {
 | 
			
		||||
		/*
 | 
			
		||||
	 * If the user has specified -2 to the client, setaf and setab may not
 | 
			
		||||
	 * work (or they may not want to use them), so send the usual sequence.
 | 
			
		||||
		 * If the user has specified -2 to the client, setaf and setab
 | 
			
		||||
		 * may not work (or they may not want to use them), so send the
 | 
			
		||||
		 * usual sequence.
 | 
			
		||||
		 */
 | 
			
		||||
		if (tty->term_flags & TERM_256COLOURS)
 | 
			
		||||
		goto fallback;
 | 
			
		||||
			goto fallback_256;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
	 * If the terminfo entry has 256 colours and setaf and setab exist,
 | 
			
		||||
	 * assume that they work correctly.
 | 
			
		||||
		 * If the terminfo entry has 256 colours and setaf and setab
 | 
			
		||||
		 * exist, assume that they work correctly.
 | 
			
		||||
		 */
 | 
			
		||||
		if (tty->term->flags & TERM_256COLOURS) {
 | 
			
		||||
			if (*type == '3') {
 | 
			
		||||
				if (!tty_term_has(tty->term, TTYC_SETAF))
 | 
			
		||||
				goto fallback;
 | 
			
		||||
			tty_putcode1(tty, TTYC_SETAF, colour);
 | 
			
		||||
					goto fallback_256;
 | 
			
		||||
				tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (!tty_term_has(tty->term, TTYC_SETAB))
 | 
			
		||||
				goto fallback;
 | 
			
		||||
			tty_putcode1(tty, TTYC_SETAB, colour);
 | 
			
		||||
					goto fallback_256;
 | 
			
		||||
				tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
 | 
			
		||||
			}
 | 
			
		||||
			return (0);
 | 
			
		||||
		}
 | 
			
		||||
		goto fallback_256;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (-1);
 | 
			
		||||
 | 
			
		||||
fallback:
 | 
			
		||||
	xsnprintf(s, sizeof s, "\033[%s;5;%hhum", type, colour);
 | 
			
		||||
	tty_puts(tty, s);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
tty_try_rgb(struct tty *tty, const struct grid_cell_rgb *rgb, const char *type)
 | 
			
		||||
{
 | 
			
		||||
	char	s[32];
 | 
			
		||||
 | 
			
		||||
	if (colour & COLOUR_FLAG_RGB) {
 | 
			
		||||
		if (!tty_term_flag(tty->term, TTYC_TC))
 | 
			
		||||
			return (-1);
 | 
			
		||||
 | 
			
		||||
	xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type, rgb->r,
 | 
			
		||||
	    rgb->g, rgb->b);
 | 
			
		||||
		colour_split_rgb(colour & 0xffffff, &r, &g, &b);
 | 
			
		||||
		xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type,
 | 
			
		||||
		    r, g, b);
 | 
			
		||||
		tty_puts(tty, s);
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (-1);
 | 
			
		||||
 | 
			
		||||
fallback_256:
 | 
			
		||||
	xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
 | 
			
		||||
	tty_puts(tty, s);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1811,31 +1695,21 @@ tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
 | 
			
		||||
	}
 | 
			
		||||
	pgc = &wp->colgc;
 | 
			
		||||
 | 
			
		||||
	if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) {
 | 
			
		||||
		if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) {
 | 
			
		||||
	if (gc->fg == 8) {
 | 
			
		||||
		if (pgc->fg != 8)
 | 
			
		||||
			gc->fg = pgc->fg;
 | 
			
		||||
			gc->flags |= (pgc->flags & GRID_FLAG_FG256);
 | 
			
		||||
		} else if (wp == w->active &&
 | 
			
		||||
		    (agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) {
 | 
			
		||||
		else if (wp == w->active && agc->fg != 8)
 | 
			
		||||
			gc->fg = agc->fg;
 | 
			
		||||
			gc->flags |= (agc->flags & GRID_FLAG_FG256);
 | 
			
		||||
		} else {
 | 
			
		||||
		else
 | 
			
		||||
			gc->fg = wgc->fg;
 | 
			
		||||
			gc->flags |= (wgc->flags & GRID_FLAG_FG256);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) {
 | 
			
		||||
		if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) {
 | 
			
		||||
	if (gc->bg == 8) {
 | 
			
		||||
		if (pgc->bg != 8)
 | 
			
		||||
			gc->bg = pgc->bg;
 | 
			
		||||
			gc->flags |= (pgc->flags & GRID_FLAG_BG256);
 | 
			
		||||
		} else if (wp == w->active &&
 | 
			
		||||
		    (agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) {
 | 
			
		||||
		else if (wp == w->active && agc->bg != 8)
 | 
			
		||||
			gc->bg = agc->bg;
 | 
			
		||||
			gc->flags |= (agc->flags & GRID_FLAG_BG256);
 | 
			
		||||
		} else {
 | 
			
		||||
		else
 | 
			
		||||
			gc->bg = wgc->bg;
 | 
			
		||||
			gc->flags |= (wgc->flags & GRID_FLAG_BG256);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -230,7 +230,7 @@ window_clock_draw_screen(struct window_pane *wp)
 | 
			
		||||
			screen_write_cursormove(&ctx, x, y);
 | 
			
		||||
 | 
			
		||||
			memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
			colour_set_fg(&gc, colour);
 | 
			
		||||
			gc.fg = colour;
 | 
			
		||||
			screen_write_puts(&ctx, &gc, "%s", tim);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +242,7 @@ window_clock_draw_screen(struct window_pane *wp)
 | 
			
		||||
	y = (screen_size_y(s) / 2) - 3;
 | 
			
		||||
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	colour_set_bg(&gc, colour);
 | 
			
		||||
	gc.bg = colour;
 | 
			
		||||
	for (ptr = tim; *ptr != '\0'; ptr++) {
 | 
			
		||||
		if (*ptr >= '0' && *ptr <= '9')
 | 
			
		||||
			idx = *ptr - '0';
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user