diff --git a/grid.c b/grid.c index 7329f855..2ca4e6c5 100644 --- a/grid.c +++ b/grid.c @@ -39,8 +39,13 @@ const struct grid_cell grid_default_cell = { 0, 0, 8, 8, { { ' ' }, 0, 1, 1 } }; -static const struct grid_cell_entry grid_default_entry = { - 0, { .data = { 0, 8, 8, ' ' } } + +/* Cleared grid cell data. */ +const struct grid_cell grid_cleared_cell = { + GRID_FLAG_CLEARED, 0, 8, 8, { { ' ' }, 0, 1, 1 } +}; +static const struct grid_cell_entry grid_cleared_entry = { + GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } } }; static void grid_empty_line(struct grid *, u_int, u_int); @@ -50,7 +55,7 @@ static void grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc, u_char c) { - gce->flags = gc->flags; + gce->flags = (gc->flags & ~GRID_FLAG_CLEARED); gce->data.fg = gc->fg & 0xff; if (gc->fg & COLOUR_FLAG_256) @@ -64,7 +69,7 @@ grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc, gce->data.data = c; } -/* Check if a cell should be extended. */ +/* Check if a cell should be an extended cell. */ static int grid_need_extended_cell(const struct grid_cell_entry *gce, const struct grid_cell *gc) @@ -80,6 +85,40 @@ grid_need_extended_cell(const struct grid_cell_entry *gce, return (0); } +/* Get an extended cell. */ +static void +grid_get_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, + int flags) +{ + u_int at = gl->extdsize + 1; + + gl->extddata = xreallocarray(gl->extddata, at, sizeof *gl->extddata); + gl->extdsize = at; + + gce->offset = at - 1; + gce->flags = (flags | GRID_FLAG_EXTENDED); +} + +/* Set cell as extended. */ +static struct grid_cell * +grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, + const struct grid_cell *gc) +{ + struct grid_cell *gcp; + int flags = (gc->flags & ~GRID_FLAG_CLEARED); + + if (~gce->flags & GRID_FLAG_EXTENDED) + grid_get_extended_cell(gl, gce, flags); + else if (gce->offset >= gl->extdsize) + fatalx("offset too big"); + gl->flags |= GRID_LINE_EXTENDED; + + gcp = &gl->extddata[gce->offset]; + memcpy(gcp, gc, sizeof *gcp); + gcp->flags = flags; + return (gcp); +} + /* Free up unused extended cells. */ static void grid_compact_line(struct grid_line *gl) @@ -122,29 +161,6 @@ grid_compact_line(struct grid_line *gl) gl->extdsize = new_extdsize; } -/* Set cell as extended. */ -static struct grid_cell * -grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, - const struct grid_cell *gc) -{ - struct grid_cell *gcp; - - gl->flags |= GRID_LINE_EXTENDED; - - if (~gce->flags & GRID_FLAG_EXTENDED) { - gl->extddata = xreallocarray(gl->extddata, gl->extdsize + 1, - sizeof *gl->extddata); - gce->offset = gl->extdsize++; - gce->flags = gc->flags | GRID_FLAG_EXTENDED; - } - if (gce->offset >= gl->extdsize) - fatalx("offset too big"); - - gcp = &gl->extddata[gce->offset]; - memcpy(gcp, gc, sizeof *gcp); - return (gcp); -} - /* Get line data. */ struct grid_line * grid_get_line(struct grid *gd, u_int line) @@ -167,9 +183,13 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg) struct grid_cell_entry *gce = &gl->celldata[px]; struct grid_cell *gc; - memcpy(gce, &grid_default_entry, sizeof *gce); + memcpy(gce, &grid_cleared_entry, sizeof *gce); if (bg & COLOUR_FLAG_RGB) { - gc = grid_extended_cell(gl, gce, &grid_default_cell); + grid_get_extended_cell(gl, gce, gce->flags); + gl->flags |= GRID_LINE_EXTENDED; + + gc = &gl->extddata[gce->offset]; + memcpy(gc, &grid_cleared_cell, sizeof *gc); gc->bg = bg; } else { if (bg & COLOUR_FLAG_256) diff --git a/tmux.h b/tmux.h index c25f80b4..0a2545d0 100644 --- a/tmux.h +++ b/tmux.h @@ -579,6 +579,7 @@ enum utf8_state { #define GRID_FLAG_EXTENDED 0x8 #define GRID_FLAG_SELECTED 0x10 #define GRID_FLAG_NOPALETTE 0x20 +#define GRID_FLAG_CLEARED 0x40 /* Grid line flags. */ #define GRID_LINE_WRAPPED 0x1 diff --git a/tty.c b/tty.c index a198b89c..cd3ea5e0 100644 --- a/tty.c +++ b/tty.c @@ -1208,7 +1208,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, u_int i, j, ux, sx, width; int flags, cleared = 0; char buf[512]; - size_t len, old_len; + size_t len; u_int cellsize; log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, @@ -1263,8 +1263,6 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, tty_putcode(tty, TTYC_EL1); cleared = 1; } - if (px + sx != 0) - tty_cursor(tty, atx, aty); } else log_debug("%s: wrapped line %u", __func__, aty); @@ -1281,10 +1279,17 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, gcp->attr != last.attr || gcp->fg != last.fg || gcp->bg != last.bg || - ux + width + gcp->data.width >= nx || + ux + width + gcp->data.width > nx || (sizeof buf) - len < gcp->data.size)) { - tty_attributes(tty, &last, wp); - tty_putn(tty, buf, len, width); + if (last.flags & GRID_FLAG_CLEARED) { + log_debug("%s: %zu cleared", __func__, len); + tty_clear_line(tty, wp, aty, atx + ux, width, + last.bg); + } else { + tty_attributes(tty, &last, wp); + tty_cursor(tty, atx + ux, aty); + tty_putn(tty, buf, len, width); + } ux += width; len = 0; @@ -1297,6 +1302,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, memcpy(&last, gcp, sizeof last); if (ux + gcp->data.width > nx) { tty_attributes(tty, &last, wp); + tty_cursor(tty, atx + ux, aty); for (j = 0; j < gcp->data.width; j++) { if (ux + j > nx) break; @@ -1305,6 +1311,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, } } else if (gcp->attr & GRID_ATTR_CHARSET) { tty_attributes(tty, &last, wp); + tty_cursor(tty, atx + ux, aty); for (j = 0; j < gcp->data.size; j++) tty_putc(tty, gcp->data.data[j]); ux += gc.data.width; @@ -1314,24 +1321,21 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, width += gcp->data.width; } } - if (len != 0) { - if (grid_cells_equal(&last, &grid_default_cell)) { - old_len = len; - while (len > 0 && buf[len - 1] == ' ') { - len--; - width--; - } - log_debug("%s: trimmed %zu spaces", __func__, - old_len - len); - } - if (len != 0) { + if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) { + if (last.flags & GRID_FLAG_CLEARED) { + log_debug("%s: %zu cleared (end)", __func__, len); + tty_clear_line(tty, wp, aty, atx + ux, width, last.bg); + } else { tty_attributes(tty, &last, wp); + tty_cursor(tty, atx + ux, aty); tty_putn(tty, buf, len, width); - ux += width; } + ux += width; } if (!cleared && ux < nx) { + log_debug("%s: %u to end of line (%zu cleared)", __func__, + nx - ux, len); tty_default_attributes(tty, wp, 8); tty_clear_line(tty, wp, aty, atx + ux, nx - ux, 8); }