diff options
Diffstat (limited to 'tty.c')
-rw-r--r-- | tty.c | 140 |
1 files changed, 103 insertions, 37 deletions
@@ -49,8 +49,11 @@ static void tty_check_fg(struct tty *, struct window_pane *, struct grid_cell *); static void tty_check_bg(struct tty *, struct window_pane *, struct grid_cell *); +static void tty_check_us(struct tty *, struct window_pane *, + struct grid_cell *); static void tty_colours_fg(struct tty *, const struct grid_cell *); static void tty_colours_bg(struct tty *, const struct grid_cell *); +static void tty_colours_us(struct tty *, const struct grid_cell *); static void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, u_int); @@ -527,6 +530,12 @@ tty_putc(struct tty *tty, u_char ch) { const char *acs; + if ((tty->term->flags & TERM_EARLYWRAP) && + ch >= 0x20 && ch != 0x7f && + tty->cy == tty->sy - 1 && + tty->cx + 1 >= tty->sx) + return; + if (tty->cell.attr & GRID_ATTR_CHARSET) { acs = tty_acs_get(tty, ch); if (acs != NULL) @@ -557,6 +566,11 @@ tty_putc(struct tty *tty, u_char ch) void tty_putn(struct tty *tty, const void *buf, size_t len, u_int width) { + if ((tty->term->flags & TERM_EARLYWRAP) && + tty->cy == tty->sy - 1 && + tty->cx + len >= tty->sx) + len = tty->sx - tty->cx - 1; + tty_add(tty, buf, len); if (tty->cx + width > tty->sx) { tty->cx = (tty->cx + width) - tty->sx; @@ -1049,17 +1063,17 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, *y = ctx->yoff + py - ctx->oy; *ry = ny; } else if (yoff < ctx->oy && yoff + ny > ctx->oy + ctx->sy) { - /* Both left and right not visible. */ + /* Both top and bottom not visible. */ *j = ctx->oy; *y = 0; *ry = ctx->sy; } else if (yoff < ctx->oy) { - /* Left not visible. */ + /* Top not visible. */ *j = ctx->oy - (ctx->yoff + py); *y = 0; *ry = ny - *j; } else { - /* Right not visible. */ + /* Bottom not visible. */ *j = 0; *y = (ctx->yoff + py) - ctx->oy; *ry = ctx->sy - *y; @@ -1203,7 +1217,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, const struct grid_cell *gcp; struct grid_line *gl; u_int i, j, ux, sx, width; - int flags, cleared = 0; + int flags, cleared = 0, wrapped = 0; char buf[512]; size_t len; u_int cellsize; @@ -1260,8 +1274,10 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, tty_putcode(tty, TTYC_EL1); cleared = 1; } - } else + } else { log_debug("%s: wrapped line %u", __func__, aty); + wrapped = 1; + } memcpy(&last, &grid_default_cell, sizeof last); len = 0; @@ -1276,6 +1292,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, gcp->attr != last.attr || gcp->fg != last.fg || gcp->bg != last.bg || + gcp->us != last.us || ux + width + gcp->data.width > nx || (sizeof buf) - len < gcp->data.size)) { tty_attributes(tty, &last, wp); @@ -1284,13 +1301,15 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, tty_clear_line(tty, wp, aty, atx + ux, width, last.bg); } else { - tty_cursor(tty, atx + ux, aty); + if (!wrapped || atx != 0 || ux != 0) + tty_cursor(tty, atx + ux, aty); tty_putn(tty, buf, len, width); } ux += width; len = 0; width = 0; + wrapped = 0; } if (gcp->flags & GRID_FLAG_SELECTED) @@ -1324,7 +1343,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, log_debug("%s: %zu cleared (end)", __func__, len); tty_clear_line(tty, wp, aty, atx + ux, width, last.bg); } else { - tty_cursor(tty, atx + ux, aty); + if (!wrapped || atx != 0 || ux != 0) + tty_cursor(tty, atx + ux, aty); tty_putn(tty, buf, len, width); } ux += width; @@ -2121,10 +2141,11 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, /* Ignore cell if it is the same as the last one. */ if (wp != NULL && (int)wp->id == tty->last_wp && - ~(wp->window->flags & WINDOW_STYLECHANGED) && + ~(wp->flags & PANE_STYLECHANGED) && gc->attr == tty->last_cell.attr && gc->fg == tty->last_cell.fg && - gc->bg == tty->last_cell.bg) + gc->bg == tty->last_cell.bg && + gc->us == tty->last_cell.us) return; tty->last_wp = (wp != NULL ? (int)wp->id : -1); memcpy(&tty->last_cell, gc, sizeof tty->last_cell); @@ -2152,14 +2173,18 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, /* Fix up the colours if necessary. */ tty_check_fg(tty, wp, &gc2); tty_check_bg(tty, wp, &gc2); + tty_check_us(tty, wp, &gc2); - /* If any bits are being cleared, reset everything. */ - if (tc->attr & ~gc2.attr) + /* + * If any bits are being cleared or the underline colour is now default, + * reset everything. + */ + if ((tc->attr & ~gc2.attr) || (tc->us != gc2.us && gc2.us == 0)) tty_reset(tty); /* * Set the colours. This may call tty_reset() (so it comes next) and - * may add to (NOT remove) the desired attributes by changing new_attr. + * may add to (NOT remove) the desired attributes. */ tty_colours(tty, &gc2); @@ -2212,7 +2237,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc) int have_ax; /* No changes? Nothing is necessary. */ - if (gc->fg == tc->fg && gc->bg == tc->bg) + if (gc->fg == tc->fg && gc->bg == tc->bg && gc->us == tc->us) return; /* @@ -2260,6 +2285,10 @@ tty_colours(struct tty *tty, const struct grid_cell *gc) */ if (!COLOUR_DEFAULT(gc->bg) && gc->bg != tc->bg) tty_colours_bg(tty, gc); + + /* Set the underscore color. */ + if (gc->us != tc->us) + tty_colours_us(tty, gc); } static void @@ -2375,6 +2404,22 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) } static void +tty_check_us(__unused struct tty *tty, struct window_pane *wp, struct grid_cell *gc) +{ + int c; + + /* Perform substitution if this pane has a palette. */ + if (~gc->flags & GRID_FLAG_NOPALETTE) { + if ((c = window_pane_get_palette(wp, gc->us)) != -1) + gc->us = c; + } + + /* Underscore colour is set as RGB so convert a 256 colour to RGB. */ + if (gc->us & COLOUR_FLAG_256) + gc->us = colour_256toRGB (gc->us); +} + +static void tty_colours_fg(struct tty *tty, const struct grid_cell *gc) { struct grid_cell *tc = &tty->cell; @@ -2438,6 +2483,31 @@ save_bg: tc->bg = gc->bg; } +static void +tty_colours_us(struct tty *tty, const struct grid_cell *gc) +{ + struct grid_cell *tc = &tty->cell; + u_int c; + u_char r, g, b; + + /* Must be an RGB colour - this should never happen. */ + if (~gc->us & COLOUR_FLAG_RGB) + return; + + /* + * Setulc follows the ncurses(3) one argument "direct colour" + * capability format. Calculate the colour value. + */ + colour_split_rgb(gc->us, &r, &g, &b); + c = (65536 * r) + (256 * g) + b; + + /* Write the colour. */ + tty_putcode1(tty, TTYC_SETULC, c); + + /* Save the new values in the terminal current cell. */ + tc->us = gc->us; +} + static int tty_try_colour(struct tty *tty, int colour, const char *type) { @@ -2503,30 +2573,28 @@ fallback_256: static void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { - struct window *w = wp->window; - struct options *oo = w->options; - struct style *active, *pane, *window; - int c; - - if (w->flags & WINDOW_STYLECHANGED) { - w->flags &= ~WINDOW_STYLECHANGED; - active = options_get_style(oo, "window-active-style"); - style_copy(&w->active_style, active); - window = options_get_style(oo, "window-style"); - style_copy(&w->style, window); + struct options *oo = wp->options; + struct style *style, *active_style; + int c; + + if (wp->flags & PANE_STYLECHANGED) { + wp->flags &= ~PANE_STYLECHANGED; + + active_style = options_get_style(oo, "window-active-style"); + style = options_get_style(oo, "window-style"); + + style_copy(&wp->cached_active_style, active_style); + style_copy(&wp->cached_style, style); } else { - active = &w->active_style; - window = &w->style; + active_style = &wp->cached_active_style; + style = &wp->cached_style; } - pane = &wp->style; if (gc->fg == 8) { - if (pane->gc.fg != 8) - gc->fg = pane->gc.fg; - else if (wp == w->active && active->gc.fg != 8) - gc->fg = active->gc.fg; + if (wp == wp->window->active && active_style->gc.fg != 8) + gc->fg = active_style->gc.fg; else - gc->fg = window->gc.fg; + gc->fg = style->gc.fg; if (gc->fg != 8) { c = window_pane_get_palette(wp, gc->fg); @@ -2536,12 +2604,10 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) } if (gc->bg == 8) { - if (pane->gc.bg != 8) - gc->bg = pane->gc.bg; - else if (wp == w->active && active->gc.bg != 8) - gc->bg = active->gc.bg; + if (wp == wp->window->active && active_style->gc.bg != 8) + gc->bg = active_style->gc.bg; else - gc->bg = window->gc.bg; + gc->bg = style->gc.bg; if (gc->bg != 8) { c = window_pane_get_palette(wp, gc->bg); |