mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Long overdue change to the way we store cells in the grid: now, instead
of storing a full grid_cell with UTF-8 data and everything, store a new type grid_cell_entry. This can either be the cell itself (for ASCII cells), or an offset into an extended array (per line) for UTF-8 data. This avoid a large (8 byte) overhead on non-UTF-8 cells (by far the majority for most users) without the complexity of the shadow array we had before. Grid memory without any UTF-8 is about half. The disadvantage that cells can no longer be modified in place and need to be copied out of the grid and back but it turned out to be lot less complicated than I expected.
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							@@ -76,7 +76,6 @@ SRCS=	alerts.c \
 | 
			
		||||
	control-notify.c \
 | 
			
		||||
	environ.c \
 | 
			
		||||
	format.c \
 | 
			
		||||
	grid-cell.c \
 | 
			
		||||
	grid-view.c \
 | 
			
		||||
	grid.c \
 | 
			
		||||
	input-keys.c \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								format.c
									
									
									
									
									
								
							@@ -415,6 +415,7 @@ format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
 | 
			
		||||
	for (i = 0; i < gd->hsize; i++) {
 | 
			
		||||
		gl = &gd->linedata[i];
 | 
			
		||||
		size += gl->cellsize * sizeof *gl->celldata;
 | 
			
		||||
		size += gl->extdsize * sizeof *gl->extddata;
 | 
			
		||||
	}
 | 
			
		||||
	size += gd->hsize * sizeof *gd->linedata;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								grid-cell.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								grid-cell.c
									
									
									
									
									
								
							@@ -1,55 +0,0 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
/* Get cell width. */
 | 
			
		||||
u_int
 | 
			
		||||
