aboutsummaryrefslogtreecommitdiff
path: root/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'tty.c')
-rw-r--r--tty.c140
1 files changed, 103 insertions, 37 deletions
diff --git a/tty.c b/tty.c
index 34403a1f..ab1da9fd 100644
--- a/tty.c
+++ b/tty.c
@@ -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);