mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master' into master
This commit is contained in:
		
							
								
								
									
										3
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								format.c
									
									
									
									
									
								
							@@ -3038,9 +3038,6 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
 | 
			
		||||
	format_add_cb(ft, "history_bytes", format_cb_history_bytes);
 | 
			
		||||
	format_add_cb(ft, "history_all_bytes", format_cb_history_all_bytes);
 | 
			
		||||
 | 
			
		||||
	format_add(ft, "pane_written", "%zu", wp->written);
 | 
			
		||||
	format_add(ft, "pane_skipped", "%zu", wp->skipped);
 | 
			
		||||
 | 
			
		||||
	if (window_pane_index(wp, &idx) != 0)
 | 
			
		||||
		fatalx("index not found");
 | 
			
		||||
	format_add(ft, "pane_index", "%u", idx);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										313
									
								
								screen-write.c
									
									
									
									
									
								
							
							
						
						
									
										313
									
								
								screen-write.c
									
									
									
									
									
								
							@@ -23,13 +23,11 @@
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
static struct screen_write_citem *screen_write_collect_trim(
 | 
			
		||||
		    struct screen_write_ctx *, u_int, u_int, u_int, int *);
 | 
			
		||||
static void	screen_write_collect_clear(struct screen_write_ctx *, u_int,
 | 
			
		||||
		    u_int);
 | 
			
		||||
static void	screen_write_collect_clear_end(struct screen_write_ctx *, u_int,
 | 
			
		||||
		    u_int);
 | 
			
		||||
static void	screen_write_collect_clear_start(struct screen_write_ctx *,
 | 
			
		||||
		    u_int, u_int);
 | 
			
		||||
static void	screen_write_collect_scroll(struct screen_write_ctx *);
 | 
			
		||||
static void	screen_write_collect_scroll(struct screen_write_ctx *, u_int);
 | 
			
		||||
static void	screen_write_collect_flush(struct screen_write_ctx *, int,
 | 
			
		||||
		    const char *);
 | 
			
		||||
 | 
			
		||||
@@ -38,23 +36,44 @@ static int	screen_write_overwrite(struct screen_write_ctx *,
 | 
			
		||||
static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
 | 
			
		||||
		    const struct utf8_data *, u_int *);
 | 
			
		||||
 | 
			
		||||
struct screen_write_collect_item {
 | 
			
		||||
struct screen_write_citem {
 | 
			
		||||
	u_int				x;
 | 
			
		||||
	int				wrapped;
 | 
			
		||||
 | 
			
		||||
	enum { TEXT, CLEAR_END, CLEAR_START } type;
 | 
			
		||||
	enum { TEXT, CLEAR }		type;
 | 
			
		||||
	u_int				used;
 | 
			
		||||
	u_int				bg;
 | 
			
		||||
 | 
			
		||||
	struct grid_cell		gc;
 | 
			
		||||
 | 
			
		||||
	TAILQ_ENTRY(screen_write_collect_item) entry;
 | 
			
		||||
	TAILQ_ENTRY(screen_write_citem) entry;
 | 
			
		||||
};
 | 
			
		||||
struct screen_write_collect_line {
 | 
			
		||||
	u_int					 bg;
 | 
			
		||||
struct screen_write_cline {
 | 
			
		||||
	char				*data;
 | 
			
		||||
	TAILQ_HEAD(, screen_write_collect_item)  items;
 | 
			
		||||
	TAILQ_HEAD(, screen_write_citem) items;
 | 
			
		||||
};
 | 
			
		||||
TAILQ_HEAD(, screen_write_citem)  screen_write_citem_freelist =
 | 
			
		||||
    TAILQ_HEAD_INITIALIZER(screen_write_citem_freelist);
 | 
			
		||||
 | 
			
		||||
static struct screen_write_citem *
 | 
			
		||||
screen_write_get_citem(void)
 | 
			
