mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 01:48:47 +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:
parent
c1b015f24e
commit
d90ca7ecd6
171
screen-write.c
171
screen-write.c
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
||||||
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_scroll(struct screen_write_ctx *);
|
||||||
static void screen_write_collect_flush(struct screen_write_ctx *, int,
|
static void screen_write_collect_flush(struct screen_write_ctx *, int,
|
||||||
const char *);
|
const char *);
|
||||||
@ -42,8 +46,12 @@ struct screen_write_collect_item {
|
|||||||
u_int x;
|
u_int x;
|
||||||
int wrapped;
|
int wrapped;
|
||||||
|
|
||||||
|
enum { TEXT, CLEAR, CLEAR_END, CLEAR_START } type;
|
||||||
u_int used;
|
u_int used;
|
||||||
|
union {
|
||||||
|
u_int bg;
|
||||||
char data[256];
|
char data[256];
|
||||||
|
};
|
||||||
|
|
||||||
struct grid_cell gc;
|
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 screen *s = ctx->s;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
struct tty_ctx ttyctx;
|
|
||||||
u_int sx = screen_size_x(s);
|
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);
|
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||||
if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
|
if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
|
||||||
ttyctx.bg = bg;
|
|
||||||
|
|
||||||
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
|
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
|
||||||
|
|
||||||
screen_write_collect_clear(ctx, s->cy, 1);
|
screen_write_collect_clear(ctx, s->cy, 1);
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
ci->x = 0;
|
||||||
tty_write(tty_cmd_clearline, &ttyctx);
|
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. */
|
/* 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 grid_line *gl;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s);
|
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);
|
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||||
if (s->cx > sx - 1 || (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg)))
|
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);
|
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
|
||||||
|
|
||||||
if (s->cx == 0)
|
if (!screen_write_collect_clear_end(ctx, s->cy, s->cx, bg)) {
|
||||||
screen_write_collect_clear(ctx, s->cy, 1);
|
ci->x = s->cx;
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
ci->type = CLEAR_END;
|
||||||
tty_write(tty_cmd_clearendofline, &ttyctx);
|
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. */
|
/* 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 screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s);
|
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);
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
ttyctx.bg = bg;
|
ttyctx.bg = bg;
|
||||||
@ -983,10 +1006,13 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
else
|
else
|
||||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
||||||
|
|
||||||
if (s->cx > sx - 1)
|
if (!screen_write_collect_clear_start(ctx, s->cy, s->cx, bg)) {
|
||||||
screen_write_collect_clear(ctx, s->cy, 1);
|
ci->x = s->cx;
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
ci->type = CLEAR_START;
|
||||||
tty_write(tty_cmd_clearstartofline, &ttyctx);
|
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. */
|
/* 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 screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
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);
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
ttyctx.bg = bg;
|
ttyctx.bg = bg;
|
||||||
|
|
||||||
if (s->cy == s->rupper)
|
tty_write(tty_cmd_reverseindex, &ttyctx);
|
||||||
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
|
} else if (s->cy > 0)
|
||||||
else if (s->cy > 0)
|
|
||||||
screen_write_set_cursor(ctx, -1, s->cy - 1);
|
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. */
|
/* Set scroll region. */
|
||||||
@ -1217,25 +1244,114 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
|
|||||||
grid_clear_history(ctx->s->grid);
|
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
|
static void
|
||||||
screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
|
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_item *ci, *tmp;
|
||||||
u_int i;
|
u_int i, items;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
for (i = y; i < y + n; i++) {
|
for (i = y; i < y + n; i++) {
|
||||||
if (TAILQ_EMPTY(&ctx->list[i].items))
|
if (TAILQ_EMPTY(&ctx->list[i].items))
|
||||||
continue;
|
continue;
|
||||||
|
items = 0;
|
||||||
size = 0;
|
size = 0;
|
||||||
TAILQ_FOREACH_SAFE(ci, &ctx->list[i].items, entry, tmp) {
|
TAILQ_FOREACH_SAFE(ci, &ctx->list[i].items, entry, tmp) {
|
||||||
|
items++;
|
||||||
size += ci->used;
|
size += ci->used;
|
||||||
TAILQ_REMOVE(&ctx->list[i].items, ci, entry);
|
TAILQ_REMOVE(&ctx->list[i].items, ci, entry);
|
||||||
free(ci);
|
free(ci);
|
||||||
}
|
}
|
||||||
ctx->skipped += size;
|
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) {
|
TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
|
||||||
screen_write_set_cursor(ctx, ci->x, y);
|
screen_write_set_cursor(ctx, ci->x, y);
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
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.cell = &ci->gc;
|
||||||
ttyctx.wrapped = ci->wrapped;
|
ttyctx.wrapped = ci->wrapped;
|
||||||
ttyctx.ptr = ci->data;
|
ttyctx.ptr = ci->data;
|
||||||
ttyctx.num = ci->used;
|
ttyctx.num = ci->used;
|
||||||
tty_write(tty_cmd_cells, &ttyctx);
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
|
}
|
||||||
|
|
||||||
items++;
|
items++;
|
||||||
written += ci->used;
|
written += ci->used;
|
||||||
|
Loading…
Reference in New Issue
Block a user