aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicm <nicm>2020-04-16 20:32:51 +0000
committernicm <nicm>2020-04-16 20:32:51 +0000
commitd90ca7ecd61ee2f1376801acd61252c03caef3ca (patch)
treeba8cf33bd9afd52b14d292cf2f6d356d9dc397ab
parentc1b015f24ed2ea93f91ae082b31be3c92b463a2f (diff)
downloadrtmux-d90ca7ecd61ee2f1376801acd61252c03caef3ca.tar.gz
rtmux-d90ca7ecd61ee2f1376801acd61252c03caef3ca.tar.bz2
rtmux-d90ca7ecd61ee2f1376801acd61252c03caef3ca.zip
Collect up line clears like text within the available data so we don't
need to flush everything.
-rw-r--r--screen-write.c207
1 files changed, 167 insertions, 40 deletions
diff --git a/screen-write.c b/screen-write.c
index aa7bd76e..8a2a19e3 100644
--- a/screen-write.c
+++ b/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;
- char data[256];
+ union {
+ u_int bg;
+ char data[256];
+ };
struct grid_cell gc;
@@ -924,33 +932,39 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
void
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 *s = ctx->s;
+ struct grid_line *gl;
+ 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. */
void
screen_write_clearendofline(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 *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;
+
+ 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,19 +975,28 @@ 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. */
void
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 *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;
- screen_write_initctx(ctx, &ttyctx, 1);
- ttyctx.bg = bg;
-
- if (s->cy == s->rupper)
+ if (s->cy == s->rupper) {
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
- else if (s->cy > 0)
+ screen_write_collect_flush(ctx, 0, __func__);
+
+ screen_write_initctx(ctx, &ttyctx, 1);
+ ttyctx.bg = bg;
+
+ 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);
- ttyctx.cell = &ci->gc;
- ttyctx.wrapped = ci->wrapped;
- ttyctx.ptr = ci->data;
- ttyctx.num = ci->used;
- tty_write(tty_cmd_cells, &ttyctx);
+ 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;