		||||
{
 | 
			
		||||
    struct screen_write_citem	*ci;
 | 
			
		||||
 | 
			
		||||
    ci = TAILQ_FIRST(&screen_write_citem_freelist);
 | 
			
		||||
    if (ci != NULL) {
 | 
			
		||||
        TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
 | 
			
		||||
        memset(ci, 0, sizeof *ci);
 | 
			
		||||
        return (ci);
 | 
			
		||||
    }
 | 
			
		||||
    return (xcalloc(1, sizeof *ci));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
screen_write_free_citem(struct screen_write_citem *ci)
 | 
			
		||||
{
 | 
			
		||||
    TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
screen_write_offset_timer(__unused int fd, __unused short events, void *data)
 | 
			
		||||
@@ -125,7 +144,8 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
 | 
			
		||||
		 * Redraw is already deferred to redraw another pane - redraw
 | 
			
		||||
		 * this one also when that happens.
 | 
			
		||||
		 */
 | 
			
		||||
		log_debug("adding %%%u to deferred redraw", wp->id);
 | 
			
		||||
		log_debug("%s: adding %%%u to deferred redraw", __func__,
 | 
			
		||||
		    wp->id);
 | 
			
		||||
		wp->flags |= PANE_REDRAW;
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
@@ -220,7 +240,7 @@ screen_write_init(struct screen_write_ctx *ctx, struct screen *s)
 | 
			
		||||
 | 
			
		||||
	if (ctx->s->write_list == NULL)
 | 
			
		||||
		screen_write_make_list(ctx->s);
 | 
			
		||||
	ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	ctx->item = screen_write_get_citem();
 | 
			
		||||
 | 
			
		||||
	ctx->scrolled = 0;
 | 
			
		||||
	ctx->bg = 8;
 | 
			
		||||
@@ -278,14 +298,7 @@ screen_write_stop(struct screen_write_ctx *ctx)
 | 
			
		||||
	screen_write_collect_end(ctx);
 | 
			
		||||
	screen_write_collect_flush(ctx, 0, __func__);
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: %u cells (%u written, %u skipped)", __func__,
 | 
			
		||||
	    ctx->cells, ctx->written, ctx->skipped);
 | 
			
		||||
	if (ctx->wp != NULL) {
 | 
			
		||||
		ctx->wp->written += ctx->written;
 | 
			
		||||
		ctx->wp->skipped += ctx->skipped;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free(ctx->item);
 | 
			
		||||
	screen_write_free_citem(ctx->item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Reset screen state. */
 | 
			
		||||
@@ -1097,6 +1110,7 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct grid_line		*gl;
 | 
			
		||||
	u_int				 sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_citem	*ci = ctx->item;
 | 
			
		||||
 | 
			
		||||
	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
 | 
			
		||||
	if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
 | 
			
		||||
@@ -1105,8 +1119,12 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
 | 
			
		||||
 | 
			
		||||
	screen_write_collect_clear(ctx, s->cy, 1);
 | 
			
		||||
	ctx->s->write_list[s->cy].bg = 1 + bg;
 | 
			
		||||
	ctx->item->used = 0;
 | 
			
		||||
	ci->x = 0;
 | 
			
		||||
	ci->used = sx;
 | 
			
		||||
	ci->type = CLEAR;
 | 
			
		||||
	ci->bg = bg;
 | 
			
		||||
	TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
 | 
			
		||||
	ctx->item = screen_write_get_citem();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to end of line from cursor. */
 | 
			
		||||
@@ -1116,7 +1134,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct grid_line		*gl;
 | 
			
		||||
	u_int				 sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_collect_item *ci = ctx->item;
 | 
			
		||||
	struct screen_write_citem	*ci = ctx->item, *before;
 | 
			
		||||
 | 
			
		||||
	if (s->cx == 0) {
 | 
			
		||||
		screen_write_clearline(ctx, bg);
 | 
			
		||||
@@ -1129,12 +1147,16 @@ 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);
 | 
			
		||||
 | 
			
		||||
 	screen_write_collect_clear_end(ctx, s->cy, s->cx);
 | 
			
		||||
 	before = screen_write_collect_trim(ctx, s->cy, s->cx, sx - s->cx, NULL);
 | 
			
		||||
	ci->x = s->cx;
 | 
			
		||||
	ci->type = CLEAR_END;
 | 
			
		||||
	ci->used = sx - s->cx;
 | 
			
		||||
	ci->type = CLEAR;
 | 
			
		||||
	ci->bg = bg;
 | 
			
		||||
	if (before == NULL)
 | 
			
		||||
		TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
 | 
			
		||||
	ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	else
 | 
			
		||||
		TAILQ_INSERT_BEFORE(before, ci, entry);
 | 
			
		||||
	ctx->item = screen_write_get_citem();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to start of line from cursor. */
 | 
			
		||||
@@ -1143,7 +1165,7 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			 *s = ctx->s;
 | 
			
		||||
	u_int				 sx = screen_size_x(s);
 | 
			
		||||
	struct screen_write_collect_item *ci = ctx->item;
 | 
			
		||||
	struct screen_write_citem	*ci = ctx->item, *before;
 | 
			
		||||
 | 
			
		||||
	if (s->cx >= sx - 1) {
 | 
			
		||||
		screen_write_clearline(ctx, bg);
 | 
			
		||||
@@ -1155,12 +1177,16 @@ 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);
 | 
			
		||||
 | 
			
		||||
	screen_write_collect_clear_start(ctx, s->cy, s->cx);
 | 
			
		||||
	ci->x = s->cx;
 | 
			
		||||
	ci->type = CLEAR_START;
 | 
			
		||||
	before = screen_write_collect_trim(ctx, s->cy, 0, s->cx + 1, NULL);
 | 
			
		||||
	ci->x = 0;
 | 
			
		||||
	ci->used = s->cx + 1;
 | 
			
		||||
	ci->type = CLEAR;
 | 
			
		||||
	ci->bg = bg;
 | 
			
		||||
	if (before == NULL)
 | 
			
		||||
		TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
 | 
			
		||||
	ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	else
 | 
			
		||||
		TAILQ_INSERT_BEFORE(before, ci, entry);
 | 
			
		||||
	ctx->item = screen_write_get_citem();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move cursor to px,py. */
 | 
			
		||||
@@ -1182,6 +1208,7 @@ screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py,
 | 
			
		||||
	if (py != -1 && (u_int)py > screen_size_y(s) - 1)
 | 
			
		||||
		py = screen_size_y(s) - 1;
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: from %u,%u to %u,%u", __func__, s->cx, s->cy, px, py);
 | 
			
		||||
	screen_write_set_cursor(ctx, px, py);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1250,7 +1277,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
 | 
			
		||||
 | 
			
		||||
	if (s->cy == s->rlower) {
 | 
			
		||||
		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
 | 
			
		||||
		screen_write_collect_scroll(ctx);
 | 
			
		||||
		screen_write_collect_scroll(ctx, bg);
 | 
			
		||||
		ctx->scrolled++;
 | 
			
		||||
	} else if (s->cy < screen_size_y(s) - 1)
 | 
			
		||||
		screen_write_set_cursor(ctx, -1, s->cy + 1);
 | 
			
		||||
@@ -1276,7 +1303,7 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < lines; i++) {
 | 
			
		||||
		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
 | 
			
		||||
		screen_write_collect_scroll(ctx);
 | 
			
		||||
		screen_write_collect_scroll(ctx, bg);
 | 
			
		||||
	}
 | 
			
		||||
	ctx->scrolled += lines;
 | 
			
		||||
}
 | 
			
		||||
@@ -1390,107 +1417,114 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
 | 
			
		||||
	grid_clear_history(ctx->s->grid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear to start of a collected line. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_collect_clear_start(struct screen_write_ctx *ctx, u_int y, u_int x)
 | 
			
		||||
/* Trim collected items. */
 | 
			
		||||
static struct screen_write_citem *
 | 
			
		||||
screen_write_collect_trim(struct screen_write_ctx *ctx, u_int y, u_int x,
 | 
			
		||||
    u_int used, int *wrapped)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	size_t					 size = 0;
 | 
			
		||||
	u_int					 items = 0;
 | 
			
		||||
	struct screen_write_cline	*cl = &ctx->s->write_list[y];
 | 
			
		||||
	struct screen_write_citem	*ci, *ci2, *tmp, *before = NULL;
 | 
			
		||||
	u_int				 sx = x, ex = x + used - 1;
 | 
			
		||||
	u_int				 csx, cex;
 | 
			
		||||
 | 
			
		||||
	if (TAILQ_EMPTY(&ctx->s->write_list[y].items))
 | 
			
		||||
		return;
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ci, &ctx->s->write_list[y].items, entry, tmp) {
 | 
			
		||||
		switch (ci->type) {
 | 
			
		||||
		case CLEAR_START:
 | 
			
		||||
			break;
 | 
			
		||||
		case CLEAR_END:
 | 
			
		||||
			if (ci->x <= x)
 | 
			
		||||
				ci->x = x;
 | 
			
		||||
	if (TAILQ_EMPTY(&cl->items))
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
 | 
			
		||||
		csx = ci->x;
 | 
			
		||||
		cex = ci->x + ci->used - 1;
 | 
			
		||||
 | 
			
		||||
		/* Item is entirely before. */
 | 
			
		||||
		if (cex < sx) {
 | 
			
		||||
			log_debug("%s: %p %u-%u before %u-%u", __func__, ci,
 | 
			
		||||
			    csx, cex, sx, ex);
 | 
			
		||||
			continue;
 | 
			
		||||
		case TEXT:
 | 
			
		||||
			if (ci->x > x)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		items++;
 | 
			
		||||
		size += ci->used;
 | 
			
		||||
		TAILQ_REMOVE(&ctx->s->write_list[y].items, ci, entry);
 | 
			
		||||
		free(ci);
 | 
			
		||||
	}
 | 
			
		||||
	ctx->skipped += size;
 | 
			
		||||
	log_debug("%s: dropped %u items (%zu bytes) (line %u)", __func__, items,
 | 
			
		||||
	    size, y);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
/* Clear to end of a collected line. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_collect_clear_end(struct screen_write_ctx *ctx, u_int y, u_int x)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	size_t					 size = 0;
 | 
			
		||||
	u_int					 items = 0;
 | 
			
		||||
		/* Item is entirely after. */
 | 
			
		||||
		if (csx > ex) {
 | 
			
		||||
			log_debug("%s: %p %u-%u after %u-%u", __func__, ci,
 | 
			
		||||
			    csx, cex, sx, ex);
 | 
			
		||||
			before = ci;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (TAILQ_EMPTY(&ctx->s->write_list[y].items))
 | 
			
		||||
		return;
 | 
			
		||||
	TAILQ_FOREACH_SAFE(ci, &ctx->s->write_list[y].items, entry, tmp) {
 | 
			
		||||
		switch (ci->type) {
 | 
			
		||||
		case CLEAR_START:
 | 
			
		||||
			if (ci->x >= x)
 | 
			
		||||
				ci->x = x;
 | 
			
		||||
		/* Item is entirely inside. */
 | 
			
		||||
		if (csx >= sx && cex <= ex) {
 | 
			
		||||
			log_debug("%s: %p %u-%u inside %u-%u", __func__, ci,
 | 
			
		||||
			    csx, cex, sx, ex);
 | 
			
		||||
			TAILQ_REMOVE(&cl->items, ci, entry);
 | 
			
		||||
			screen_write_free_citem(ci);
 | 
			
		||||
			if (csx == 0 && ci->wrapped && wrapped != NULL)
 | 
			
		||||
				*wrapped = 1;
 | 
			
		||||
			continue;
 | 
			
		||||
		case CLEAR_END:
 | 
			
		||||
			break;
 | 
			
		||||
		case TEXT:
 | 
			
		||||
			if (ci->x < x)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Item under the start. */
 | 
			
		||||
		if (csx < sx && cex >= sx && cex <= ex) {
 | 
			
		||||
			log_debug("%s: %p %u-%u start %u-%u", __func__, ci,
 | 
			
		||||
			    csx, cex, sx, ex);
 | 
			
		||||
			ci->used = sx - csx;
 | 
			
		||||
			log_debug("%s: %p now %u-%u", __func__, ci, ci->x,
 | 
			
		||||
			    ci->x + ci->used + 1);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Item covers the end. */
 | 
			
		||||
		if (cex > ex && csx >= sx && csx <= ex) {
 | 
			
		||||
			log_debug("%s: %p %u-%u end %u-%u", __func__, ci,
 | 
			
		||||
			    csx, cex, sx, ex);
 | 
			
		||||
			ci->x = ex + 1;
 | 
			
		||||
			ci->used = cex - ex;
 | 
			
		||||
			log_debug("%s: %p now %u-%u", __func__, ci, ci->x,
 | 
			
		||||
			    ci->x + ci->used + 1);
 | 
			
		||||
			before = ci;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		items++;
 | 
			
		||||
		size += ci->used;
 | 
			
		||||
		TAILQ_REMOVE(&ctx->s->write_list[y].items, ci, entry);
 | 
			
		||||
		free(ci);
 | 
			
		||||
 | 
			
		||||
		/* Item must cover both sides. */
 | 
			
		||||
		log_debug("%s: %p %u-%u under %u-%u", __func__, ci,
 | 
			
		||||
		    csx, cex, sx, ex);
 | 
			
		||||
		ci2 = screen_write_get_citem();
 | 
			
		||||
		ci2->type = ci->type;
 | 
			
		||||
		ci2->bg = ci->bg;
 | 
			
		||||
		memcpy(&ci2->gc, &ci->gc, sizeof ci2->gc);
 | 
			
		||||
		TAILQ_INSERT_AFTER(&cl->items, ci, ci2, entry);
 | 
			
		||||
 | 
			
		||||
		ci->used = sx - csx;
 | 
			
		||||
		ci2->x = ex + 1;
 | 
			
		||||
		ci2->used = cex - ex;
 | 
			
		||||
 | 
			
		||||
		log_debug("%s: %p now %u-%u (%p) and %u-%u (%p)", __func__, ci,
 | 
			
		||||
		    ci->x, ci->x + ci->used - 1, ci, ci2->x,
 | 
			
		||||
		    ci2->x + ci2->used - 1, ci2);
 | 
			
		||||
		before = ci2;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->skipped += size;
 | 
			
		||||
	log_debug("%s: dropped %u items (%zu bytes) (line %u)", __func__, items,
 | 
			
		||||
	    size, y);
 | 
			
		||||
	return (before);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear collected lines. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
 | 
			
		||||
{
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	struct screen_write_collect_line	*cl;
 | 
			
		||||
	u_int					 i, items;
 | 
			
		||||
	size_t					 size;
 | 
			
		||||
	struct screen_write_cline	*cl;
 | 
			
		||||
	u_int				 i;
 | 
			
		||||
 | 
			
		||||
	for (i = y; i < y + n; i++) {
 | 
			
		||||
		if (TAILQ_EMPTY(&ctx->s->write_list[i].items))
 | 
			
		||||
			continue;
 | 
			
		||||
		items = 0;
 | 
			
		||||
		size = 0;
 | 
			
		||||
		cl = &ctx->s->write_list[i];
 | 
			
		||||
		TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
 | 
			
		||||
			items++;
 | 
			
		||||
			size += ci->used;
 | 
			
		||||
			TAILQ_REMOVE(&cl->items, ci, entry);
 | 
			
		||||
			free(ci);
 | 
			
		||||
		}
 | 
			
		||||
		ctx->skipped += size;
 | 
			
		||||
		log_debug("%s: dropped %u items (%zu bytes) (line %u)",
 | 
			
		||||
		    __func__, items, size, y);
 | 
			
		||||
		TAILQ_CONCAT(&screen_write_citem_freelist, &cl->items, entry);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Scroll collected lines up. */
 | 
			
		||||
static void
 | 
			
		||||
screen_write_collect_scroll(struct screen_write_ctx *ctx)
 | 
			
		||||
screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct screen_write_collect_line	*cl;
 | 
			
		||||
	struct screen_write_cline	*cl;
 | 
			
		||||
	u_int				 y;
 | 
			
		||||
	char				*saved;
 | 
			
		||||
	struct screen_write_citem	*ci;
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
 | 
			
		||||
	    s->rupper, s->rlower);
 | 
			
		||||
@@ -1500,11 +1534,16 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx)
 | 
			
		||||
	for (y = s->rupper; y < s->rlower; y++) {
 | 
			
		||||
		cl = &ctx->s->write_list[y + 1];
 | 
			
		||||
		TAILQ_CONCAT(&ctx->s->write_list[y].items, &cl->items, entry);
 | 
			
		||||
		ctx->s->write_list[y].bg = cl->bg;
 | 
			
		||||
		ctx->s->write_list[y].data = cl->data;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->s->write_list[s->rlower].bg = 1 + 8;
 | 
			
		||||
	ctx->s->write_list[s->rlower].data = saved;
 | 
			
		||||
 | 
			
		||||
	ci = screen_write_get_citem();
 | 
			
		||||
	ci->x = 0;
 | 
			
		||||
	ci->used = screen_size_x(s);
 | 
			
		||||
	ci->type = CLEAR;
 | 
			
		||||
	ci->bg = bg;
 | 
			
		||||
	TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Flush collected lines. */
 | 
			
		||||
@@ -1513,11 +1552,10 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
 | 
			
		||||
    const char *from)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct screen_write_collect_item	*ci, *tmp;
 | 
			
		||||
	struct screen_write_collect_line	*cl;
 | 
			
		||||
	u_int					 y, cx, cy, items = 0;
 | 
			
		||||
	struct screen_write_citem	*ci, *tmp;
 | 
			
		||||
	struct screen_write_cline	*cl;
 | 
			
		||||
	u_int				 y, cx, cy, last, items = 0;
 | 
			
		||||
	struct tty_ctx			 ttyctx;
 | 
			
		||||
	size_t					 written = 0;
 | 
			
		||||
 | 
			
		||||
	if (ctx->scrolled != 0) {
 | 
			
		||||
		log_debug("%s: scrolled %u (region %u-%u)", __func__,
 | 
			
		||||
@@ -1539,22 +1577,18 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
 | 
			
		||||
	cx = s->cx; cy = s->cy;
 | 
			
		||||
	for (y = 0; y < screen_size_y(s); y++) {
 | 
			
		||||
		cl = &ctx->s->write_list[y];
 | 
			
		||||
		if (cl->bg != 0) {
 | 
			
		||||
			screen_write_set_cursor(ctx, 0, y);
 | 
			
		||||
			screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
			ttyctx.bg = cl->bg - 1;
 | 
			
		||||
			tty_write(tty_cmd_clearline, &ttyctx);
 | 
			
		||||
		}
 | 
			
		||||
		last = UINT_MAX;
 | 
			
		||||
		TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
 | 
			
		||||
			if (last != UINT_MAX && ci->x <= last) {
 | 
			
		||||
				fatalx("collect list not in order: %u <= %u",
 | 
			
		||||
				    ci->x, last);
 | 
			
		||||
			}
 | 
			
		||||
			screen_write_set_cursor(ctx, ci->x, y);
 | 
			
		||||
			if (ci->type == CLEAR_END) {
 | 
			
		||||
			if (ci->type == CLEAR) {
 | 
			
		||||
				screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
				ttyctx.bg = ci->bg;
 | 
			
		||||
				tty_write(tty_cmd_clearendofline, &ttyctx);
 | 
			
		||||
			} else if (ci->type == CLEAR_START) {
 | 
			
		||||
				screen_write_initctx(ctx, &ttyctx, 1);
 | 
			
		||||
				ttyctx.bg = ci->bg;
 | 
			
		||||
				tty_write(tty_cmd_clearstartofline, &ttyctx);
 | 
			
		||||
				ttyctx.num = ci->used;
 | 
			
		||||
				tty_write(tty_cmd_clearcharacter, &ttyctx);
 | 
			
		||||
			} else {
 | 
			
		||||
				screen_write_initctx(ctx, &ttyctx, 0);
 | 
			
		||||
				ttyctx.cell = &ci->gc;
 | 
			
		||||
@@ -1563,20 +1597,16 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
 | 
			
		||||
				ttyctx.num = ci->used;
 | 
			
		||||
				tty_write(tty_cmd_cells, &ttyctx);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			items++;
 | 
			
		||||
			written += ci->used;
 | 
			
		||||
 | 
			
		||||
			TAILQ_REMOVE(&cl->items, ci, entry);
 | 
			
		||||
			free(ci);
 | 
			
		||||
			screen_write_free_citem(ci);
 | 
			
		||||
			last = ci->x;
 | 
			
		||||
		}
 | 
			
		||||
		cl->bg = 0;
 | 
			
		||||
	}
 | 
			
		||||
	s->cx = cx; s->cy = cy;
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: flushed %u items (%zu bytes) (%s)", __func__, items,
 | 
			
		||||
	    written, from);
 | 
			
		||||
	ctx->written += written;
 | 
			
		||||
	log_debug("%s: flushed %u items (%s)", __func__, items, from);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Finish and store collected cells. */
 | 
			
		||||
@@ -1584,17 +1614,24 @@ void
 | 
			
		||||
screen_write_collect_end(struct screen_write_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct screen_write_collect_item	*ci = ctx->item;
 | 
			
		||||
	struct screen_write_collect_line	*cl = &s->write_list[s->cy];
 | 
			
		||||
	struct screen_write_citem	*ci = ctx->item, *before;
 | 
			
		||||
	struct screen_write_cline	*cl = &s->write_list[s->cy];
 | 
			
		||||
	struct grid_cell		 gc;
 | 
			
		||||
	u_int				 xx;
 | 
			
		||||
	int				 wrapped = ci->wrapped;
 | 
			
		||||
 | 
			
		||||
	if (ci->used == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
 | 
			
		||||
	    &wrapped);
 | 
			
		||||
	ci->x = s->cx;
 | 
			
		||||
	ci->wrapped = wrapped;
 | 
			
		||||
	if (before == NULL)
 | 
			
		||||
		TAILQ_INSERT_TAIL(&cl->items, ci, entry);
 | 
			
		||||
	ctx->item = xcalloc(1, sizeof *ctx->item);
 | 
			
		||||
	else
 | 
			
		||||
		TAILQ_INSERT_BEFORE(before, ci, entry);
 | 
			
		||||
	ctx->item = screen_write_get_citem();
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
 | 
			
		||||
	    (int)ci->used, cl->data + ci->x, s->cx, s->cy);
 | 
			
		||||
@@ -1631,7 +1668,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
 | 
			
		||||
    const struct grid_cell *gc)
 | 
			
		||||
{
 | 
			
		||||
	struct screen			*s = ctx->s;
 | 
			
		||||
	struct screen_write_collect_item	*ci;
 | 
			
		||||
	struct screen_write_citem	*ci;
 | 
			
		||||
	u_int				 sx = screen_size_x(s);
 | 
			
		||||
	int				 collect;
 | 
			
		||||
 | 
			
		||||
@@ -1658,7 +1695,6 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
 | 
			
		||||
		screen_write_cell(ctx, gc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->cells++;
 | 
			
		||||
 | 
			
		||||
	if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
 | 
			
		||||
		screen_write_collect_end(ctx);
 | 
			
		||||
@@ -1695,7 +1731,6 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
	/* Ignore padding cells. */
 | 
			
		||||
	if (gc->flags & GRID_FLAG_PADDING)
 | 
			
		||||
		return;
 | 
			
		||||
	ctx->cells++;
 | 
			
		||||
 | 
			
		||||
	/* If the width is zero, combine onto the previous character. */
 | 
			
		||||
	if (width == 0) {
 | 
			
		||||
@@ -1822,9 +1857,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 | 
			
		||||
		} else
 | 
			
		||||
			ttyctx.cell = gc;
 | 
			
		||||
		tty_write(tty_cmd_cell, &ttyctx);
 | 
			
		||||
		ctx->written++;
 | 
			
		||||
	} else
 | 
			
		||||
		ctx->skipped++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Combine a UTF-8 zero-width character onto the previous. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.1
									
									
									
									
									
								
							@@ -4823,7 +4823,6 @@ The following variables are available, where appropriate:
 | 
			
		||||
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
 | 
			
		||||
.It Li "pane_right" Ta "" Ta "Right of pane"
 | 
			
		||||
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
 | 
			
		||||
.It Li "pane_skipped" Ta "" Ta "Bytes skipped as not visible in pane"
 | 
			
		||||
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
 | 
			
		||||
.It Li "pane_synchronized" Ta "" Ta "1 if pane is synchronized"
 | 
			
		||||
.It Li "pane_tabs" Ta "" Ta "Pane tab positions"
 | 
			
		||||
@@ -4831,7 +4830,6 @@ The following variables are available, where appropriate:
 | 
			
		||||
.It Li "pane_top" Ta "" Ta "Top of pane"
 | 
			
		||||
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
 | 
			
		||||
.It Li "pane_width" Ta "" Ta "Width of pane"
 | 
			
		||||
.It Li "pane_written" Ta "" Ta "Bytes written by pane (aside from redrawing)"
 | 
			
		||||
.It Li "pid" Ta "" Ta "Server PID"
 | 
			
		||||
.It Li "popup_key" Ta "" Ta "Key pressed in popup"
 | 
			
		||||
.It Li "popup_mouse_x" Ta "" Ta "Mouse X position in popup"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								tmux.h
									
									
									
									
									
								
							@@ -56,8 +56,8 @@ struct mouse_event;
 | 
			
		||||
struct options;
 | 
			
		||||
struct options_array_item;
 | 
			
		||||
struct options_entry;
 | 
			
		||||
struct screen_write_collect_item;
 | 
			
		||||
struct screen_write_collect_line;
 | 
			
		||||
struct screen_write_citem;
 | 
			
		||||
struct screen_write_cline;
 | 
			
		||||
struct screen_write_ctx;
 | 
			
		||||
struct session;
 | 
			
		||||
struct tty_ctx;
 | 
			
		||||
@@ -821,7 +821,7 @@ struct screen {
 | 
			
		||||
	bitstr_t			*tabs;
 | 
			
		||||
	struct screen_sel		*sel;
 | 
			
		||||
 | 
			
		||||
	struct screen_write_collect_line *write_list;
 | 
			
		||||
	struct screen_write_cline	*write_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Screen write context. */
 | 
			
		||||
@@ -837,13 +837,9 @@ struct screen_write_ctx {
 | 
			
		||||
	screen_write_init_ctx_cb	 init_ctx_cb;
 | 
			
		||||
	void				*arg;
 | 
			
		||||
 | 
			
		||||
	struct screen_write_collect_item *item;
 | 
			
		||||
	struct screen_write_citem	*item;
 | 
			
		||||
	u_int				 scrolled;
 | 
			
		||||
	u_int				 bg;
 | 
			
		||||
 | 
			
		||||
	u_int			 cells;
 | 
			
		||||
	u_int			 written;
 | 
			
		||||
	u_int			 skipped;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Screen redraw context. */
 | 
			
		||||
@@ -1002,9 +998,6 @@ struct window_pane {
 | 
			
		||||
	char		*searchstr;
 | 
			
		||||
	int		 searchregex;
 | 
			
		||||
 | 
			
		||||
	size_t		 written;
 | 
			
		||||
	size_t		 skipped;
 | 
			
		||||
 | 
			
		||||
	int		 border_gc_set;
 | 
			
		||||
	struct grid_cell border_gc;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user