Add support for BCE (background colour erase). This makes various escape

sequences (notable EL and ED but also IL, DL, ICH, DCH) create blank
cells using the current background colour rather than the default
colour.

On modern systems BCE doesn't really have many benefits, but most other
terminals now support it, some (lazy) applications rely on it, and it is
not hard to include now that we have pane background colours anyway.

Mostly written by Sean Haugh.
This commit is contained in:
nicm
2016-10-13 20:27:27 +00:00
parent 1bd08f903b
commit 4179b42424
12 changed files with 278 additions and 198 deletions

View File

@ -147,7 +147,7 @@ screen_write_reset(struct screen_write_ctx *ctx)
s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD|MODE_FOCUSON);
s->mode &= ~(ALL_MOUSE_MODES|MODE_MOUSE_UTF8|MODE_MOUSE_SGR);
screen_write_clearscreen(ctx);
screen_write_clearscreen(ctx, 8);
screen_write_cursormove(ctx, 0, 0);
}
@ -601,7 +601,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
/* Insert nx characters. */
void
screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
@ -618,15 +618,16 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
ttyctx.num = nx;
ttyctx.bg = bg;
tty_write(tty_cmd_insertcharacter, &ttyctx);
}
/* Delete nx characters. */
void
screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
@ -643,9 +644,10 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
ttyctx.num = nx;
ttyctx.bg = bg;
tty_write(tty_cmd_deletecharacter, &ttyctx);
}
@ -668,7 +670,7 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
if (s->cx <= screen_size_x(s) - 1) {
screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
grid_view_clear(s->grid, s->cx, s->cy, nx, 1, 8);
} else
return;
@ -678,7 +680,7 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
/* Insert ny lines. */
void
screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
@ -695,9 +697,10 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_insert_lines(s->grid, s->cy, ny);
grid_view_insert_lines(s->grid, s->cy, ny, bg);
ttyctx.num = ny;
ttyctx.bg = bg;
tty_write(tty_cmd_insertline, &ttyctx);
return;
}
@ -711,17 +714,20 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_insert_lines(s->grid, s->cy, ny);
else
grid_view_insert_lines_region(s->grid, s->rlower, s->cy, ny);
grid_view_insert_lines(s->grid, s->cy, ny, bg);
else {
grid_view_insert_lines_region(s->grid, s->rlower, s->cy, ny,
bg);
}
ttyctx.num = ny;
ttyctx.bg = bg;
tty_write(tty_cmd_insertline, &ttyctx);
}
/* Delete ny lines. */
void
screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
@ -738,9 +744,10 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_delete_lines(s->grid, s->cy, ny);
grid_view_delete_lines(s->grid, s->cy, ny, bg);
ttyctx.num = ny;
ttyctx.bg = bg;
tty_write(tty_cmd_deleteline, &ttyctx);
return;
}
@ -754,17 +761,20 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_delete_lines(s->grid, s->cy, ny);
else
grid_view_delete_lines_region(s->grid, s->rlower, s->cy, ny);
grid_view_delete_lines(s->grid, s->cy, ny, bg);
else {
grid_view_delete_lines_region(s->grid, s->rlower, s->cy, ny,
bg);
}
ttyctx.num = ny;
ttyctx.bg = bg;
tty_write(tty_cmd_deleteline, &ttyctx);
}
/* Clear line at cursor. */
void
screen_write_clearline(struct screen_write_ctx *ctx)
screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
{
struct screen *s = ctx->s;
struct grid_line *gl;
@ -772,20 +782,21 @@ screen_write_clearline(struct screen_write_ctx *ctx)
u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
ttyctx.bg = bg;
gl = &s->grid->linedata[s->grid->hsize + s->cy];
if (gl->cellsize != 0) {
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
} else
if (gl->cellsize == 0 && bg == 8)
return;
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
tty_write(tty_cmd_clearline, &ttyctx);
}
/* Clear to end of line from cursor. */
void
screen_write_clearendofline(struct screen_write_ctx *ctx)
screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
{
struct screen *s = ctx->s;
struct grid_line *gl;
@ -793,33 +804,35 @@ screen_write_clearendofline(struct screen_write_ctx *ctx)
u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
ttyctx.bg = bg;
gl = &s->grid->linedata[s->grid->hsize + s->cy];
if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
} else
if (s->cx > sx - 1 || (s->cx >= gl->cellsize && bg == 8))
return;
screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
tty_write(tty_cmd_clearendofline, &ttyctx);
}
/* Clear to start of line from cursor. */
void
screen_write_clearstartofline(struct screen_write_ctx *ctx)
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);
screen_write_initctx(ctx, &ttyctx);
ttyctx.bg = bg;
if (s->cx > sx - 1) {
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
} else {
screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
}
tty_write(tty_cmd_clearstartofline, &ttyctx);
@ -919,25 +932,28 @@ screen_write_carriagereturn(struct screen_write_ctx *ctx)
/* Clear to end of screen from cursor. */
void
screen_write_clearendofscreen(struct screen_write_ctx *ctx)
screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
ttyctx.bg = bg;
/* Scroll into history if it is enabled and clearing entire screen. */
if (s->cy == 0 && s->grid->flags & GRID_HISTORY) {
if (s->cx == 0 && s->cy == 0 && s->grid->flags & GRID_HISTORY) {
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
grid_view_clear_history(s->grid);
grid_view_clear_history(s->grid, bg);
} else {
if (s->cx <= sx - 1) {
screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1,
bg);
}
screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1),
bg);
}
tty_write(tty_cmd_clearendofscreen, &ttyctx);
@ -955,14 +971,14 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
if (s->cy > 0) {
screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
grid_view_clear(s->grid, 0, 0, sx, s->cy);
grid_view_clear(s->grid, 0, 0, sx, s->cy, 8);
}
if (s->cx > sx - 1) {
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
grid_view_clear(s->grid, 0, s->cy, sx, 1, 8);
} else {
screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, 8);
}
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
@ -970,21 +986,22 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
/* Clear entire screen. */
void
screen_write_clearscreen(struct screen_write_ctx *ctx)
screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
ttyctx.bg = bg;
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
/* Scroll into history if it is enabled. */
if (s->grid->flags & GRID_HISTORY)
grid_view_clear_history(s->grid);
grid_view_clear_history(s->grid, bg);
else
grid_view_clear(s->grid, 0, 0, sx, sy);
grid_view_clear(s->grid, 0, 0, sx, sy, bg);
tty_write(tty_cmd_clearscreen, &ttyctx);
}
@ -996,7 +1013,7 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
struct screen *s = ctx->s;
struct grid *gd = s->grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
grid_move_lines(gd, 0, gd->hsize, gd->sy, 8);
gd->hscrolled = gd->hsize = 0;
}
@ -1049,7 +1066,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
if (s->cx <= sx - width) {
screen_write_flush(ctx);
xx = sx - s->cx - width;
grid_view_insert_cells(s->grid, s->cx, s->cy, xx);
grid_view_insert_cells(s->grid, s->cx, s->cy, xx, 8);
}
insert = 1;
} else