diff --git a/screen-write.c b/screen-write.c index c9a3fad7..f23a47d2 100644 --- a/screen-write.c +++ b/screen-write.c @@ -176,11 +176,10 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c) static int screen_write_pane_is_obscured(struct screen_write_ctx *ctx) { - struct window_pane *wp = ctx->wp; - - if (ctx->wp == NULL) - return (0); + struct window_pane *wp = ctx->wp; + if (ctx->wp == NULL) + return (0); if (ctx->flags & SCREEN_WRITE_CHECKED_IF_OBSCURED) { if (ctx->flags & SCREEN_WRITE_OBSCURED) return (1); @@ -188,21 +187,21 @@ screen_write_pane_is_obscured(struct screen_write_ctx *ctx) } ctx->flags |= SCREEN_WRITE_CHECKED_IF_OBSCURED; - while ((wp = TAILQ_PREV(wp, window_panes, zentry)) != NULL) { - if ((wp->flags & PANE_FLOATING) && - ((wp->yoff >= ctx->wp->yoff && - wp->yoff <= ctx->wp->yoff + (int)ctx->wp->sy) || - (wp->yoff + (int)wp->sy >= ctx->wp->yoff && - wp->yoff + wp->sy <= ctx->wp->yoff + ctx->wp->sy)) && - ((wp->xoff >= ctx->wp->xoff && - wp->xoff <= ctx->wp->xoff + (int)ctx->wp->sx) || - (wp->xoff + (int)wp->sx >= ctx->wp->xoff && - wp->xoff + wp->sx <= ctx->wp->xoff + ctx->wp->sx))) { + while ((wp = TAILQ_PREV(wp, window_panes, zentry)) != NULL) { + if ((wp->flags & PANE_FLOATING) && + ((wp->yoff >= ctx->wp->yoff && + wp->yoff <= ctx->wp->yoff + (int)ctx->wp->sy) || + (wp->yoff + (int)wp->sy >= ctx->wp->yoff && + wp->yoff + wp->sy <= ctx->wp->yoff + ctx->wp->sy)) && + ((wp->xoff >= ctx->wp->xoff && + wp->xoff <= ctx->wp->xoff + (int)ctx->wp->sx) || + (wp->xoff + (int)wp->sx >= ctx->wp->xoff && + wp->xoff + wp->sx <= ctx->wp->xoff + ctx->wp->sx))) { ctx->flags |= SCREEN_WRITE_OBSCURED; - return (1); + return (1); } - } - return (0); + } + return (0); } /* Set up context for TTY command. */ @@ -394,9 +393,9 @@ size_t screen_write_strlen(const char *fmt, ...) { va_list ap; - char *msg; + char *msg; struct utf8_data ud; - u_char *ptr; + u_char *ptr; size_t left, size = 0; enum utf8_state more; @@ -549,9 +548,9 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen, { struct grid_cell gc; struct utf8_data *ud = &gc.data; - char *msg; - u_char *ptr; - size_t left, size = 0; + char *msg; + u_char *ptr; + size_t left, size = 0; enum utf8_state more; memcpy(&gc, gcp, sizeof gc); @@ -610,11 +609,11 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src, { struct screen *s = ctx->s; struct window_pane *wp = ctx->wp; - struct tty_ctx ttyctx; + struct tty_ctx ttyctx; struct grid *gd = src->grid; struct grid_line *gl, *sgl; struct grid_cell gc; - u_int xx, yy, cx = s->cx, cy = s->cy; + u_int xx, yy, cx = s->cx, cy = s->cy; if (nx == 0 || ny == 0) return; @@ -657,28 +656,28 @@ screen_write_box_border_set(enum box_lines lines, int cell_type, struct grid_cell *gc) { switch (lines) { - case BOX_LINES_NONE: + case BOX_LINES_NONE: break; - case BOX_LINES_DOUBLE: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); + case BOX_LINES_DOUBLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); break; - case BOX_LINES_HEAVY: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); + case BOX_LINES_HEAVY: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); break; - case BOX_LINES_ROUNDED: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); + case BOX_LINES_ROUNDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); + break; + case BOX_LINES_SIMPLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); + break; + case BOX_LINES_PADDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, PADDED_BORDERS[cell_type]); break; - case BOX_LINES_SIMPLE: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); - break; - case BOX_LINES_PADDED: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_set(&gc->data, PADDED_BORDERS[cell_type]); - break; case BOX_LINES_SINGLE: case BOX_LINES_DEFAULT: gc->attr |= GRID_ATTR_CHARSET; @@ -806,7 +805,7 @@ screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny, enum box_lines lines, const struct grid_cell *gcp, const char *title) { struct screen *s = ctx->s; - struct grid_cell gc; + struct grid_cell gc; u_int cx, cy, i; cx = s->cx; @@ -1105,13 +1104,54 @@ screen_write_backspace(struct screen_write_ctx *ctx) screen_write_set_cursor(ctx, cx, cy); } +/* Redraw all visible cells on a line. */ +static void +screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, + u_int yy) +{ + struct window_pane *wp = ctx->wp; + struct screen *s = ctx->s; + struct grid_cell gc; + u_int sx = screen_size_x(s),cx, i, n; + u_int xoff = wp->xoff, yoff = wp->yoff; + struct visible_ranges *r; + struct visible_range *ri; + + r = screen_redraw_get_visible_ranges(wp, xoff, yoff + yy, sx, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + + cx = ri->px - xoff; + for (n = 0; n < ri->nx && cx < sx; n++, cx++) { + grid_view_get_cell(s->grid, cx, yy, &gc); + ttyctx->ocx = cx; + ttyctx->ocy = yy; + ttyctx->cell = &gc; + tty_write(tty_cmd_cell, ttyctx); + } + } +} + +/* Redraw all visible cells in a pane. */ +static void +screen_write_redraw_pane(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) +{ + struct screen *s = ctx->s; + u_int yy; + + for (yy = 0; yy < screen_size_y(s); yy++) + screen_write_redraw_line(ctx, ttyctx, yy); +} + /* VT100 alignment test. */ void screen_write_alignmenttest(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; - struct tty_ctx ttyctx; - struct grid_cell gc; + struct tty_ctx ttyctx; + struct grid_cell gc; u_int xx, yy; memcpy(&gc, &grid_default_cell, sizeof gc); @@ -1127,10 +1167,16 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) s->rupper = 0; s->rlower = screen_size_y(s) - 1; + screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1); + screen_write_initctx(ctx, &ttyctx, 1, 1); - screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1); - tty_write(tty_cmd_alignmenttest, &ttyctx); + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_alignmenttest, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); } /* Insert nx characters. */ @@ -1158,7 +1204,13 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_insertcharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertcharacter, &ttyctx); + return; + } + + screen_write_redraw_line(ctx, &ttyctx, s->cy); } /* Delete nx characters. */ @@ -1186,7 +1238,13 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_deletecharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deletecharacter, &ttyctx); + return; + } + + screen_write_redraw_line(ctx, &ttyctx, s->cy); } /* Clear nx characters. */ @@ -1207,14 +1265,20 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) if (s->cx > screen_size_x(s) - 1) return; - screen_write_initctx(ctx, &ttyctx, 0, 0); + screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.bg = bg; grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg); screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; - tty_write(tty_cmd_clearcharacter, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_clearcharacter, &ttyctx); + return; + } + + screen_write_redraw_line(ctx, &ttyctx, s->cy); } /* Insert ny lines. */ @@ -1224,13 +1288,14 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) struct screen *s = ctx->s; struct grid *gd = s->grid; struct tty_ctx ttyctx; + u_int sy = screen_size_y(s); if (ny == 0) ny = 1; if (s->cy < s->rupper || s->cy > s->rlower) { - if (ny > screen_size_y(s) - s->cy) - ny = screen_size_y(s) - s->cy; + if (ny > sy - s->cy) + ny = sy - s->cy; if (ny == 0) return; @@ -1241,7 +1306,13 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_insertline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertline, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); return; } @@ -1259,9 +1330,14 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) grid_view_insert_lines_region(gd, s->rlower, s->cy, ny, bg); screen_write_collect_flush(ctx, 0, __func__); - ttyctx.n = ny; - tty_write(tty_cmd_insertline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_insertline, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); } /* Delete ny lines. */ @@ -1289,7 +1365,13 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_deleteline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deleteline, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); return; } @@ -1308,7 +1390,13 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; - tty_write(tty_cmd_deleteline, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_deleteline, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); } /* Clear line at cursor. */ @@ -1418,17 +1506,20 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) struct tty_ctx ttyctx; if (s->cy == s->rupper) { - grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); screen_write_collect_flush(ctx, 0, __func__); - screen_write_initctx(ctx, &ttyctx, 1, 0); + screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; - tty_write(tty_cmd_reverseindex, &ttyctx); + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_reverseindex, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); } else if (s->cy > 0) screen_write_set_cursor(ctx, -1, s->cy - 1); - } /* Set scroll region. */ @@ -1530,7 +1621,13 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = lines; - tty_write(tty_cmd_scrolldown, &ttyctx); + + if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { + tty_write(tty_cmd_scrolldown, &ttyctx); + return; + } + + screen_write_redraw_pane(ctx, &ttyctx); } /* Carriage return (cursor to start of line). */ @@ -1770,36 +1867,34 @@ static void screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only, const char *from) { + struct window_pane *wp = ctx->wp; struct screen *s = ctx->s; struct screen_write_citem *ci, *tmp; struct screen_write_cline *cl; u_int y, cx, cy, last, items = 0; struct tty_ctx ttyctx; - if (s->mode & MODE_SYNC) { - for (y = 0; y < screen_size_y(s); y++) { - cl = &ctx->s->write_list[y]; - TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) { - TAILQ_REMOVE(&cl->items, ci, entry); - screen_write_free_citem(ci); - } - } - return; - } + if (s->mode & MODE_SYNC) + goto discard; if (ctx->scrolled != 0) { + screen_write_initctx(ctx, &ttyctx, 1, 1); + if (ttyctx.flags & TTY_CTX_PANE_OBSCURED && wp != NULL) { + screen_write_redraw_pane(ctx, &ttyctx); + goto discard; + } + log_debug("%s: scrolled %u (region %u-%u)", __func__, ctx->scrolled, s->rupper, s->rlower); if (ctx->scrolled > s->rlower - s->rupper + 1) ctx->scrolled = s->rlower - s->rupper + 1; - screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.n = ctx->scrolled; ttyctx.bg = ctx->bg; tty_write(tty_cmd_scrollup, &ttyctx); - if (ctx->wp != NULL) - ctx->wp->flags |= PANE_REDRAWSCROLLBAR; + if (wp != NULL) + wp->flags |= PANE_REDRAWSCROLLBAR; } ctx->scrolled = 0; ctx->bg = 8; @@ -1843,6 +1938,18 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only, s->cx = cx; s->cy = cy; log_debug("%s: flushed %u items (%s)", __func__, items, from); + return; + +discard: + for (y = 0; y < screen_size_y(s); y++) { + cl = &ctx->s->write_list[y]; + TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) { + TAILQ_REMOVE(&cl->items, ci, entry); + screen_write_free_citem(ci); + } + } + ctx->scrolled = 0; + ctx->bg = 8; } /* Insert an item on current line. */ diff --git a/tty.c b/tty.c index 9746d6b7..4fab57ae 100644 --- a/tty.c +++ b/tty.c @@ -1559,7 +1559,7 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_ICH) && @@ -1582,7 +1582,7 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_DCH) && @@ -1614,7 +1614,7 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1642,7 +1642,7 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1702,7 +1702,7 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) if (ctx->ocy != ctx->orupper) return; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1777,7 +1777,7 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) struct client *c = tty->client; u_int i; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1816,7 +1816,7 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) u_int i; struct client *c = tty->client; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1919,7 +1919,7 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) struct client *c = tty->client; u_int i, j; - if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || c->overlay_check != NULL) { ctx->redraw_cb(ctx); return;