grid_cell_width(const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	return (gc->xstate >> 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell data. */
 | 
			
		||||
void
 | 
			
		||||
grid_cell_get(const struct grid_cell *gc, struct utf8_data *ud)
 | 
			
		||||
{
 | 
			
		||||
	ud->size = gc->xstate & 0xf;
 | 
			
		||||
	ud->width = gc->xstate >> 4;
 | 
			
		||||
	memcpy(ud->data, gc->xdata, ud->size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set cell data. */
 | 
			
		||||
void
 | 
			
		||||
grid_cell_set(struct grid_cell *gc, const struct utf8_data *ud)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(gc->xdata, ud->data, ud->size);
 | 
			
		||||
	gc->xstate = (ud->width << 4) | ud->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set a single character as cell data. */
 | 
			
		||||
void
 | 
			
		||||
grid_cell_one(struct grid_cell *gc, u_char ch)
 | 
			
		||||
{
 | 
			
		||||
	*gc->xdata = ch;
 | 
			
		||||
	gc->xstate = (1 << 4) | 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								grid-view.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								grid-view.c
									
									
									
									
									
								
							@@ -30,24 +30,17 @@
 | 
			
		||||
#define grid_view_x(gd, x) (x)
 | 
			
		||||
#define grid_view_y(gd, y) ((gd)->hsize + (y))
 | 
			
		||||
 | 
			
		||||
/* Get cell for reading. */
 | 
			
		||||
const struct grid_cell *
 | 
			
		||||
grid_view_peek_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
/* Get cel. */
 | 
			
		||||
void
 | 
			
		||||
grid_view_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell for writing. */
 | 
			
		||||
struct grid_cell *
 | 
			
		||||
grid_view_get_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	return (grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
 | 
			
		||||
	grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set cell. */
 | 
			
		||||
void
 | 
			
		||||
grid_view_set_cell(
 | 
			
		||||
    struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
 | 
			
		||||
grid_view_set_cell(struct grid *gd, u_int px, u_int py,
 | 
			
		||||
    const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										169
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								grid.c
									
									
									
									
									
								
							@@ -36,15 +36,17 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Default grid cell data. */
 | 
			
		||||
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " };
 | 
			
		||||
 | 
			
		||||
#define grid_put_cell(gd, px, py, gc) do {			\
 | 
			
		||||
	memcpy(&gd->linedata[py].celldata[px], 			\
 | 
			
		||||
	    gc, sizeof gd->linedata[py].celldata[px]);		\
 | 
			
		||||
} while (0)
 | 
			
		||||
const struct grid_cell grid_default_cell = {
 | 
			
		||||
	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);
 | 
			
		||||
void	grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int,
 | 
			
		||||
	    u_int);
 | 
			
		||||
@@ -54,6 +56,13 @@ size_t	grid_string_cells_bg(const struct grid_cell *, int *);
 | 
			
		||||
void	grid_string_cells_code(const struct grid_cell *,
 | 
			
		||||
	    const struct grid_cell *, char *, size_t, int);
 | 
			
		||||
 | 
			
		||||
/* Copy default into a cell. */
 | 
			
		||||
static void
 | 
			
		||||
grid_clear_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	gd->linedata[py].celldata[px] = grid_default_entry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check grid y position. */
 | 
			
		||||
int
 | 
			
		||||
grid_check_y(struct grid *gd, u_int py)
 | 
			
		||||
@@ -95,6 +104,7 @@ grid_destroy(struct grid *gd)
 | 
			
		||||
	for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
 | 
			
		||||
		gl = &gd->linedata[yy];
 | 
			
		||||
		free(gl->celldata);
 | 
			
		||||
		free(gl->extddata);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free(gd->linedata);
 | 
			
		||||
@@ -107,7 +117,7 @@ int
 | 
			
		||||
grid_compare(struct grid *ga, struct grid *gb)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_line	*gla, *glb;
 | 
			
		||||
	struct grid_cell	*gca, *gcb;
 | 
			
		||||
	struct grid_cell	 gca, gcb;
 | 
			
		||||
	u_int			 xx, yy;
 | 
			
		||||
 | 
			
		||||
	if (ga->sx != gb->sx || ga->sy != gb->sy)
 | 
			
		||||
@@ -118,10 +128,10 @@ grid_compare(struct grid *ga, struct grid *gb)
 | 
			
		||||
		glb = &gb->linedata[yy];
 | 
			
		||||
		if (gla->cellsize != glb->cellsize)
 | 
			
		||||
			return (1);
 | 
			
		||||
		for (xx = 0; xx < ga->sx; xx++) {
 | 
			
		||||
			gca = &gla->celldata[xx];
 | 
			
		||||
			gcb = &glb->celldata[xx];
 | 
			
		||||
			if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0)
 | 
			
		||||
		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)
 | 
			
		||||
				return (1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -224,7 +234,7 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
 | 
			
		||||
 | 
			
		||||
	gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
 | 
			
		||||
	for (xx = gl->cellsize; xx < sx; xx++)
 | 
			
		||||
		grid_put_cell(gd, xx, py, &grid_default_cell);
 | 
			
		||||
		grid_clear_cell(gd, xx, py);
 | 
			
		||||
	gl->cellsize = sx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -238,37 +248,72 @@ grid_peek_line(struct grid *gd, u_int py)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get cell for reading. */
 | 
			
		||||
const struct grid_cell *
 | 
			
		||||
grid_peek_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
void
 | 
			
		||||
grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	if (grid_check_y(gd, py) != 0)
 | 
			
		||||
		return (&grid_default_cell);
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct grid_cell_entry	*gce;
 | 
			
		||||
 | 
			
		||||
	if (px >= gd->linedata[py].cellsize)
 | 
			
		||||
		return (&grid_default_cell);
 | 
			
		||||
	return (&gd->linedata[py].celldata[px]);
 | 
			
		||||
}
 | 
			
		||||
	if (grid_check_y(gd, py) != 0 || px >= gd->linedata[py].cellsize) {
 | 
			
		||||
		memcpy(gc, &grid_default_cell, sizeof *gc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/* Get cell at relative position (for writing). */
 | 
			
		||||
struct grid_cell *
 | 
			
		||||
grid_get_cell(struct grid *gd, u_int px, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	if (grid_check_y(gd, py) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	gl = &gd->linedata[py];
 | 
			
		||||
	gce = &gl->celldata[px];
 | 
			
		||||
 | 
			
		||||
	grid_expand_line(gd, py, px + 1);
 | 
			
		||||
	return (&gd->linedata[py].celldata[px]);
 | 
			
		||||
	if (gce->flags & GRID_FLAG_EXTENDED) {
 | 
			
		||||
		if (gce->offset >= gl->extdsize)
 | 
			
		||||
			memcpy(gc, &grid_default_cell, sizeof *gc);
 | 
			
		||||
		else
 | 
			
		||||
			memcpy(gc, &gl->extddata[gce->offset], sizeof *gc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
 | 
			
		||||
	gc->attr = gce->data.attr;
 | 
			
		||||
	gc->fg = gce->data.fg;
 | 
			
		||||
	gc->bg = gce->data.bg;
 | 
			
		||||
	utf8_set(&gc->data, gce->data.data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set cell at relative position. */
 | 
			
		||||
void
 | 
			
		||||
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct grid_cell_entry	*gce;
 | 
			
		||||
	struct grid_cell 	*gcp;
 | 
			
		||||
 | 
			
		||||
	if (grid_check_y(gd, py) != 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	grid_expand_line(gd, py, px + 1);
 | 
			
		||||
	grid_put_cell(gd, px, py, gc);
 | 
			
		||||
 | 
			
		||||
	gl = &gd->linedata[py];
 | 
			
		||||
	gce = &gl->celldata[px];
 | 
			
		||||
 | 
			
		||||
	if ((gce->flags & GRID_FLAG_EXTENDED) || gc->data.size != 1 ||
 | 
			
		||||
	    gc->data.width != 1) {
 | 
			
		||||
		if (~gce->flags & GRID_FLAG_EXTENDED) {
 | 
			
		||||
			gl->extddata = xreallocarray(gl->extddata,
 | 
			
		||||
			    gl->extdsize + 1, sizeof *gl->extddata);
 | 
			
		||||
			gce->offset = gl->extdsize++;
 | 
			
		||||
			gce->flags = gc->flags | GRID_FLAG_EXTENDED;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (gce->offset >= gl->extdsize)
 | 
			
		||||
			fatalx("offset too big");
 | 
			
		||||
		gcp = &gl->extddata[gce->offset];
 | 
			
		||||
		memcpy(gcp, gc, sizeof *gcp);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
 | 
			
		||||
	gce->data.attr = gc->attr;
 | 
			
		||||
	gce->data.fg = gc->fg;
 | 
			
		||||
	gce->data.bg = gc->bg;
 | 
			
		||||
	gce->data.data = gc->data.data[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear area. */
 | 
			
		||||
@@ -300,7 +345,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
 | 
			
		||||
		for (xx = px; xx < px + nx; xx++) {
 | 
			
		||||
			if (xx >= gd->linedata[yy].cellsize)
 | 
			
		||||
				break;
 | 
			
		||||
			grid_put_cell(gd, xx, yy, &grid_default_cell);
 | 
			
		||||
			grid_clear_cell(gd, xx, yy);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -324,6 +369,10 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
 | 
			
		||||
		gl = &gd->linedata[yy];
 | 
			
		||||
		free(gl->celldata);
 | 
			
		||||
		memset(gl, 0, sizeof *gl);
 | 
			
		||||
 | 
			
		||||
		free(gl->extddata);
 | 
			
		||||
		gl->extddata = NULL;
 | 
			
		||||
		gl->extdsize = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -386,7 +435,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
 | 
			
		||||
	for (xx = px; xx < px + nx; xx++) {
 | 
			
		||||
		if (xx >= dx && xx < dx + nx)
 | 
			
		||||
			continue;
 | 
			
		||||
		grid_put_cell(gd, xx, py, &grid_default_cell);
 | 
			
		||||
		grid_clear_cell(gd, xx, py);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -568,9 +617,8 @@ char *
 | 
			
		||||
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
 | 
			
		||||
    struct grid_cell **lastgc, int with_codes, int escape_c0, int trim)
 | 
			
		||||
{
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
	static struct grid_cell	 lastgc1;
 | 
			
		||||
	struct utf8_data	 ud;
 | 
			
		||||
	const char		*data;
 | 
			
		||||
	char			*buf, code[128];
 | 
			
		||||
	size_t			 len, off, size, codelen;
 | 
			
		||||
@@ -590,21 +638,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
 | 
			
		||||
	for (xx = px; xx < px + nx; xx++) {
 | 
			
		||||
		if (gl == NULL || xx >= gl->cellsize)
 | 
			
		||||
			break;
 | 
			
		||||
		gc = &gl->celldata[xx];
 | 
			
		||||
		if (gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
		grid_get_cell(gd, xx, py, &gc);
 | 
			
		||||
		if (gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
			continue;
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
 | 
			
		||||
		if (with_codes) {
 | 
			
		||||
			grid_string_cells_code(*lastgc, gc, code, sizeof code,
 | 
			
		||||
			grid_string_cells_code(*lastgc, &gc, code, sizeof code,
 | 
			
		||||
			    escape_c0);
 | 
			
		||||
			codelen = strlen(code);
 | 
			
		||||
			memcpy(*lastgc, gc, sizeof *gc);
 | 
			
		||||
			memcpy(*lastgc, &gc, sizeof **lastgc);
 | 
			
		||||
		} else
 | 
			
		||||
			codelen = 0;
 | 
			
		||||
 | 
			
		||||
		data = ud.data;
 | 
			
		||||
		size = ud.size;
 | 
			
		||||
		data = gc.data.data;
 | 
			
		||||
		size = gc.data.size;
 | 
			
		||||
		if (escape_c0 && size == 1 && *data == '\\') {
 | 
			
		||||
			data = "\\\\";
 | 
			
		||||
			size = 2;
 | 
			
		||||
@@ -663,11 +710,44 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
 | 
			
		||||
		} else
 | 
			
		||||
			dstl->celldata = NULL;
 | 
			
		||||
 | 
			
		||||
		if (srcl->extdsize != 0) {
 | 
			
		||||
			dstl->extdsize = srcl->extdsize;
 | 
			
		||||
			dstl->extddata = xreallocarray(NULL, dstl->extdsize,
 | 
			
		||||
			    sizeof *dstl->extddata);
 | 
			
		||||
			memcpy(dstl->extddata, srcl->extddata, dstl->extdsize *
 | 
			
		||||
			    sizeof *dstl->extddata);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sy++;
 | 
			
		||||
		dy++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Copy a section of a line. */
 | 
			
		||||
void
 | 
			
		||||
grid_reflow_copy(struct grid_line *dst_gl, u_int to, struct grid_line *src_gl,
 | 
			
		||||
    u_int from, u_int to_copy)
 | 
			
		||||
{
 | 
			
		||||
	struct grid_cell_entry	*gce;
 | 
			
		||||
	u_int			 i, was;
 | 
			
		||||
 | 
			
		||||
	memcpy(&dst_gl->celldata[to], &src_gl->celldata[from],
 | 
			
		||||
	    to_copy * sizeof *dst_gl->celldata);
 | 
			
		||||
 | 
			
		||||
	for (i = to; i < to + to_copy; i++) {
 | 
			
		||||
		gce = &dst_gl->celldata[i];
 | 
			
		||||
		if (~gce->flags & GRID_FLAG_EXTENDED)
 | 
			
		||||
			continue;
 | 
			
		||||
		was = gce->offset;
 | 
			
		||||
 | 
			
		||||
		dst_gl->extddata = xreallocarray(dst_gl->extddata,
 | 
			
		||||
		    dst_gl->extdsize + 1, sizeof *dst_gl->extddata);
 | 
			
		||||
		gce->offset = dst_gl->extdsize++;
 | 
			
		||||
		memcpy(&dst_gl->extddata[gce->offset], &src_gl->extddata[was],
 | 
			
		||||
		    sizeof *dst_gl->extddata);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Join line data. */
 | 
			
		||||
void
 | 
			
		||||
grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
 | 
			
		||||
@@ -692,8 +772,7 @@ grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
 | 
			
		||||
	dst_gl->cellsize = nx;
 | 
			
		||||
 | 
			
		||||
	/* Append as much as possible. */
 | 
			
		||||
	memcpy(&dst_gl->celldata[ox], &src_gl->celldata[0],
 | 
			
		||||
	    to_copy * sizeof src_gl->celldata[0]);
 | 
			
		||||
	grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy);
 | 
			
		||||
 | 
			
		||||
	/* If there is any left in the source, split it. */
 | 
			
		||||
	if (src_gl->cellsize > to_copy) {
 | 
			
		||||
@@ -732,8 +811,7 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
 | 
			
		||||
		dst_gl->flags |= GRID_LINE_WRAPPED;
 | 
			
		||||
 | 
			
		||||
		/* Copy the data. */
 | 
			
		||||
		memcpy(&dst_gl->celldata[0], &src_gl->celldata[offset],
 | 
			
		||||
		    to_copy * sizeof dst_gl->celldata[0]);
 | 
			
		||||
		grid_reflow_copy(dst_gl, 0, src_gl, offset, to_copy);
 | 
			
		||||
 | 
			
		||||
		/* Move offset and reduce old line size. */
 | 
			
		||||
		offset += to_copy;
 | 
			
		||||
@@ -763,6 +841,7 @@ grid_reflow_move(struct grid *dst, u_int *py, struct grid_line *src_gl)
 | 
			
		||||
 | 
			
		||||
	/* Clear old line. */
 | 
			
		||||
	src_gl->celldata = NULL;
 | 
			
		||||
	src_gl->extddata = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -792,7 +871,7 @@ grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
 | 
			
		||||
			/* Previous was wrapped. Try to join. */
 | 
			
		||||
			grid_reflow_join(dst, &py, src_gl, new_x);
 | 
			
		||||
		}
 | 
			
		||||
		previous_wrapped = src_gl->flags & GRID_LINE_WRAPPED;
 | 
			
		||||
		previous_wrapped = (src_gl->flags & GRID_LINE_WRAPPED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	grid_destroy(src);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								input.c
									
									
									
									
									
								
							@@ -1006,7 +1006,7 @@ input_print(struct input_ctx *ictx)
 | 
			
		||||
	else
 | 
			
		||||
		ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
 | 
			
		||||
 | 
			
		||||
	grid_cell_one(&ictx->cell.cell, ictx->ch);
 | 
			
		||||
	utf8_set(&ictx->cell.cell.data, ictx->ch);
 | 
			
		||||
	screen_write_cell(&ictx->ctx, &ictx->cell.cell);
 | 
			
		||||
 | 
			
		||||
	ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
 | 
			
		||||
@@ -1945,7 +1945,7 @@ input_utf8_close(struct input_ctx *ictx)
 | 
			
		||||
 | 
			
		||||
	utf8_append(&ictx->utf8data, ictx->ch);
 | 
			
		||||
 | 
			
		||||
	grid_cell_set(&ictx->cell.cell, &ictx->utf8data);
 | 
			
		||||
	utf8_copy(&ictx->cell.cell.data, &ictx->utf8data);
 | 
			
		||||
	screen_write_cell(&ictx->ctx, &ictx->cell.cell);
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ void
 | 
			
		||||
screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
 | 
			
		||||
    u_char ch)
 | 
			
		||||
{
 | 
			
		||||
	grid_cell_one(gc, ch);
 | 
			
		||||
	utf8_set(&gc->data, ch);
 | 
			
		||||
	screen_write_cell(ctx, gc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -126,7 +126,7 @@ screen_write_strlen(const char *fmt, ...)
 | 
			
		||||
			ptr++;
 | 
			
		||||
 | 
			
		||||
			left = strlen(ptr);
 | 
			
		||||
			if (left < ud.size - 1)
 | 
			
		||||
			if (left < (size_t)ud.size - 1)
 | 
			
		||||
				break;
 | 
			
		||||
			while (utf8_append(&ud, *ptr))
 | 
			
		||||
				ptr++;
 | 
			
		||||
@@ -185,7 +185,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
 | 
			
		||||
			ptr++;
 | 
			
		||||
 | 
			
		||||
			left = strlen(ptr);
 | 
			
		||||
			if (left < ud.size - 1)
 | 
			
		||||
			if (left < (size_t)ud.size - 1)
 | 
			
		||||
				break;
 | 
			
		||||
			while (utf8_append(&ud, *ptr))
 | 
			
		||||
				ptr++;
 | 
			
		||||
@@ -201,7 +201,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
 | 
			
		||||
			}
 | 
			
		||||
			size += ud.width;
 | 
			
		||||
 | 
			
		||||
			grid_cell_set(gc, &ud);
 | 
			
		||||
			utf8_copy(&gc->data, &ud);
 | 
			
		||||
			screen_write_cell(ctx, gc);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (maxlen > 0 && size + 1 > (size_t) maxlen)
 | 
			
		||||
@@ -258,7 +258,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
 | 
			
		||||
			ptr++;
 | 
			
		||||
 | 
			
		||||
			left = strlen(ptr);
 | 
			
		||||
			if (left < ud.size - 1)
 | 
			
		||||
			if (left < (size_t)ud.size - 1)
 | 
			
		||||
				break;
 | 
			
		||||
			while (utf8_append(&ud, *ptr))
 | 
			
		||||
				ptr++;
 | 
			
		||||
@@ -274,7 +274,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
 | 
			
		||||
			}
 | 
			
		||||
			size += ud.width;
 | 
			
		||||
 | 
			
		||||
			grid_cell_set(&lgc, &ud);
 | 
			
		||||
			utf8_copy(&lgc.data, &ud);
 | 
			
		||||
			screen_write_cell(ctx, &lgc);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (maxlen > 0 && size + 1 > (size_t) maxlen)
 | 
			
		||||
@@ -299,8 +299,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid		*gd = src->grid;
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	struct utf8_data	 ud;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
	u_int		 	 xx, yy, cx, cy, ax, bx;
 | 
			
		||||
 | 
			
		||||
	cx = s->cx;
 | 
			
		||||
@@ -324,12 +323,8 @@ screen_write_copy(struct screen_write_ctx *ctx,
 | 
			
		||||
				bx = px + nx;
 | 
			
		||||
 | 
			
		||||
			for (xx = ax; xx < bx; xx++) {
 | 
			
		||||
				if (xx >= gl->cellsize)
 | 
			
		||||
					gc = &grid_default_cell;
 | 
			
		||||
				else
 | 
			
		||||
					gc = &gl->celldata[xx];
 | 
			
		||||
				grid_cell_get(gc, &ud);
 | 
			
		||||
				screen_write_cell(ctx, gc);
 | 
			
		||||
				grid_get_cell(gd, xx, yy, &gc);
 | 
			
		||||
				screen_write_cell(ctx, &gc);
 | 
			
		||||
			}
 | 
			
		||||
			if (px + nx == gd->sx && px + nx > gl->cellsize)
 | 
			
		||||
				screen_write_clearendofline(ctx);
 | 
			
		||||
@@ -342,12 +337,12 @@ screen_write_copy(struct screen_write_ctx *ctx,
 | 
			
		||||
 | 
			
		||||
/* Set up context for TTY command. */
 | 
			
		||||
void
 | 
			
		||||
screen_write_initctx(
 | 
			
		||||
    struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last)
 | 
			
		||||
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
 | 
			
		||||
    int save_last)
 | 
			
		||||
{
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid		*gd = s->grid;
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
	u_int			 xx;
 | 
			
		||||
 | 
			
		||||
	ttyctx->wp = ctx->wp;
 | 
			
		||||
@@ -362,14 +357,14 @@ screen_write_initctx(
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Save the last cell on the screen. */
 | 
			
		||||
	gc = &grid_default_cell;
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	for (xx = 1; xx <= screen_size_x(s); xx++) {
 | 
			
		||||
		gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING))
 | 
			
		||||
		grid_view_get_cell(gd, screen_size_x(s) - xx, s->cy, &gc);
 | 
			
		||||
		if (~gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	ttyctx->last_width = xx;
 | 
			
		||||
	memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell);
 | 
			
		||||
	memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set a mode. */
 | 
			
		||||
@@ -507,7 +502,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx, 0);
 | 
			
		||||
 | 
			
		||||
	memcpy(&gc, &grid_default_cell, sizeof gc);
 | 
			
		||||
	grid_cell_one(&gc, 'E');
 | 
			
		||||
	utf8_set(&gc.data, 'E');
 | 
			
		||||
 | 
			
		||||
	for (yy = 0; yy < screen_size_y(s); yy++) {
 | 
			
		||||
		for (xx = 0; xx < screen_size_x(s); xx++)
 | 
			
		||||
@@ -904,14 +899,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;
 | 
			
		||||
	struct grid_cell 	 tmp_gc, *tmp_gcp;
 | 
			
		||||
	struct utf8_data	 ud;
 | 
			
		||||
	struct grid_cell 	 tmp_gc;
 | 
			
		||||
	int			 insert;
 | 
			
		||||
 | 
			
		||||
	/* Ignore padding. */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
		return;
 | 
			
		||||
	width = grid_cell_width(gc);
 | 
			
		||||
	width = gc->data.width;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If this is a wide character and there is no room on the screen, for
 | 
			
		||||
@@ -928,8 +922,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	 * there is space.
 | 
			
		||||
	 */
 | 
			
		||||
	if (width == 0) {
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (screen_write_combine(ctx, &ud) == 0) {
 | 
			
		||||
		if (screen_write_combine(ctx, &gc->data) == 0) {
 | 
			
		||||
			screen_write_initctx(ctx, &ttyctx, 0);
 | 
			
		||||
			tty_write(tty_cmd_utf8character, &ttyctx);
 | 
			
		||||
		}
 | 
			
		||||
@@ -964,11 +957,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	 * If the new character is UTF-8 wide, fill in padding cells. Have
 | 
			
		||||
	 * already ensured there is enough room.
 | 
			
		||||
	 */
 | 
			
		||||
	for (xx = s->cx + 1; xx < s->cx + width; xx++) {
 | 
			
		||||
		tmp_gcp = grid_view_get_cell(gd, xx, s->cy);
 | 
			
		||||
		if (tmp_gcp != NULL)
 | 
			
		||||
			tmp_gcp->flags |= GRID_FLAG_PADDING;
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(&tmp_gc, &grid_default_cell, sizeof tmp_gc);
 | 
			
		||||
	tmp_gc.flags |= GRID_FLAG_PADDING;
 | 
			
		||||
	tmp_gc.data.width = 0;
 | 
			
		||||
	for (xx = s->cx + 1; xx < s->cx + width; xx++)
 | 
			
		||||
		grid_view_set_cell(gd, xx, s->cy, &tmp_gc);
 | 
			
		||||
 | 
			
		||||
	/* Set the cell. */
 | 
			
		||||
	grid_view_set_cell(gd, s->cx, s->cy, gc);
 | 
			
		||||
@@ -990,8 +983,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	}
 | 
			
		||||
	if (screen_check_selection(s, s->cx - width, s->cy)) {
 | 
			
		||||
		memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		grid_cell_set(&tmp_gc, &ud);
 | 
			
		||||
		utf8_copy(&tmp_gc.data, &gc->data);
 | 
			
		||||
		tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
 | 
			
		||||
		tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
 | 
			
		||||
		tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
@@ -1011,8 +1003,7 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
 | 
			
		||||
{
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid		*gd = s->grid;
 | 
			
		||||
	struct grid_cell	*gc;
 | 
			
		||||
	struct utf8_data	 ud1;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
 | 
			
		||||
	/* Can't combine if at 0. */
 | 
			
		||||
	if (s->cx == 0)
 | 
			
		||||
@@ -1023,17 +1014,18 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
 | 
			
		||||
		fatalx("UTF-8 data empty");
 | 
			
		||||
 | 
			
		||||
	/* Retrieve the previous cell. */
 | 
			
		||||
	gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
 | 
			
		||||
	grid_cell_get(gc, &ud1);
 | 
			
		||||
	grid_view_get_cell(gd, s->cx - 1, s->cy, &gc);
 | 
			
		||||
 | 
			
		||||
	/* Check there is enough space. */
 | 
			
		||||
	if (ud1.size + ud->size > sizeof ud1.data)
 | 
			
		||||
	if (gc.data.size + ud->size > sizeof gc.data.data)
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	/* Append the data and set the cell. */
 | 
			
		||||
	memcpy(ud1.data + ud1.size, ud->data, ud->size);
 | 
			
		||||
	ud1.size += ud->size;
 | 
			
		||||
	grid_cell_set(gc, &ud1);
 | 
			
		||||
	/* Append the data. */
 | 
			
		||||
	memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
 | 
			
		||||
	gc.data.size += ud->size;
 | 
			
		||||
 | 
			
		||||
	/* Set the new cell. */
 | 
			
		||||
	grid_view_set_cell(gd, s->cx - 1, s->cy, &gc);
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1052,11 +1044,11 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
 | 
			
		||||
{
 | 
			
		||||
	struct screen		*s = ctx->s;
 | 
			
		||||
	struct grid		*gd = s->grid;
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
	u_int			 xx;
 | 
			
		||||
 | 
			
		||||
	gc = grid_view_peek_cell(gd, s->cx, s->cy);
 | 
			
		||||
	if (gc->flags & GRID_FLAG_PADDING) {
 | 
			
		||||
	grid_view_get_cell(gd, s->cx, s->cy, &gc);
 | 
			
		||||
	if (gc.flags & GRID_FLAG_PADDING) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * A padding cell, so clear any following and leading padding
 | 
			
		||||
		 * cells back to the character. Don't overwrite the current
 | 
			
		||||
@@ -1064,8 +1056,8 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
 | 
			
		||||
		 */
 | 
			
		||||
		xx = s->cx + 1;
 | 
			
		||||
		while (--xx > 0) {
 | 
			
		||||
			gc = grid_view_peek_cell(gd, xx, s->cy);
 | 
			
		||||
			if (!(gc->flags & GRID_FLAG_PADDING))
 | 
			
		||||
			grid_view_get_cell(gd, xx, s->cy, &gc);
 | 
			
		||||
			if (~gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
				break;
 | 
			
		||||
			grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
 | 
			
		||||
		}
 | 
			
		||||
@@ -1080,8 +1072,8 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
 | 
			
		||||
	 */
 | 
			
		||||
	xx = s->cx + width - 1;
 | 
			
		||||
	while (++xx < screen_size_x(s)) {
 | 
			
		||||
		gc = grid_view_peek_cell(gd, xx, s->cy);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING))
 | 
			
		||||
		grid_view_get_cell(gd, xx, s->cy, &gc);
 | 
			
		||||
		if (~gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
			break;
 | 
			
		||||
		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								status.c
									
									
									
									
									
								
							@@ -746,7 +746,7 @@ status_prompt_redraw(struct client *c)
 | 
			
		||||
	struct session		       *s = c->session;
 | 
			
		||||
	struct screen		        old_status;
 | 
			
		||||
	size_t			        i, size, left, len, off;
 | 
			
		||||
	struct grid_cell		gc, *gcp;
 | 
			
		||||
	struct grid_cell		gc;
 | 
			
		||||
 | 
			
		||||
	if (c->tty.sx == 0 || c->tty.sy == 0)
 | 
			
		||||
		return (0);
 | 
			
		||||
@@ -789,8 +789,9 @@ status_prompt_redraw(struct client *c)
 | 
			
		||||
 | 
			
		||||
	/* Apply fake cursor. */
 | 
			
		||||
	off = len + c->prompt_index - off;
 | 
			
		||||
	gcp = grid_view_get_cell(c->status.grid, off, 0);
 | 
			
		||||
	gcp->attr ^= GRID_ATTR_REVERSE;
 | 
			
		||||
	grid_view_get_cell(c->status.grid, off, 0, &gc);
 | 
			
		||||
	gc.attr ^= GRID_ATTR_REVERSE;
 | 
			
		||||
	grid_view_set_cell(c->status.grid, off, 0, &gc);
 | 
			
		||||
 | 
			
		||||
	if (grid_compare(c->status.grid, old_status.grid) == 0) {
 | 
			
		||||
		screen_free(&old_status);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								tmux.h
									
									
									
									
									
								
							@@ -621,11 +621,11 @@ struct mode_key_table {
 | 
			
		||||
struct utf8_data {
 | 
			
		||||
	u_char	data[UTF8_SIZE];
 | 
			
		||||
 | 
			
		||||
	size_t	have;
 | 
			
		||||
	size_t	size;
 | 
			
		||||
	u_char	have;
 | 
			
		||||
	u_char	size;
 | 
			
		||||
 | 
			
		||||
	u_int	width;
 | 
			
		||||
};
 | 
			
		||||
	u_char	width;
 | 
			
		||||
} __packed;
 | 
			
		||||
 | 
			
		||||
/* Grid attributes. */
 | 
			
		||||
#define GRID_ATTR_BRIGHT 0x1
 | 
			
		||||
@@ -641,41 +641,56 @@ struct utf8_data {
 | 
			
		||||
#define GRID_FLAG_FG256 0x1
 | 
			
		||||
#define GRID_FLAG_BG256 0x2
 | 
			
		||||
#define GRID_FLAG_PADDING 0x4
 | 
			
		||||
#define GRID_FLAG_EXTENDED 0x8
 | 
			
		||||
 | 
			
		||||
/* Grid line flags. */
 | 
			
		||||
#define GRID_LINE_WRAPPED 0x1
 | 
			
		||||
 | 
			
		||||
/* Grid cell data. */
 | 
			
		||||
struct grid_cell {
 | 
			
		||||
	u_char	attr;
 | 
			
		||||
	u_char	flags;
 | 
			
		||||
	u_char	fg;
 | 
			
		||||
	u_char	bg;
 | 
			
		||||
	u_char			flags;
 | 
			
		||||
	u_char			attr;
 | 
			
		||||
	u_char			fg;
 | 
			
		||||
	u_char			bg;
 | 
			
		||||
	struct utf8_data	data;
 | 
			
		||||
 | 
			
		||||
	u_char	xstate; /* top 4 bits width, bottom 4 bits size */
 | 
			
		||||
	u_char	xdata[UTF8_SIZE];
 | 
			
		||||
};
 | 
			
		||||
struct grid_cell_entry {
 | 
			
		||||
	u_char			flags;
 | 
			
		||||
	union {
 | 
			
		||||
		u_int		offset;
 | 
			
		||||
		struct {
 | 
			
		||||
			u_char	attr;
 | 
			
		||||
			u_char	fg;
 | 
			
		||||
			u_char	bg;
 | 
			
		||||
			u_char	data;
 | 
			
		||||
		} data;
 | 
			
		||||
	};
 | 
			
		||||
} __packed;
 | 
			
		||||
 | 
			
		||||
/* Grid line. */
 | 
			
		||||
struct grid_line {
 | 
			
		||||
	u_int	cellsize;
 | 
			
		||||
	struct grid_cell *celldata;
 | 
			
		||||
	u_int			 cellsize;
 | 
			
		||||
	struct grid_cell_entry	*celldata;
 | 
			
		||||
 | 
			
		||||
	int	flags;
 | 
			
		||||
	u_int			 extdsize;
 | 
			
		||||
	struct grid_cell	*extddata;
 | 
			
		||||
 | 
			
		||||
	int			 flags;
 | 
			
		||||
} __packed;
 | 
			
		||||
 | 
			
		||||
/* Entire grid of cells. */
 | 
			
		||||
struct grid {
 | 
			
		||||
	int	flags;
 | 
			
		||||
#define GRID_HISTORY 0x1	/* scroll lines into history */
 | 
			
		||||
	int			 flags;
 | 
			
		||||
#define GRID_HISTORY 0x1 /* scroll lines into history */
 | 
			
		||||
 | 
			
		||||
	u_int	sx;
 | 
			
		||||
	u_int	sy;
 | 
			
		||||
	u_int			 sx;
 | 
			
		||||
	u_int			 sy;
 | 
			
		||||
 | 
			
		||||
	u_int	hsize;
 | 
			
		||||
	u_int	hlimit;
 | 
			
		||||
	u_int			 hsize;
 | 
			
		||||
	u_int			 hlimit;
 | 
			
		||||
 | 
			
		||||
	struct grid_line *linedata;
 | 
			
		||||
	struct grid_line	*linedata;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Option data structures. */
 | 
			
		||||
@@ -1854,9 +1869,8 @@ void	 grid_scroll_history(struct grid *);
 | 
			
		||||
void	 grid_scroll_history_region(struct grid *, u_int, u_int);
 | 
			
		||||
void	 grid_clear_history(struct grid *);
 | 
			
		||||
void	 grid_expand_line(struct grid *, u_int, u_int);
 | 
			
		||||
const struct grid_cell *grid_peek_cell(struct grid *, u_int, u_int);
 | 
			
		||||
const struct grid_line *grid_peek_line(struct grid *, u_int);
 | 
			
		||||
struct grid_cell *grid_get_cell(struct grid *, u_int, u_int);
 | 
			
		||||
void	 grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
 | 
			
		||||
void	 grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
 | 
			
		||||
void	 grid_clear(struct grid *, u_int, u_int, u_int, u_int);
 | 
			
		||||
void	 grid_clear_lines(struct grid *, u_int, u_int);
 | 
			
		||||
@@ -1868,17 +1882,10 @@ void	 grid_duplicate_lines(
 | 
			
		||||
	     struct grid *, u_int, struct grid *, u_int, u_int);
 | 
			
		||||
u_int	 grid_reflow(struct grid *, struct grid *, u_int);
 | 
			
		||||
 | 
			
		||||
/* grid-cell.c */
 | 
			
		||||
u_int	 grid_cell_width(const struct grid_cell *);
 | 
			
		||||
void	 grid_cell_get(const struct grid_cell *, struct utf8_data *);
 | 
			
		||||
void	 grid_cell_set(struct grid_cell *, const struct utf8_data *);
 | 
			
		||||
void	 grid_cell_one(struct grid_cell *, u_char);
 | 
			
		||||
 | 
			
		||||
/* grid-view.c */
 | 
			
		||||
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int);
 | 
			
		||||
struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int);
 | 
			
		||||
void	 grid_view_set_cell(
 | 
			
		||||
	     struct grid *, u_int, u_int, const struct grid_cell *);
 | 
			
		||||
void	 grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
 | 
			
		||||
void	 grid_view_set_cell(struct grid *, u_int, u_int,
 | 
			
		||||
	     const struct grid_cell *);
 | 
			
		||||
void	 grid_view_clear_history(struct grid *);
 | 
			
		||||
void	 grid_view_clear(struct grid *, u_int, u_int, u_int, u_int);
 | 
			
		||||
void	 grid_view_scroll_region_up(struct grid *, u_int, u_int);
 | 
			
		||||
@@ -2183,6 +2190,7 @@ void		 session_renumber_windows(struct session *);
 | 
			
		||||
/* utf8.c */
 | 
			
		||||
u_int		 utf8_width(u_int);
 | 
			
		||||
void		 utf8_set(struct utf8_data *, u_char);
 | 
			
		||||
void		 utf8_copy(struct utf8_data *, const struct utf8_data *);
 | 
			
		||||
int		 utf8_open(struct utf8_data *, u_char);
 | 
			
		||||
int		 utf8_append(struct utf8_data *, u_char);
 | 
			
		||||
u_int		 utf8_combine(const struct utf8_data *);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								tty.c
									
									
									
									
									
								
							@@ -656,10 +656,8 @@ void
 | 
			
		||||
tty_draw_line(struct tty *tty, const struct window_pane *wp,
 | 
			
		||||
    struct screen *s, u_int py, u_int ox, u_int oy)
 | 
			
		||||
{
 | 
			
		||||
	const struct grid_cell	*gc;
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
	struct grid_line	*gl;
 | 
			
		||||
	struct grid_cell	 tmpgc;
 | 
			
		||||
	struct utf8_data	 ud;
 | 
			
		||||
	u_int			 i, sx;
 | 
			
		||||
	int			 flags;
 | 
			
		||||
 | 
			
		||||
@@ -686,18 +684,13 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
 | 
			
		||||
		tty_cursor(tty, ox, oy + py);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sx; i++) {
 | 
			
		||||
		gc = grid_view_peek_cell(s->grid, i, py);
 | 
			
		||||
		grid_view_get_cell(s->grid, i, py, &gc);
 | 
			
		||||
		if (screen_check_selection(s, i, py)) {
 | 
			
		||||
			memcpy(&tmpgc, &s->sel.cell, sizeof tmpgc);
 | 
			
		||||
			grid_cell_get(gc, &ud);
 | 
			
		||||
			grid_cell_set(&tmpgc, &ud);
 | 
			
		||||
			tmpgc.flags = gc->flags &
 | 
			
		||||
			    ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			tmpgc.flags |= s->sel.cell.flags &
 | 
			
		||||
			gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			gc.flags |= s->sel.cell.flags &
 | 
			
		||||
			    (GRID_FLAG_FG256|GRID_FLAG_BG256);
 | 
			
		||||
			tty_cell(tty, &tmpgc, wp);
 | 
			
		||||
		} else
 | 
			
		||||
			tty_cell(tty, gc, wp);
 | 
			
		||||
		}
 | 
			
		||||
		tty_cell(tty, &gc, wp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sx < tty->sx) {
 | 
			
		||||
@@ -1078,7 +1071,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
 | 
			
		||||
	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
 | 
			
		||||
 | 
			
		||||
	/* Is the cursor in the very last position? */
 | 
			
		||||
	width = grid_cell_width(ctx->cell);
 | 
			
		||||
	width = ctx->cell->data.width;
 | 
			
		||||
	if (ctx->ocx > wp->sx - width) {
 | 
			
		||||
		if (ctx->xoff != 0 || wp->sx != tty->sx) {
 | 
			
		||||
			/*
 | 
			
		||||
@@ -1095,7 +1088,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
 | 
			
		||||
			 * move as far left as possible and redraw the last
 | 
			
		||||
			 * cell to move into the last position.
 | 
			
		||||
			 */
 | 
			
		||||
			cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell);
 | 
			
		||||
			cx = screen_size_x(s) - ctx->last_cell.data.width;
 | 
			
		||||
			tty_cursor_pane(tty, ctx, cx, ctx->ocy);
 | 
			
		||||
			tty_cell(tty, &ctx->last_cell, wp);
 | 
			
		||||
		}
 | 
			
		||||
@@ -1155,8 +1148,7 @@ void
 | 
			
		||||
tty_cell(struct tty *tty, const struct grid_cell *gc,
 | 
			
		||||
    const struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct utf8_data	ud;
 | 
			
		||||
	u_int			i;
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	/* Skip last character if terminal is stupid. */
 | 
			
		||||
	if (tty->term->flags & TERM_EARLYWRAP &&
 | 
			
		||||
@@ -1171,23 +1163,22 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
 | 
			
		||||
	tty_attributes(tty, gc, wp);
 | 
			
		||||
 | 
			
		||||
	/* Get the cell and if ASCII write with putc to do ACS translation. */
 | 
			
		||||
	grid_cell_get(gc, &ud);
 | 
			
		||||
	if (ud.size == 1) {
 | 
			
		||||
		if (*ud.data < 0x20 || *ud.data == 0x7f)
 | 
			
		||||
	if (gc->data.size == 1) {
 | 
			
		||||
		if (*gc->data.data < 0x20 || *gc->data.data == 0x7f)
 | 
			
		||||
			return;
 | 
			
		||||
		tty_putc(tty, *ud.data);
 | 
			
		||||
		tty_putc(tty, *gc->data.data);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If not UTF-8, write _. */
 | 
			
		||||
	if (!(tty->flags & TTY_UTF8)) {
 | 
			
		||||
		for (i = 0; i < ud.width; i++)
 | 
			
		||||
		for (i = 0; i < gc->data.width; i++)
 | 
			
		||||
			tty_putc(tty, '_');
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Write the data. */
 | 
			
		||||
	tty_putn(tty, ud.data, ud.size, ud.width);
 | 
			
		||||
	tty_putn(tty, gc->data.data, gc->data.size, gc->data.width);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								utf8.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								utf8.c
									
									
									
									
									
								
							@@ -352,10 +352,27 @@ static void	utf8_build(void);
 | 
			
		||||
void
 | 
			
		||||
utf8_set(struct utf8_data *ud, u_char ch)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	*ud->data = ch;
 | 
			
		||||
	ud->size = 1;
 | 
			
		||||
 | 
			
		||||
	ud->width = 1;
 | 
			
		||||
 | 
			
		||||
	for (i = ud->size; i < sizeof ud->data; i++)
 | 
			
		||||
		ud->data[i] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Copy UTF-8 character. */
 | 
			
		||||
void
 | 
			
		||||
utf8_copy(struct utf8_data *to, const struct utf8_data *from)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i;
 | 
			
		||||
 | 
			
		||||
	memcpy(to, from, sizeof *to);
 | 
			
		||||
 | 
			
		||||
	for (i = to->size; i < sizeof to->data; i++)
 | 
			
		||||
		to->data[i] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								window-copy.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								window-copy.c
									
									
									
									
									
								
							@@ -942,21 +942,21 @@ int
 | 
			
		||||
window_copy_search_compare(struct grid *gd, u_int px, u_int py,
 | 
			
		||||
    struct grid *sgd, u_int spx, int cis)
 | 
			
		||||
{
 | 
			
		||||
	const struct grid_cell	*gc, *sgc;
 | 
			
		||||
	struct utf8_data	 ud, sud;
 | 
			
		||||
	struct grid_cell	 gc, sgc;
 | 
			
		||||
	const struct utf8_data	*ud, *sud;
 | 
			
		||||
 | 
			
		||||
	gc = grid_peek_cell(gd, px, py);
 | 
			
		||||
	grid_cell_get(gc, &ud);
 | 
			
		||||
	sgc = grid_peek_cell(sgd, spx, 0);
 | 
			
		||||
	grid_cell_get(sgc, &sud);
 | 
			
		||||
	grid_get_cell(gd, px, py, &gc);
 | 
			
		||||
	ud = &gc.data;
 | 
			
		||||
	grid_get_cell(sgd, spx, 0, &sgc);
 | 
			
		||||
	sud = &sgc.data;
 | 
			
		||||
 | 
			
		||||
	if (ud.size != sud.size || ud.width != sud.width)
 | 
			
		||||
	if (ud->size != sud->size || ud->width != sud->width)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (cis && ud.size == 1)
 | 
			
		||||
		return (tolower(ud.data[0]) == sud.data[0]);
 | 
			
		||||
	if (cis && ud->size == 1)
 | 
			
		||||
		return (tolower(ud->data[0]) == sud->data[0]);
 | 
			
		||||
 | 
			
		||||
	return (memcmp(ud.data, sud.data, ud.size) == 0);
 | 
			
		||||
	return (memcmp(ud->data, sud->data, ud->size) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
@@ -1541,12 +1541,12 @@ window_copy_append_selection(struct window_pane *wp, const char *bufname)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_copy_copy_line(struct window_pane *wp,
 | 
			
		||||
    char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
 | 
			
		||||
window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy,
 | 
			
		||||
    u_int sx, u_int ex)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct grid			*gd = data->backing->grid;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	struct grid_line		*gl;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	u_int				 i, xx, wrapped = 0;
 | 
			
		||||
@@ -1575,11 +1575,11 @@ window_copy_copy_line(struct window_pane *wp,
 | 
			
		||||
 | 
			
		||||
	if (sx < ex) {
 | 
			
		||||
		for (i = sx; i < ex; i++) {
 | 
			
		||||
			gc = grid_peek_cell(gd, i, sy);
 | 
			
		||||
			if (gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
			grid_get_cell(gd, i, sy, &gc);
 | 
			
		||||
			if (gc.flags & GRID_FLAG_PADDING)
 | 
			
		||||
				continue;
 | 
			
		||||
			grid_cell_get(gc, &ud);
 | 
			
		||||
			if (ud.size == 1 && (gc->attr & GRID_ATTR_CHARSET)) {
 | 
			
		||||
			utf8_copy(&ud, &gc.data);
 | 
			
		||||
			if (ud.size == 1 && (gc.attr & GRID_ATTR_CHARSET)) {
 | 
			
		||||
				s = tty_acs_get(NULL, ud.data[0]);
 | 
			
		||||
				if (s != NULL && strlen(s) <= sizeof ud.data) {
 | 
			
		||||
					ud.size = strlen(s);
 | 
			
		||||
@@ -1618,16 +1618,17 @@ int
 | 
			
		||||
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	const struct utf8_data		*ud;
 | 
			
		||||
 | 
			
		||||
	gc = grid_peek_cell(data->backing->grid, px, py);
 | 
			
		||||
	grid_cell_get(gc, &ud);
 | 
			
		||||
	if (ud.size != 1 || gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
	grid_get_cell(data->backing->grid, px, py, &gc);
 | 
			
		||||
 | 
			
		||||
	ud = &gc.data;
 | 
			
		||||
	if (ud->size != 1 || (gc.flags & GRID_FLAG_PADDING))
 | 
			
		||||
		return (0);
 | 
			
		||||
	if (*ud.data == 0x00 || *ud.data == 0x7f)
 | 
			
		||||
	if (*ud->data == 0x00 || *ud->data == 0x7f)
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (strchr(set, *ud.data) != NULL);
 | 
			
		||||
	return (strchr(set, *ud->data) != NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u_int
 | 
			
		||||
@@ -1635,8 +1636,7 @@ window_copy_find_length(struct window_pane *wp, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct screen			*s = data->backing;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 px;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -1649,9 +1649,8 @@ window_copy_find_length(struct window_pane *wp, u_int py)
 | 
			
		||||
	if (px > screen_size_x(s))
 | 
			
		||||
		px = screen_size_x(s);
 | 
			
		||||
	while (px > 0) {
 | 
			
		||||
		gc = grid_peek_cell(s->grid, px - 1, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (ud.size != 1 || *ud.data != ' ')
 | 
			
		||||
		grid_get_cell(s->grid, px - 1, py, &gc);
 | 
			
		||||
		if (gc.data.size != 1 || *gc.data.data != ' ')
 | 
			
		||||
			break;
 | 
			
		||||
		px--;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1685,17 +1684,15 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	u_int				 px, py, xx;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
 | 
			
		||||
	px = 0;
 | 
			
		||||
	py = screen_hsize(data->backing) + data->cy - data->oy;
 | 
			
		||||
	xx = window_copy_find_length(wp, py);
 | 
			
		||||
 | 
			
		||||
	while (px < xx) {
 | 
			
		||||
		gc = grid_peek_cell(data->backing->grid, px, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (ud.size != 1 || *ud.data != ' ')
 | 
			
		||||
		grid_get_cell(data->backing->grid, px, py, &gc);
 | 
			
		||||
		if (gc.data.size != 1 || *gc.data.data != ' ')
 | 
			
		||||
			break;
 | 
			
		||||
		px++;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1909,8 +1906,7 @@ window_copy_cursor_jump(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct screen			*back_s = data->backing;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 px, py, xx;
 | 
			
		||||
 | 
			
		||||
	px = data->cx + 1;
 | 
			
		||||
@@ -1918,10 +1914,9 @@ window_copy_cursor_jump(struct window_pane *wp)
 | 
			
		||||
	xx = window_copy_find_length(wp, py);
 | 
			
		||||
 | 
			
		||||
	while (px < xx) {
 | 
			
		||||
		gc = grid_peek_cell(back_s->grid, px, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    ud.size == 1 && *ud.data == data->jumpchar) {
 | 
			
		||||
		grid_get_cell(back_s->grid, px, py, &gc);
 | 
			
		||||
		if (!(gc.flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    gc.data.size == 1 && *gc.data.data == data->jumpchar) {
 | 
			
		||||
			window_copy_update_cursor(wp, px, data->cy);
 | 
			
		||||
			if (window_copy_update_selection(wp, 1))
 | 
			
		||||
				window_copy_redraw_lines(wp, data->cy, 1);
 | 
			
		||||
@@ -1936,8 +1931,7 @@ window_copy_cursor_jump_back(struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct screen			*back_s = data->backing;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 px, py;
 | 
			
		||||
 | 
			
		||||
	px = data->cx;
 | 
			
		||||
@@ -1947,10 +1941,9 @@ window_copy_cursor_jump_back(struct window_pane *wp)
 | 
			
		||||
		px--;
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		gc = grid_peek_cell(back_s->grid, px, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    ud.size == 1 && *ud.data == data->jumpchar) {
 | 
			
		||||
		grid_get_cell(back_s->grid, px, py, &gc);
 | 
			
		||||
		if (!(gc.flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    gc.data.size == 1 && *gc.data.data == data->jumpchar) {
 | 
			
		||||
			window_copy_update_cursor(wp, px, data->cy);
 | 
			
		||||
			if (window_copy_update_selection(wp, 1))
 | 
			
		||||
				window_copy_redraw_lines(wp, data->cy, 1);
 | 
			
		||||
@@ -1967,8 +1960,7 @@ window_copy_cursor_jump_to(struct window_pane *wp, int jump_again)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct screen			*back_s = data->backing;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 px, py, xx;
 | 
			
		||||
 | 
			
		||||
	px = data->cx + 1 + jump_again;
 | 
			
		||||
@@ -1976,10 +1968,9 @@ window_copy_cursor_jump_to(struct window_pane *wp, int jump_again)
 | 
			
		||||
	xx = window_copy_find_length(wp, py);
 | 
			
		||||
 | 
			
		||||
	while (px < xx) {
 | 
			
		||||
		gc = grid_peek_cell(back_s->grid, px, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    ud.size == 1 && *ud.data == data->jumpchar) {
 | 
			
		||||
		grid_get_cell(back_s->grid, px, py, &gc);
 | 
			
		||||
		if (!(gc.flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    gc.data.size == 1 && *gc.data.data == data->jumpchar) {
 | 
			
		||||
			window_copy_update_cursor(wp, px - 1, data->cy);
 | 
			
		||||
			if (window_copy_update_selection(wp, 1))
 | 
			
		||||
				window_copy_redraw_lines(wp, data->cy, 1);
 | 
			
		||||
@@ -1994,8 +1985,7 @@ window_copy_cursor_jump_to_back(struct window_pane *wp, int jump_again)
 | 
			
		||||
{
 | 
			
		||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
			
		||||
	struct screen			*back_s = data->backing;
 | 
			
		||||
	const struct grid_cell		*gc;
 | 
			
		||||
	struct utf8_data		 ud;
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 px, py;
 | 
			
		||||
 | 
			
		||||
	px = data->cx;
 | 
			
		||||
@@ -2008,10 +1998,9 @@ window_copy_cursor_jump_to_back(struct window_pane *wp, int jump_again)
 | 
			
		||||
		px--;
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		gc = grid_peek_cell(back_s->grid, px, py);
 | 
			
		||||
		grid_cell_get(gc, &ud);
 | 
			
		||||
		if (!(gc->flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    ud.size == 1 && *ud.data == data->jumpchar) {
 | 
			
		||||
		grid_get_cell(back_s->grid, px, py, &gc);
 | 
			
		||||
		if (!(gc.flags & GRID_FLAG_PADDING) &&
 | 
			
		||||
		    gc.data.size == 1 && *gc.data.data == data->jumpchar) {
 | 
			
		||||
			window_copy_update_cursor(wp, px + 1, data->cy);
 | 
			
		||||
			if (window_copy_update_selection(wp, 1))
 | 
			
		||||
				window_copy_redraw_lines(wp, data->cy, 1);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user