mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:44:18 +00:00 
			
		
		
		
	Collect up line clears like text within the available data so we don't
need to flush everything.
This commit is contained in:
		
							
								
								
									
										171
									
								
								screen-write.c
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								screen-write.c
									
									
									
									
									
								
							@@ -25,6 +25,10 @@
 | 
			
		||||
 | 
			
		||||
static void	screen_write_collect_clear(struct screen_write_ctx *, u_int,
 | 
			
		||||
		    u_int);
 | 
			
		||||
static int	screen_write_collect_clear_end(struct screen_write_ctx *, u_int,
 | 
			
		||||
		    u_int, u_int);
 | 
			
		||||
static int	screen_write_collect_clear_start(struct screen_write_ctx *, u_int,
 | 
			
		||||
		    u_int, u_int);
 | 
			
		||||
static void	screen_write_collect_scroll(struct screen_write_ctx *);
 | 
			
		||||
static void	screen_write_collect_flush(struct screen_write_ctx *, int,
 | 
			
		||||
		    const char *);
 | 
			
		||||
@@ -42,8 +46,12 @@ struct screen_write_collect_item {
 | 
			
		||||
	u_int			 x;
 | 
			
		||||
	int			 wrapped;
 | 
			
		||||
 | 
			
		||||
	enum { TEXT, CLEAR, CLEAR_END, CLEAR_START } type;
 | 
			
		||||
	u_int			 used;
 | 
			
		||||
	union {
 | 
			
		||||
		u_int		 bg;
 | 
			
		||||
		char		 data[256];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct grid_cell	 gc;
 | 
			
		||||
 | 
			
		||||
@@ -926,21 +934,21 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			 *s = ctx->s;
 | 
			
		||||
	struct grid_line		 *gl;
 | 
			
		||||
	struct tty_ctx		 ttyctx;
 | 
			
		||||
	u_int				  sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_collect_item *ci = ctx->item;
 | 
			
		||||
 | 
			
		||||
	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
 | 
			
		||||
	if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
	ttyctx.bg = bg;
 | 
			
		||||
 | 
			
		||||
	grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
 | 
			
		||||
 | 
			
		||||
	screen_write_collect_clear(ctx, s->cy, 1);
 | 
			
		||||
	screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
	tty_write(tty_cmd_clearline, &ttyctx);
 | 
			
		||||
	ci->x = 0;
 | 
			
		||||
	ci->type = CLEAR;
 | 
			
		||||
	ci->bg = bg;
 | 
			
		||||
	TAILQ_INSERT_TAIL(&ctx->list[s->cy].items, ci, entry);
 | 
			
		||||
	ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to end of line from cursor. */
 | 
			
		||||
@@ -951,6 +959,12 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	struct grid_line		 *gl;
 | 
			
		||||
	struct tty_ctx			  ttyctx;
 | 
			
		||||
	u_int				  sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_collect_item *ci = ctx->item;
 | 
			
		||||
 | 
			
		||||
	if (s->cx == 0) {
 | 
			
		||||
		screen_write_clearline(ctx, bg);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
 | 
			
		||||
	if (s->cx > sx - 1 || (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg)))
 | 
			
		||||
@@ -961,10 +975,13 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
 | 
			
		||||
	grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
 | 
			
		||||
 | 
			
		||||
	if (s->cx == 0)
 | 
			
		||||
		screen_write_collect_clear(ctx, s->cy, 1);
 | 
			
		||||
	screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
	tty_write(tty_cmd_clearendofline, &ttyctx);
 | 
			
		||||
	if (!screen_write_collect_clear_end(ctx, s->cy, s->cx, bg)) {
 | 
			
		||||
		ci->x = s->cx;
 | 
			
		||||
		ci->type = CLEAR_END;
 | 
			
		||||
		ci->bg = bg;
 | 
			
		||||
		TAILQ_INSERT_TAIL(&ctx->list[s->cy].items, ci, entry);
 | 
			
		||||
		ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to start of line from cursor. */
 | 
			
		||||
@@ -974,6 +991,12 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	struct screen			 *s = ctx->s;
 | 
			
		||||
	struct tty_ctx			  ttyctx;
 | 
			
		||||
	u_int				  sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_collect_item *ci = ctx->item;
 | 
			
		||||
 | 
			
		||||
	if (s->cx >= sx - 1) {
 | 
			
		||||
		screen_write_clearline(ctx, bg);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
	ttyctx.bg = bg;
 | 
			
		||||
@@ -983,10 +1006,13 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	else
 | 
			
		||||
		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
 | 
			
		||||
 | 
			
		||||
	if (s->cx > sx - 1)
 | 
			
		||||
		screen_write_collect_clear(ctx, s->cy, 1);
 | 
			
		||||
	screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
	tty_write(tty_cmd_clearstartofline, &ttyctx);
 | 
			
		||||
	if (!screen_write_collect_clear_start(ctx, s->cy, s->cx, bg)) {
 | 
			
		||||
		ci->x = s->cx;
 | 
			
		||||
		ci->type = CLEAR_START;
 | 
			
		||||
		ci->bg = bg;
 | 
			
		||||
		TAILQ_INSERT_TAIL(&ctx->list[s->cy].items, ci, entry);
 | 
			
		||||
		ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor to px,py. */
 | 
			
		||||
@@ -1018,16 +1044,17 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	struct screen	*s = ctx->s;
 | 
			
		||||
	struct tty_ctx	 ttyctx;
 | 
			
		||||
 | 
			
		||||
	if (s->cy == s->rupper) {
 | 
			
		||||
		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
 | 
			
		||||
		screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
 | 
			
		||||
		screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
		ttyctx.bg = bg;
 | 
			
		||||
 | 
			
		||||
	if (s->cy == s->rupper)
 | 
			
		||||
		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
 | 
			
		||||
	else if (s->cy > 0)
 | 
			
		||||
		tty_write(tty_cmd_reverseindex, &ttyctx);
 | 
			
		||||
	} else if (s->cy > 0)
 | 
			
		||||
		screen_write_set_cursor(ctx, -1, s->cy - 1);
 | 
			
		||||
 | 
			
		||||
	screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
	tty_write(tty_cmd_reverseindex, &ttyctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set scroll region. */
 | 
			
		||||
@@ -1217,25 +1244,114 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
 | 
			
		||||
	grid_clear_history(ctx->s->grid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear a collected line. */
 | 
			
		||||
/* Clear to start of a collected line. */
 | 
			
		||||
static int
 | 
			
		||||
screen_write_collect_clear_start(struct screen_write_ctx *ctx, u_int y, u_int x,
 | 
			
		||||
    u_int bg)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	size_t					 size = 0;
 | 
			
		||||
	u_int					 items = 0;
 | 
			
		||||
	int					 redundant = 0;
 | 
			
		||||
 | 
			
		||||
	if (TAILQ_EMPTY(&ctx->list[y].items))
 | 
			
		||||
		return (0);
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
 | 
			
		||||
		switch (ci->type) {
 | 
			
		||||
		case CLEAR:
 | 
			
		||||
			continue;
 | 
			
		||||
		case CLEAR_START:
 | 
			
		||||
			if (ci->x >= x) {
 | 
			
		||||
				if (ci->bg == bg)
 | 
			
		||||
					redundant = 1;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case CLEAR_END:
 | 
			
		||||
			if (ci->x <= x)
 | 
			
		||||
				ci->x = x;
 | 
			
		||||
			continue;
 | 
			
		||||
		case TEXT:
 | 
			
		||||
			if (ci->x > x)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		items++;
 | 
			
		||||
		size += ci->used;
 | 
			
		||||
		TAILQ_REMOVE(&ctx->list[y].items, ci, entry);
 | 
			
		||||
		free(ci);
 | 
			
		||||
	}
 | 
			
		||||
	ctx->skipped += size;
 | 
			
		||||
	log_debug("%s: dropped %u items (%zu bytes) (line %u)", __func__, items,
 | 
			
		||||
	    size, y);
 | 
			
		||||
	return (redundant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to end of a collected line. */
 | 
			
		||||
static int
 | 
			
		||||
screen_write_collect_clear_end(struct screen_write_ctx *ctx, u_int y, u_int x,
 | 
			
		||||
    u_int bg)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	size_t					 size = 0;
 | 
			
		||||
	int					 redundant = 0;
 | 
			
		||||
	u_int					 items = 0;
 | 
			
		||||
 | 
			
		||||
	if (TAILQ_EMPTY(&ctx->list[y].items))
 | 
			
		||||
		return (0);
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
 | 
			
		||||
		switch (ci->type) {
 | 
			
		||||
		case CLEAR:
 | 
			
		||||
			continue;
 | 
			
		||||
		case CLEAR_START:
 | 
			
		||||
			if (ci->x >= x)
 | 
			
		||||
				ci->x = x;
 | 
			
		||||
			continue;
 | 
			
		||||
		case CLEAR_END:
 | 
			
		||||
			if (ci->x <= x) {
 | 
			
		||||
				if (ci->bg == bg)
 | 
			
		||||
					redundant = 1;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case TEXT:
 | 
			
		||||
			if (ci->x < x)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		items++;
 | 
			
		||||
		size += ci->used;
 | 
			
		||||
		TAILQ_REMOVE(&ctx->list[y].items, ci, entry);
 | 
			
		||||
		free(ci);
 | 
			
		||||
	}
 | 
			
		||||
	ctx->skipped += size;
 | 
			
		||||
	log_debug("%s: dropped %u items (%zu bytes) (line %u)", __func__, items,
 | 
			
		||||
	    size, y);
 | 
			
		||||
	return (redundant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear part of a collected line. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	u_int					 i;
 | 
			
		||||
	u_int					 i, items;
 | 
			
		||||
	size_t					 size;
 | 
			
		||||
 | 
			
		||||
	for (i = y; i < y + n; i++) {
 | 
			
		||||
		if (TAILQ_EMPTY(&ctx->list[i].items))
 | 
			
		||||
			continue;
 | 
			
		||||
		items = 0;
 | 
			
		||||
		size = 0;
 | 
			
		||||
		TAILQ_FOREACH_SAFE(ci, &ctx->list[i].items, entry, tmp) {
 | 
			
		||||
			items++;
 | 
			
		||||
			size += ci->used;
 | 
			
		||||
			TAILQ_REMOVE(&ctx->list[i].items, ci, entry);
 | 
			
		||||
			free(ci);
 | 
			
		||||
		}
 | 
			
		||||
		ctx->skipped += size;
 | 
			
		||||
		log_debug("%s: dropped %zu bytes (line %u)", __func__, size, i);
 | 
			
		||||
		log_debug("%s: dropped %u items (%zu bytes) (line %u)",
 | 
			
		||||
		    __func__, items, size, y);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1290,11 +1406,22 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
 | 
			
		||||
		TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
 | 
			
		||||
			screen_write_set_cursor(ctx, ci->x, y);
 | 
			
		||||
			screen_write_initctx(ctx, &ttyctx, 0);
 | 
			
		||||
			if (ci->type == CLEAR) {
 | 
			
		||||
				ttyctx.bg = ci->bg;
 | 
			
		||||
				tty_write(tty_cmd_clearline, &ttyctx);
 | 
			
		||||
			} else if (ci->type == CLEAR_END) {
 | 
			
		||||
				ttyctx.bg = ci->bg;
 | 
			
		||||
				tty_write(tty_cmd_clearendofline, &ttyctx);
 | 
			
		||||
			} else if (ci->type == CLEAR_START) {
 | 
			
		||||
				ttyctx.bg = ci->bg;
 | 
			
		||||
				tty_write(tty_cmd_clearstartofline, &ttyctx);
 | 
			
		||||
			} else {
 | 
			
		||||
				ttyctx.cell = &ci->gc;
 | 
			
		||||
				ttyctx.wrapped = ci->wrapped;
 | 
			
		||||
				ttyctx.ptr = ci->data;
 | 
			
		||||
				ttyctx.num = ci->used;
 | 
			
		||||
				tty_write(tty_cmd_cells, &ttyctx);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			items++;
 | 
			
		||||
			written += ci->used;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user