diff options
Diffstat (limited to 'tty.c')
-rw-r--r-- | tty.c | 170 |
1 files changed, 124 insertions, 46 deletions
@@ -43,11 +43,14 @@ void tty_colours_fg(struct tty *, const struct grid_cell *); void tty_colours_bg(struct tty *, const struct grid_cell *); int tty_large_region(struct tty *, const struct tty_ctx *); +int tty_fake_bce(const struct tty *, const struct window_pane *); void tty_redraw_region(struct tty *, const struct tty_ctx *); void tty_emulate_repeat( struct tty *, enum tty_code_code, enum tty_code_code, u_int); void tty_repeat_space(struct tty *, u_int); -void tty_cell(struct tty *, const struct grid_cell *); +void tty_cell(struct tty *, const struct grid_cell *, + const struct window_pane *); +void tty_default_colours(struct grid_cell *, const struct window_pane *); #define tty_use_acs(tty) \ (tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) @@ -582,6 +585,23 @@ tty_large_region(unused struct tty *tty, const struct tty_ctx *ctx) } /* + * Return if BCE is needed but the terminal doesn't have it - it'll need to be + * emulated. + */ +int +tty_fake_bce(const struct tty *tty, const struct window_pane *wp) +{ + struct grid_cell gc; + + memcpy(&gc, &grid_default_cell, sizeof gc); + tty_default_colours(&gc, wp); + + if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256)) + return (0); + return (!tty_term_flag(tty->term, TTYC_BCE)); +} + +/* * Redraw scroll region using data from screen (already updated). Used when * CSR not supported, or window is a pane that doesn't take up the full * width of the terminal. @@ -604,15 +624,23 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx) if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) { for (i = ctx->ocy; i < screen_size_y(s); i++) - tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff); } else { for (i = ctx->orupper; i <= ctx->orlower; i++) - tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff); } } void -tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) +tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox, + u_int oy) +{ + tty_draw_line(tty, wp, wp->screen, py, ox, oy); +} + +void +tty_draw_line(struct tty *tty, const struct window_pane *wp, + struct screen *s, u_int py, u_int ox, u_int oy) { const struct grid_cell *gc; struct grid_line *gl; @@ -650,20 +678,20 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmpgc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); - tty_cell(tty, &tmpgc); + tty_cell(tty, &tmpgc, wp); } else - tty_cell(tty, gc); + tty_cell(tty, gc, wp); } if (sx >= tty->sx) { tty_update_mode(tty, tty->mode, s); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_cursor(tty, ox + sx, oy + py); if (sx != screen_size_x(s) && ox + screen_size_x(s) >= tty->sx && - tty_term_has(tty->term, TTYC_EL)) + tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) tty_putcode(tty, TTYC_EL); else tty_repeat_space(tty, screen_size_x(s) - sx); @@ -713,19 +741,19 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) struct window_pane *wp = ctx->wp; if (!tty_pane_full_width(tty, ctx)) { - tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (tty_term_has(tty->term, TTYC_ICH) || - tty_term_has(tty->term, TTYC_ICH1)) + if (!tty_fake_bce(tty, wp) && (tty_term_has(tty->term, TTYC_ICH) || + tty_term_has(tty->term, TTYC_ICH1))) tty_emulate_repeat(tty, TTYC_ICH, TTYC_ICH1, ctx->num); else - tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff); } void @@ -733,14 +761,14 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - if (!tty_pane_full_width(tty, ctx) || + if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, wp) || (!tty_term_has(tty->term, TTYC_DCH) && !tty_term_has(tty->term, TTYC_DCH1))) { - tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -754,11 +782,11 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) { u_int i; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (tty_term_has(tty->term, TTYC_ECH)) + if (tty_term_has(tty->term, TTYC_ECH) && !tty_fake_bce(tty, ctx->wp)) tty_putcode1(tty, TTYC_ECH, ctx->num); else { for (i = 0; i < ctx->num; i++) @@ -769,14 +797,14 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) { - if (!tty_pane_full_width(tty, ctx) || + if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_IL1)) { tty_redraw_region(tty, ctx); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -787,14 +815,14 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) { - if (!tty_pane_full_width(tty, ctx) || + if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_DL1)) { tty_redraw_region(tty, ctx); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -808,11 +836,12 @@ tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx) struct window_pane *wp = ctx->wp; struct screen *s = wp->screen; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_cursor_pane(tty, ctx, 0, ctx->ocy); - if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) + if (tty_pane_full_width(tty, ctx) && !tty_fake_bce(tty, wp) && + tty_term_has(tty->term, TTYC_EL)) tty_putcode(tty, TTYC_EL); else tty_repeat_space(tty, screen_size_x(s)); @@ -824,11 +853,12 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) struct window_pane *wp = ctx->wp; struct screen *s = wp->screen; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) + if (tty_pane_full_width(tty, ctx) && + tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) tty_putcode(tty, TTYC_EL); else tty_repeat_space(tty, screen_size_x(s) - ctx->ocx); @@ -837,9 +867,10 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) { - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); - if (ctx->xoff == 0 && tty_term_has(tty->term, TTYC_EL1)) { + if (ctx->xoff == 0 && tty_term_has(tty->term, TTYC_EL1) && + !tty_fake_bce(tty, ctx->wp)) { tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); tty_putcode(tty, TTYC_EL1); } else { @@ -854,14 +885,14 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) if (ctx->ocy != ctx->orupper) return; - if (!tty_pane_full_width(tty, ctx) || + if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_RI)) { tty_redraw_region(tty, ctx); return; } - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper); @@ -877,7 +908,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) if (ctx->ocy != ctx->orlower) return; - if (!tty_pane_full_width(tty, ctx) || + if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, wp) || !tty_term_has(tty->term, TTYC_CSR)) { if (tty_large_region(tty, ctx)) wp->flags |= PANE_REDRAW; @@ -894,7 +925,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) if (ctx->num && !(tty->term->flags & TERM_EARLYWRAP)) return; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -909,12 +940,13 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) struct screen *s = wp->screen; u_int i, j; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) { + if (tty_pane_full_width(tty, ctx) && + tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) { tty_putcode(tty, TTYC_EL); if (ctx->ocy != screen_size_y(s) - 1) { tty_cursor_pane(tty, ctx, 0, ctx->ocy + 1); @@ -942,12 +974,13 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx) struct screen *s = wp->screen; u_int i, j; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, 0, 0); - if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) { + if (tty_pane_full_width(tty, ctx) && + tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) { for (i = 0; i < ctx->ocy; i++) { tty_putcode(tty, TTYC_EL); tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); @@ -969,12 +1002,13 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) struct screen *s = wp->screen; u_int i, j; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); tty_cursor_pane(tty, ctx, 0, 0); - if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) { + if (tty_pane_full_width(tty, ctx) && + tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) { for (i = 0; i < screen_size_y(s); i++) { tty_putcode(tty, TTYC_EL); if (i != screen_size_y(s) - 1) { @@ -997,7 +1031,7 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) struct screen *s = wp->screen; u_int i, j; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, wp); tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1); @@ -1038,12 +1072,12 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) */ cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell); tty_cursor_pane(tty, ctx, cx, ctx->ocy); - tty_cell(tty, &ctx->last_cell); + tty_cell(tty, &ctx->last_cell, wp); } } else tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_cell(tty, ctx->cell); + tty_cell(tty, ctx->cell, wp); } void @@ -1055,7 +1089,7 @@ tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx) * Cannot rely on not being a partial character, so just redraw the * whole line. */ - tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff); + tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff); } void @@ -1088,12 +1122,13 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) tty->cx = tty->cy = UINT_MAX; tty->rupper = tty->rlower = UINT_MAX; - tty_reset(tty); + tty_attributes(tty, &grid_default_cell, ctx->wp); tty_cursor(tty, 0, 0); } void -tty_cell(struct tty *tty, const struct grid_cell *gc) +tty_cell(struct tty *tty, const struct grid_cell *gc, + const struct window_pane *wp) { struct utf8_data ud; u_int i; @@ -1108,7 +1143,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc) return; /* Set the attributes. */ - tty_attributes(tty, gc); + tty_attributes(tty, gc, wp); /* Get the cell and if ASCII write with putc to do ACS translation. */ grid_cell_get(gc, &ud); @@ -1312,12 +1347,14 @@ out: } void -tty_attributes(struct tty *tty, const struct grid_cell *gc) +tty_attributes(struct tty *tty, const struct grid_cell *gc, + const struct window_pane *wp) { struct grid_cell *tc = &tty->cell, gc2; u_char changed; memcpy(&gc2, gc, sizeof gc2); + tty_default_colours(&gc2, wp); /* * If no setab, try to use the reverse attribute as a best-effort for a @@ -1610,6 +1647,47 @@ tty_try_256(struct tty *tty, u_char colour, const char *type) } void +tty_default_colours(struct grid_cell *gc, const struct window_pane *wp) +{ + const struct grid_cell *agc, *pgc, *wgc; + + if (wp == NULL) + return; + + pgc = &wp->colgc; + agc = options_get_style(&wp->window->options, "window-active-style"); + wgc = options_get_style(&wp->window->options, "window-style"); + + if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) { + if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) { + gc->fg = pgc->fg; + gc->flags |= (pgc->flags & GRID_FLAG_FG256); + } else if (wp == wp->window->active && + (agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) { + gc->fg = agc->fg; + gc->flags |= (agc->flags & GRID_FLAG_FG256); + } else { + gc->fg = wgc->fg; + gc->flags |= (wgc->flags & GRID_FLAG_FG256); + } + } + + if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) { + if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) { + gc->bg = pgc->bg; + gc->flags |= (pgc->flags & GRID_FLAG_BG256); + } else if (wp == wp->window->active && + (agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) { + gc->bg = agc->bg; + gc->flags |= (agc->flags & GRID_FLAG_BG256); + } else { + gc->bg = wgc->bg; + gc->flags |= (wgc->flags & GRID_FLAG_BG256); + } + } +} + +void tty_bell(struct tty *tty) { tty_putcode(tty, TTYC_BEL); |