version 1.164, 2020/04/16 17:24:28 |
version 1.165, 2020/04/16 20:32:51 |
|
|
|
|
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 *); |
|
|
u_int x; |
u_int x; |
int wrapped; |
int wrapped; |
|
|
|
enum { TEXT, CLEAR, CLEAR_END, CLEAR_START } type; |
u_int used; |
u_int used; |
char data[256]; |
union { |
|
u_int bg; |
|
char data[256]; |
|
}; |
|
|
struct grid_cell gc; |
struct grid_cell gc; |
|
|
|
|
void |
void |
screen_write_clearline(struct screen_write_ctx *ctx, u_int bg) |
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. */ |
void |
void |
screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg) |
screen_write_clearendofline(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; |
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))) |
return; |
return; |
|
|
|
|
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. */ |
void |
void |
screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg) |
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; |
|
|
|
|
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. */ |
|
|
struct screen *s = ctx->s; |
struct screen *s = ctx->s; |
struct tty_ctx ttyctx; |
struct tty_ctx ttyctx; |
|
|
screen_write_initctx(ctx, &ttyctx, 1); |
if (s->cy == s->rupper) { |
ttyctx.bg = bg; |
|
|
|
if (s->cy == s->rupper) |
|
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); |
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_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. */ |
|
|
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); |
} |
} |
} |
} |
|
|
|
|
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); |
ttyctx.cell = &ci->gc; |
if (ci->type == CLEAR) { |
ttyctx.wrapped = ci->wrapped; |
ttyctx.bg = ci->bg; |
ttyctx.ptr = ci->data; |
tty_write(tty_cmd_clearline, &ttyctx); |
ttyctx.num = ci->used; |
} else if (ci->type == CLEAR_END) { |
tty_write(tty_cmd_cells, &ttyctx); |
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++; |
items++; |
written += ci->used; |
written += ci->used; |