summaryrefslogtreecommitdiffstats
path: root/grid.c
diff options
context:
space:
mode:
authornicm <nicm>2016-10-13 20:27:27 +0000
committernicm <nicm>2016-10-13 20:27:27 +0000
commit4179b4242411f41a22d9743b4eff3b19ef69b3e8 (patch)
treec50ccb7dac6c4ddc71a666aeaaba5c489e703946 /grid.c
parent1bd08f903b8f70b0dd9aad577f830d944b969516 (diff)
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.
Diffstat (limited to 'grid.c')
-rw-r--r--grid.c106
1 files changed, 60 insertions, 46 deletions
diff --git a/grid.c b/grid.c
index 35de2aef..d0a28463 100644
--- a/grid.c
+++ b/grid.c
@@ -43,7 +43,8 @@ const struct grid_cell_entry grid_default_entry = {
0, { .data = { 0, 8, 8, ' ' } }
};
-static void grid_expand_line(struct grid *, u_int, u_int);
+static void grid_expand_line(struct grid *, u_int, u_int, u_int);
+static void grid_empty_line(struct grid *, u_int, u_int);
static void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *,
u_int, u_int);
@@ -60,9 +61,10 @@ static void grid_string_cells_code(const struct grid_cell *,
/* Copy default into a cell. */
static void
-grid_clear_cell(struct grid *gd, u_int px, u_int py)
+grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
{
gd->linedata[py].celldata[px] = grid_default_entry;
+ gd->linedata[py].celldata[px].data.bg = bg;
}
/* Check grid y position. */
@@ -162,7 +164,7 @@ grid_compare(struct grid *ga, struct grid *gb)
* and shift up.
*/
void
-grid_collect_history(struct grid *gd)
+grid_collect_history(struct grid *gd, u_int bg)
{
u_int yy;
@@ -173,7 +175,7 @@ grid_collect_history(struct grid *gd)
if (yy < 1)
yy = 1;
- grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
+ grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy, bg);
gd->hsize -= yy;
if (gd->hscrolled > gd->hsize)
gd->hscrolled = gd->hsize;
@@ -184,14 +186,14 @@ grid_collect_history(struct grid *gd)
* allocate a new line at the bottom and move the history size indicator.
*/
void
-grid_scroll_history(struct grid *gd)
+grid_scroll_history(struct grid *gd, u_int bg)
{
u_int yy;
yy = gd->hsize + gd->sy;
gd->linedata = xreallocarray(gd->linedata, yy + 1,
sizeof *gd->linedata);
- memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
+ grid_empty_line(gd, yy, bg);
gd->hscrolled++;
gd->hsize++;
@@ -201,8 +203,8 @@ grid_scroll_history(struct grid *gd)
void
grid_clear_history(struct grid *gd)
{
- grid_clear_lines(gd, 0, gd->hsize);
- grid_move_lines(gd, 0, gd->hsize, gd->sy);
+ grid_clear_lines(gd, 0, gd->hsize, 8);
+ grid_move_lines(gd, 0, gd->hsize, gd->sy, 8);
gd->hscrolled = 0;
gd->hsize = 0;
@@ -247,7 +249,7 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
/* Expand line to fit to cell. */
static void
-grid_expand_line(struct grid *gd, u_int py, u_int sx)
+grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
{
struct grid_line *gl;
u_int xx;
@@ -258,10 +260,19 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
for (xx = gl->cellsize; xx < sx; xx++)
- grid_clear_cell(gd, xx, py);
+ grid_clear_cell(gd, xx, py, bg);
gl->cellsize = sx;
}
+/* Empty a line and set background colour if needed. */
+static void
+grid_empty_line(struct grid *gd, u_int py, u_int bg)
+{
+ memset(&gd->linedata[py], 0, sizeof gd->linedata[py]);
+ if (bg != 8)
+ grid_expand_line(gd, py, gd->sx, bg);
+}
+
/* Peek at grid line. */
const struct grid_line *
grid_peek_line(struct grid *gd, u_int py)
@@ -317,11 +328,14 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
if (grid_check_y(gd, py) != 0)
return;
- grid_expand_line(gd, py, px + 1);
+ grid_expand_line(gd, py, px + 1, 8);
gl = &gd->linedata[py];
gce = &gl->celldata[px];
+ if (px + 1 > gl->cellused)
+ gl->cellused = px + 1;
+
extended = (gce->flags & GRID_FLAG_EXTENDED);
if (!extended && (gc->data.size != 1 || gc->data.width != 1))
extended = 1;
@@ -358,7 +372,7 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
/* Clear area. */
void
-grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
+grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
{
u_int xx, yy;
@@ -366,7 +380,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
return;
if (px == 0 && nx == gd->sx) {
- grid_clear_lines(gd, py, ny);
+ grid_clear_lines(gd, py, ny, bg);
return;
}
@@ -376,23 +390,23 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
return;
for (yy = py; yy < py + ny; yy++) {
- if (px >= gd->linedata[yy].cellsize)
+ if (px + nx >= gd->sx && px < gd->linedata[yy].cellused)
+ gd->linedata[yy].cellused = px;
+ if (px > gd->linedata[yy].cellsize && bg == 8)
continue;
- if (px + nx >= gd->linedata[yy].cellsize) {
+ if (px + nx >= gd->linedata[yy].cellsize && bg == 8) {
gd->linedata[yy].cellsize = px;
continue;
}
- for (xx = px; xx < px + nx; xx++) {
- if (xx >= gd->linedata[yy].cellsize)
- break;
- grid_clear_cell(gd, xx, yy);
- }
+ grid_expand_line(gd, yy, px + nx, bg);
+ for (xx = px; xx < px + nx; xx++)
+ grid_clear_cell(gd, xx, yy, bg);
}
}
/* Clear lines. This just frees and truncates the lines. */
void
-grid_clear_lines(struct grid *gd, u_int py, u_int ny)
+grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg)
{
struct grid_line *gl;
u_int yy;
@@ -409,13 +423,13 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
gl = &gd->linedata[yy];
free(gl->celldata);
free(gl->extddata);
- memset(gl, 0, sizeof *gl);
+ grid_empty_line(gd, yy, bg);
}
}
/* Move a group of lines. */
void
-grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
+grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg)
{
u_int yy;
@@ -435,7 +449,7 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
for (yy = dy; yy < dy + ny; yy++) {
if (yy >= py && yy < py + ny)
continue;
- grid_clear_lines(gd, yy, 1);
+ grid_clear_lines(gd, yy, 1, bg);
}
memmove(&gd->linedata[dy], &gd->linedata[py],
@@ -443,15 +457,15 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
/* Wipe any lines that have been moved (without freeing them). */
for (yy = py; yy < py + ny; yy++) {
- if (yy >= dy && yy < dy + ny)
- continue;
- memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
+ if (yy < dy || yy >= dy + ny)
+ grid_empty_line(gd, yy, bg);
}
}
/* Move a group of cells. */
void
-grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
+grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx,
+ u_int bg)
{
struct grid_line *gl;
u_int xx;
@@ -463,8 +477,8 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
return;
gl = &gd->linedata[py];
- grid_expand_line(gd, py, px + nx);
- grid_expand_line(gd, py, dx + nx);
+ grid_expand_line(gd, py, px + nx, 8);
+ grid_expand_line(gd, py, dx + nx, 8);
memmove(&gl->celldata[dx], &gl->celldata[px],
nx * sizeof *gl->celldata);
@@ -472,7 +486,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
for (xx = px; xx < px + nx; xx++) {
if (xx >= dx && xx < dx + nx)
continue;
- grid_clear_cell(gd, xx, py);
+ grid_clear_cell(gd, xx, py, bg);
}
}
@@ -748,7 +762,7 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
ny = dst->hsize + dst->sy - dy;
if (sy + ny > src->hsize + src->sy)
ny = src->hsize + src->sy - sy;
- grid_clear_lines(dst, dy, ny);
+ grid_clear_lines(dst, dy, ny, 8);
for (yy = 0; yy < ny; yy++) {
srcl = &src->linedata[sy];
@@ -810,28 +824,28 @@ grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
u_int left, to_copy, ox, nx;
/* How much is left on the old line? */
- left = new_x - dst_gl->cellsize;
+ left = new_x - dst_gl->cellused;
/* Work out how much to append. */
- to_copy = src_gl->cellsize;
+ to_copy = src_gl->cellused;
if (to_copy > left)
to_copy = left;
- ox = dst_gl->cellsize;
+ ox = dst_gl->cellused;
nx = ox + to_copy;
/* Resize the destination line. */
dst_gl->celldata = xreallocarray(dst_gl->celldata, nx,
sizeof *dst_gl->celldata);
- dst_gl->cellsize = nx;
+ dst_gl->cellsize = dst_gl->cellused = nx;
/* Append as much as possible. */
grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy);
/* If there is any left in the source, split it. */
- if (src_gl->cellsize > to_copy) {
+ if (src_gl->cellused > to_copy) {
dst_gl->flags |= GRID_LINE_WRAPPED;
- src_gl->cellsize -= to_copy;
+ src_gl->cellused -= to_copy;
grid_reflow_split(dst, py, src_gl, new_x, to_copy);
}
}
@@ -845,22 +859,22 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
u_int to_copy;
/* Loop and copy sections of the source line. */
- while (src_gl->cellsize > 0) {
+ while (src_gl->cellused > 0) {
/* Create new line. */
if (*py >= dst->hsize + dst->sy)
- grid_scroll_history(dst);
+ grid_scroll_history(dst, 8);
dst_gl = &dst->linedata[*py];
(*py)++;
/* How much should we copy? */
to_copy = new_x;
- if (to_copy > src_gl->cellsize)
- to_copy = src_gl->cellsize;
+ if (to_copy > src_gl->cellused)
+ to_copy = src_gl->cellused;
/* Expand destination line. */
dst_gl->celldata = xreallocarray(NULL, to_copy,
sizeof *dst_gl->celldata);
- dst_gl->cellsize = to_copy;
+ dst_gl->cellsize = dst_gl->cellused = to_copy;
dst_gl->flags |= GRID_LINE_WRAPPED;
/* Copy the data. */
@@ -868,7 +882,7 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
/* Move offset and reduce old line size. */
offset += to_copy;
- src_gl->cellsize -= to_copy;
+ src_gl->cellused -= to_copy;
}
/* Last line is not wrapped. */
@@ -884,7 +898,7 @@ grid_reflow_move(struct grid *dst, u_int *py, struct grid_line *src_gl)
/* Create new line. */
if (*py >= dst->hsize + dst->sy)
- grid_scroll_history(dst);
+ grid_scroll_history(dst, 8);
dst_gl = &dst->linedata[*py];
(*py)++;
@@ -916,7 +930,7 @@ grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
src_gl = src->linedata + line;
if (!previous_wrapped) {
/* Wasn't wrapped. If smaller, move to destination. */
- if (src_gl->cellsize <= new_x)
+ if (src_gl->cellused <= new_x)
grid_reflow_move(dst, &py, src_gl);
else
grid_reflow_split(dst, &py, src_gl, new_x, 0);