aboutsummaryrefslogtreecommitdiff
path: root/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'tty.c')
-rw-r--r--tty.c828
1 files changed, 404 insertions, 424 deletions
diff --git a/tty.c b/tty.c
index 8efe57b5..c8efeac7 100644
--- a/tty.c
+++ b/tty.c
@@ -34,7 +34,7 @@
static int tty_log_fd = -1;
-static int tty_client_ready(struct client *, struct window_pane *);
+static int tty_client_ready(struct client *);
static void tty_set_italics(struct tty *);
static int tty_try_colour(struct tty *, int, const char *);
@@ -45,12 +45,9 @@ static void tty_cursor_pane_unless_wrap(struct tty *,
const struct tty_ctx *, u_int, u_int);
static void tty_invalidate(struct tty *);
static void tty_colours(struct tty *, const struct grid_cell *);
-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_check_fg(struct tty *, int *, struct grid_cell *);
+static void tty_check_bg(struct tty *, int *, struct grid_cell *);
+static void tty_check_us(struct tty *, int *, 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 *);
@@ -61,23 +58,22 @@ static void tty_region(struct tty *, u_int, u_int);
static void tty_margin_pane(struct tty *, const struct tty_ctx *);
static void tty_margin(struct tty *, u_int, u_int);
static int tty_large_region(struct tty *, const struct tty_ctx *);
-static int tty_fake_bce(const struct tty *, struct window_pane *, u_int);
+static int tty_fake_bce(const struct tty *, const struct grid_cell *,
+ u_int);
static void tty_redraw_region(struct tty *, const struct tty_ctx *);
static void tty_emulate_repeat(struct tty *, enum tty_code_code,
enum tty_code_code, u_int);
static void tty_repeat_space(struct tty *, u_int);
static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
static void tty_cell(struct tty *, const struct grid_cell *,
- struct window_pane *);
-static void tty_default_colours(struct grid_cell *, struct window_pane *);
-static void tty_default_attributes(struct tty *, struct window_pane *,
- u_int);
+ const struct grid_cell *, int *);
+static void tty_default_attributes(struct tty *, const struct grid_cell *,
+ int *, u_int);
#define tty_use_margin(tty) \
- ((tty->term->flags|tty->term_flags) & TERM_DECSLRM)
-
-#define tty_pane_full_width(tty, ctx) \
- ((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
+ (tty->term->flags & TERM_DECSLRM)
+#define tty_full_width(tty, ctx) \
+ ((ctx)->xoff == 0 && (ctx)->sx >= (tty)->sx)
#define TTY_BLOCK_INTERVAL (100000 /* 100 milliseconds */)
#define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8)
@@ -96,27 +92,19 @@ tty_create_log(void)
}
int
-tty_init(struct tty *tty, struct client *c, int fd, char *term)
+tty_init(struct tty *tty, struct client *c, int fd)
{
if (!isatty(fd))
return (-1);
memset(tty, 0, sizeof *tty);
- if (term == NULL || *term == '\0')
- tty->term_name = xstrdup("unknown");
- else
- tty->term_name = xstrdup(term);
-
tty->fd = fd;
tty->client = c;
tty->cstyle = 0;
tty->ccolour = xstrdup("");
- tty->flags = 0;
- tty->term_flags = 0;
-
return (0);
}
@@ -256,7 +244,10 @@ tty_write_callback(__unused int fd, __unused short events, void *data)
int
tty_open(struct tty *tty, char **cause)
{
- tty->term = tty_term_find(tty->term_name, tty->fd, cause);
+ struct client *c = tty->client;
+
+ tty->term = tty_term_create(tty, c->term_name, &c->term_features,
+ tty->fd, cause);
if (tty->term == NULL) {
tty_close(tty);
return (-1);
@@ -292,7 +283,7 @@ tty_start_timer_callback(__unused int fd, __unused short events, void *data)
struct client *c = tty->client;
log_debug("%s: start timer fired", c->name);
- tty->flags |= (TTY_HAVEDA|TTY_HAVEDSR);
+ tty->flags |= (TTY_HAVEDA|TTY_HAVEXDA);
}
void
@@ -335,17 +326,12 @@ tty_start_tty(struct tty *tty)
tty_puts(tty, "\033[?1006l\033[?1005l");
}
- if (tty_term_flag(tty->term, TTYC_XT)) {
- if (options_get_number(global_options, "focus-events")) {
- tty->flags |= TTY_FOCUS;
- tty_puts(tty, "\033[?1004h");
- }
- if (~tty->flags & TTY_HAVEDA)
- tty_puts(tty, "\033[c");
- if (~tty->flags & TTY_HAVEDSR)
- tty_puts(tty, "\033[1337n");
- } else
- tty->flags |= (TTY_HAVEDA|TTY_HAVEDSR);
+ if (options_get_number(global_options, "focus-events")) {
+ tty->flags |= TTY_FOCUS;
+ tty_raw(tty, tty_term_string(tty->term, TTYC_ENFCS));
+ }
+ if (tty->term->flags & TERM_VT100LIKE)
+ tty_puts(tty, "\033[?7727h");
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
evtimer_add(&tty->start_timer, &tv);
@@ -362,6 +348,21 @@ tty_start_tty(struct tty *tty)
}
void
+tty_send_requests(struct tty *tty)
+{
+ if (~tty->flags & TTY_STARTED)
+ return;
+
+ if (tty->term->flags & TERM_VT100LIKE) {
+ if (~tty->flags & TTY_HAVEDA)
+ tty_puts(tty, "\033[>c");
+ if (~tty->flags & TTY_HAVEXDA)
+ tty_puts(tty, "\033[>q");
+ } else
+ tty->flags |= (TTY_HAVEDA|TTY_HAVEXDA);
+}
+
+void
tty_stop_tty(struct tty *tty)
{
struct winsize ws;
@@ -401,7 +402,7 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0));
}
if (tty->mode & MODE_BRACKETPASTE)
- tty_raw(tty, "\033[?2004l");
+ tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP));
if (*tty->ccolour != '\0')
tty_raw(tty, tty_term_string(tty->term, TTYC_CR));
@@ -411,15 +412,15 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, "\033[?1006l\033[?1005l");
}
- if (tty_term_flag(tty->term, TTYC_XT)) {
- if (tty->flags & TTY_FOCUS) {
- tty->flags &= ~TTY_FOCUS;
- tty_raw(tty, "\033[?1004l");
- }
+ if (tty->flags & TTY_FOCUS) {
+ tty->flags &= ~TTY_FOCUS;
+ tty_raw(tty, tty_term_string(tty->term, TTYC_DSFCS));
}
+ if (tty->term->flags & TERM_VT100LIKE)
+ tty_raw(tty, "\033[?7727l");
if (tty_use_margin(tty))
- tty_raw(tty, "\033[?69l"); /* DECLRMM */
+ tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
setblocking(tty->fd, 1);
@@ -454,18 +455,19 @@ void
tty_free(struct tty *tty)
{
tty_close(tty);
-
free(tty->ccolour);
- free(tty->term_name);
}
void
-tty_set_flags(struct tty *tty, int flags)
+tty_update_features(struct tty *tty)
{
- tty->term_flags |= flags;
+ struct client *c = tty->client;
+
+ if (tty_apply_features(tty->term, c->term_features))
+ tty_term_apply_overrides(tty->term);
if (tty_use_margin(tty))
- tty_puts(tty, "\033[?69h"); /* DECLRMM */
+ tty_putcode(tty, TTYC_ENMG);
}
void
@@ -658,7 +660,8 @@ tty_force_cursor_colour(struct tty *tty, const char *ccolour)
void
tty_update_mode(struct tty *tty, int mode, struct screen *s)
{
- int changed;
+ struct client *c = tty->client;
+ int changed;
if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0)
tty_force_cursor_colour(tty, s->ccolour);
@@ -667,6 +670,9 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
mode &= ~MODE_CURSOR;
changed = mode ^ tty->mode;
+ if (changed != 0)
+ log_debug("%s: update mode %x to %x", c->name, tty->mode, mode);
+
if (changed & MODE_BLINKING) {
if (tty_term_has(tty->term, TTYC_CVVIS))
tty_putcode(tty, TTYC_CVVIS);
@@ -690,34 +696,37 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
}
tty->cstyle = s->cstyle;
}
- if (changed & ALL_MOUSE_MODES) {
- if (mode & ALL_MOUSE_MODES) {
- /*
- * Enable the SGR (1006) extension unconditionally, as
- * it is safe from misinterpretation.
- */
- tty_puts(tty, "\033[?1006h");
- if (mode & MODE_MOUSE_ALL)
- tty_puts(tty, "\033[?1003h");
- else if (mode & MODE_MOUSE_BUTTON)
- tty_puts(tty, "\033[?1002h");
- else if (mode & MODE_MOUSE_STANDARD)
- tty_puts(tty, "\033[?1000h");
- } else {
- if (tty->mode & MODE_MOUSE_ALL)
- tty_puts(tty, "\033[?1003l");
- else if (tty->mode & MODE_MOUSE_BUTTON)
- tty_puts(tty, "\033[?1002l");
- else if (tty->mode & MODE_MOUSE_STANDARD)
- tty_puts(tty, "\033[?1000l");
+ if ((changed & ALL_MOUSE_MODES) &&
+ tty_term_has(tty->term, TTYC_KMOUS)) {
+ if ((mode & ALL_MOUSE_MODES) == 0)
tty_puts(tty, "\033[?1006l");
- }
+ if ((changed & MODE_MOUSE_STANDARD) &&
+ (~mode & MODE_MOUSE_STANDARD))
+ tty_puts(tty, "\033[?1000l");
+ if ((changed & MODE_MOUSE_BUTTON) &&
+ (~mode & MODE_MOUSE_BUTTON))
+ tty_puts(tty, "\033[?1002l");
+ if ((changed & MODE_MOUSE_ALL) &&
+ (~mode & MODE_MOUSE_ALL))
+ tty_puts(tty, "\033[?1003l");
+
+ if (mode & ALL_MOUSE_MODES)
+ tty_puts(tty, "\033[?1006h");
+ if ((changed & MODE_MOUSE_STANDARD) &&
+ (mode & MODE_MOUSE_STANDARD))
+ tty_puts(tty, "\033[?1000h");
+ if ((changed & MODE_MOUSE_BUTTON) &&
+ (mode & MODE_MOUSE_BUTTON))
+ tty_puts(tty, "\033[?1002h");
+ if ((changed & MODE_MOUSE_ALL) &&
+ (mode & MODE_MOUSE_ALL))
+ tty_puts(tty, "\033[?1003h");
}
if (changed & MODE_BRACKETPASTE) {
if (mode & MODE_BRACKETPASTE)
- tty_puts(tty, "\033[?2004h");
+ tty_putcode(tty, TTYC_ENBP);
else
- tty_puts(tty, "\033[?2004l");
+ tty_putcode(tty, TTYC_DSBP);
}
tty->mode = mode;
}
@@ -876,6 +885,27 @@ tty_update_client_offset(struct client *c)
c->flags |= (CLIENT_REDRAWWINDOW|CLIENT_REDRAWSTATUS);
}
+/* Get a palette entry. */
+static int
+tty_get_palette(int *palette, int c)
+{
+ int new;
+
+ if (palette == NULL)
+ return (-1);
+
+ new = -1;
+ if (c < 8)
+ new = palette[c];
+ else if (c >= 90 && c <= 97)
+ new = palette[8 + c - 90];
+ else if (c & COLOUR_FLAG_256)
+ new = palette[c & ~COLOUR_FLAG_256];
+ if (new == 0)
+ return (-1);
+ return (new);
+}
+
/*
* Is the region large enough to be worth redrawing once later rather than
* probably several times now? Currently yes if it is more than 50% of the
@@ -884,9 +914,7 @@ tty_update_client_offset(struct client *c)
static int
tty_large_region(__unused struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
- return (ctx->orlower - ctx->orupper >= screen_size_y(wp->screen) / 2);
+ return (ctx->orlower - ctx->orupper >= ctx->sy / 2);
}
/*
@@ -894,18 +922,11 @@ tty_large_region(__unused struct tty *tty, const struct tty_ctx *ctx)
* emulated.
*/
static int
-tty_fake_bce(const struct tty *tty, struct window_pane *wp, u_int bg)
+tty_fake_bce(const struct tty *tty, const struct grid_cell *gc, u_int bg)
{
- struct grid_cell gc;
-
if (tty_term_flag(tty->term, TTYC_BCE))
return (0);
-
- memcpy(&gc, &grid_default_cell, sizeof gc);
- if (wp != NULL)
- tty_default_colours(&gc, wp);
-
- if (!COLOUR_DEFAULT(bg) || !COLOUR_DEFAULT(gc.bg))
+ if (!COLOUR_DEFAULT(bg) || !COLOUR_DEFAULT(gc->bg))
return (1);
return (0);
}
@@ -918,21 +939,21 @@ tty_fake_bce(const struct tty *tty, struct window_pane *wp, u_int bg)
static void
tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
+ struct client *c = tty->client;
u_int i;
/*
- * If region is large, schedule a window redraw. In most cases this is
- * likely to be followed by some more scrolling.
+ * If region is large, schedule a redraw. In most cases this is likely
+ * to be followed by some more scrolling.
*/
if (tty_large_region(tty, ctx)) {
- wp->flags |= PANE_REDRAW;
+ log_debug("%s: %s large redraw", __func__, c->name);
+ ctx->redraw_cb(ctx);
return;
}
if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
- for (i = ctx->ocy; i < screen_size_y(s); i++)
+ for (i = ctx->ocy; i < ctx->sy; i++)
tty_draw_pane(tty, ctx, i);
} else {
for (i = ctx->orupper; i <= ctx->orlower; i++)
@@ -942,21 +963,16 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
/* Is this position visible in the pane? */
static int
-tty_is_visible(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
- u_int nx, u_int ny)
+tty_is_visible(__unused struct tty *tty, const struct tty_ctx *ctx, u_int px,
+ u_int py, u_int nx, u_int ny)
{
- u_int xoff = ctx->xoff + px, yoff = ctx->yoff + py, lines;
+ u_int xoff = ctx->rxoff + px, yoff = ctx->ryoff + py;
if (!ctx->bigger)
return (1);
- if (status_at_line(tty->client) == 0)
- lines = status_line_size(tty->client);
- else
- lines = 0;
-
- if (xoff + nx <= ctx->ox || xoff >= ctx->ox + ctx->sx ||
- yoff + ny <= ctx->oy || yoff >= lines + ctx->oy + ctx->sy)
+ if (xoff + nx <= ctx->wox || xoff >= ctx->wox + ctx->wsx ||
+ yoff + ny <= ctx->woy || yoff >= ctx->woy + ctx->wsy)
return (0);
return (1);
}
@@ -966,33 +982,32 @@ static int
tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry)
{
- struct window_pane *wp = ctx->wp;
- u_int xoff = wp->xoff + px;
+ u_int xoff = ctx->rxoff + px;
if (!tty_is_visible(tty, ctx, px, py, nx, 1))
return (0);
- *ry = ctx->yoff + py - ctx->oy;
+ *ry = ctx->yoff + py - ctx->woy;
- if (xoff >= ctx->ox && xoff + nx <= ctx->ox + ctx->sx) {
+ if (xoff >= ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
/* All visible. */
*i = 0;
- *x = ctx->xoff + px - ctx->ox;
+ *x = ctx->xoff + px - ctx->wox;
*rx = nx;
- } else if (xoff < ctx->ox && xoff + nx > ctx->ox + ctx->sx) {
+ } else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
/* Both left and right not visible. */
- *i = ctx->ox;
+ *i = ctx->wox;
*x = 0;
- *rx = ctx->sx;
- } else if (xoff < ctx->ox) {
+ *rx = ctx->wsx;
+ } else if (xoff < ctx->wox) {
/* Left not visible. */
- *i = ctx->ox - (ctx->xoff + px);
+ *i = ctx->wox - (ctx->xoff + px);
*x = 0;
*rx = nx - *i;
} else {
/* Right not visible. */
*i = 0;
- *x = (ctx->xoff + px) - ctx->ox;
- *rx = ctx->sx - *x;
+ *x = (ctx->xoff + px) - ctx->wox;
+ *rx = ctx->wsx - *x;
}
if (*rx > nx)
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
@@ -1002,8 +1017,8 @@ tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
/* Clear a line. */
static void
-tty_clear_line(struct tty *tty, struct window_pane *wp, u_int py, u_int px,
- u_int nx, u_int bg)
+tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
+ u_int px, u_int nx, u_int bg)
{
struct client *c = tty->client;
@@ -1014,7 +1029,7 @@ tty_clear_line(struct tty *tty, struct window_pane *wp, u_int py, u_int px,
return;
/* If genuine BCE is available, can try escape sequences. */
- if (!tty_fake_bce(tty, wp, bg)) {
+ if (!tty_fake_bce(tty, defaults, bg)) {
/* Off the end of the line, use EL if available. */
if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) {
tty_cursor(tty, px, py);
@@ -1053,7 +1068,7 @@ tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
if (tty_clamp_line(tty, ctx, px, py, nx, &i, &x, &rx, &ry))
- tty_clear_line(tty, ctx->wp, ry, x, rx, bg);
+ tty_clear_line(tty, &ctx->defaults, ry, x, rx, bg);
}
/* Clamp area position to visible part of pane. */
@@ -1062,56 +1077,55 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
u_int nx, u_int ny, u_int *i, u_int *j, u_int *x, u_int *y, u_int *rx,
u_int *ry)
{
- struct window_pane *wp = ctx->wp;
- u_int xoff = wp->xoff + px, yoff = wp->yoff + py;
+ u_int xoff = ctx->rxoff + px, yoff = ctx->ryoff + py;
if (!tty_is_visible(tty, ctx, px, py, nx, ny))
return (0);
- if (xoff >= ctx->ox && xoff + nx <= ctx->ox + ctx->sx) {
+ if (xoff >= ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
/* All visible. */
*i = 0;
- *x = ctx->xoff + px - ctx->ox;
+ *x = ctx->xoff + px - ctx->wox;
*rx = nx;
- } else if (xoff < ctx->ox && xoff + nx > ctx->ox + ctx->sx) {
+ } else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
/* Both left and right not visible. */
- *i = ctx->ox;
+ *i = ctx->wox;
*x = 0;
- *rx = ctx->sx;
- } else if (xoff < ctx->ox) {
+ *rx = ctx->wsx;
+ } else if (xoff < ctx->wox) {
/* Left not visible. */
- *i = ctx->ox - (ctx->xoff + px);
+ *i = ctx->wox - (ctx->xoff + px);
*x = 0;
*rx = nx - *i;
} else {
/* Right not visible. */
*i = 0;
- *x = (ctx->xoff + px) - ctx->ox;
- *rx = ctx->sx - *x;
+ *x = (ctx->xoff + px) - ctx->wox;
+ *rx = ctx->wsx - *x;
}
if (*rx > nx)
fatalx("%s: x too big, %u > %u", __func__, *rx, nx);
- if (yoff >= ctx->oy && yoff + ny <= ctx->oy + ctx->sy) {
+ if (yoff >= ctx->woy && yoff + ny <= ctx->woy + ctx->wsy) {
/* All visible. */
*j = 0;
- *y = ctx->yoff + py - ctx->oy;
+ *y = ctx->yoff + py - ctx->woy;
*ry = ny;
- } else if (yoff < ctx->oy && yoff + ny > ctx->oy + ctx->sy) {
+ } else if (yoff < ctx->woy && yoff + ny > ctx->woy + ctx->wsy) {
/* Both top and bottom not visible. */
- *j = ctx->oy;
+ *j = ctx->woy;
*y = 0;
- *ry = ctx->sy;
- } else if (yoff < ctx->oy) {
+ *ry = ctx->wsy;
+ } else if (yoff < ctx->woy) {
/* Top not visible. */
- *j = ctx->oy - (ctx->yoff + py);
+ *j = ctx->woy - (ctx->yoff + py);
*y = 0;
*ry = ny - *j;
} else {
/* Bottom not visible. */
*j = 0;
- *y = (ctx->yoff + py) - ctx->oy;
- *ry = ctx->sy - *y;
+ *y = (ctx->yoff + py) - ctx->woy;
+ *ry = ctx->wsy - *y;
}
if (*ry > ny)
fatalx("%s: y too big, %u > %u", __func__, *ry, ny);
@@ -1121,8 +1135,8 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
/* Clear an area, adjusting to visible part of pane. */
static void
-tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
- u_int px, u_int nx, u_int bg)
+tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
+ u_int ny, u_int px, u_int nx, u_int bg)
{
struct client *c = tty->client;
u_int yy;
@@ -1135,7 +1149,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
return;
/* If genuine BCE is available, can try escape sequences. */
- if (!tty_fake_bce(tty, wp, bg)) {
+ if (!tty_fake_bce(tty, defaults, bg)) {
/* Use ED if clearing off the bottom of the terminal. */
if (px == 0 &&
px + nx >= tty->sx &&
@@ -1151,8 +1165,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
* background colour isn't default (because it doesn't work
* after SGR 0).
*/
- if (((tty->term->flags|tty->term_flags) & TERM_DECFRA) &&
- !COLOUR_DEFAULT(bg)) {
+ if ((tty->term->flags & TERM_DECFRA) && !COLOUR_DEFAULT(bg)) {
xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x",
py + 1, px + 1, py + ny, px + nx);
tty_puts(tty, tmp);
@@ -1189,7 +1202,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny,
/* Couldn't use an escape sequence, loop over the lines. */
for (yy = py; yy < py + ny; yy++)
- tty_clear_line(tty, wp, yy, px, nx, bg);
+ tty_clear_line(tty, defaults, yy, px, nx, bg);
}
/* Clear an area in a pane. */
@@ -1200,24 +1213,26 @@ tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
u_int i, j, x, y, rx, ry;
if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry))
- tty_clear_area(tty, ctx->wp, y, ry, x, rx, bg);
+ tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg);
}
static void
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
{
- struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int nx = screen_size_x(s), i, x, rx, ry;
+ struct screen *s = ctx->s;
+ u_int nx = ctx->sx, i, x, rx, ry;
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
if (!ctx->bigger) {
- tty_draw_line(tty, wp, s, 0, py, nx, ctx->xoff, ctx->yoff + py);
+ tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py,
+ &ctx->defaults, ctx->palette);
return;
}
- if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry))
- tty_draw_line(tty, wp, s, i, py, rx, x, ry);
+ if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) {
+ tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults,
+ ctx->palette);
+ }
}
static const struct grid_cell *
@@ -1231,7 +1246,7 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
return (gc);
/* UTF-8 terminal and a UTF-8 character - fine. */
- if (tty->flags & TTY_UTF8)
+ if (tty->client->flags & CLIENT_UTF8)
return (gc);
/* Replace by the right number of underscores. */
@@ -1244,9 +1259,19 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
return (&new);
}
+static int
+tty_check_overlay(struct tty *tty, u_int px, u_int py)
+{
+ struct client *c = tty->client;
+
+ if (c->overlay_check == NULL)
+ return (1);
+ return (c->overlay_check(c, px, py));
+}
+
void
-tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
- u_int px, u_int py, u_int nx, u_int atx, u_int aty)
+tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
+ u_int atx, u_int aty, const struct grid_cell *defaults, int *palette)
{
struct grid *gd = s->grid;
struct grid_cell gc, last;
@@ -1294,8 +1319,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
gl = NULL;
else
gl = grid_get_line(gd, gd->hsize + py - 1);
- if (wp == NULL ||
- gl == NULL ||
+ if (gl == NULL ||
(~gl->flags & GRID_LINE_WRAPPED) ||
atx != 0 ||
tty->cx < tty->sx ||
@@ -1304,8 +1328,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
atx == 0 &&
px + sx != nx &&
tty_term_has(tty->term, TTYC_EL1) &&
- !tty_fake_bce(tty, wp, 8)) {
- tty_default_attributes(tty, wp, 8);
+ !tty_fake_bce(tty, defaults, 8)) {
+ tty_default_attributes(tty, defaults, palette, 8);
tty_cursor(tty, nx - 1, aty);
tty_putcode(tty, TTYC_EL1);
cleared = 1;
@@ -1323,7 +1347,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
grid_view_get_cell(gd, px + i, py, &gc);
gcp = tty_check_codeset(tty, &gc);
if (len != 0 &&
- ((gcp->attr & GRID_ATTR_CHARSET) ||
+ (!tty_check_overlay(tty, atx + ux + width, aty) ||
+ (gcp->attr & GRID_ATTR_CHARSET) ||
gcp->flags != last.flags ||
gcp->attr != last.attr ||
gcp->fg != last.fg ||
@@ -1331,11 +1356,11 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
gcp->us != last.us ||
ux + width + gcp->data.width > nx ||
(sizeof buf) - len < gcp->data.size)) {
- tty_attributes(tty, &last, wp);
+ tty_attributes(tty, &last, defaults, palette);
if (last.flags & GRID_FLAG_CLEARED) {
log_debug("%s: %zu cleared", __func__, len);
- tty_clear_line(tty, wp, aty, atx + ux, width,
- last.bg);
+ tty_clear_line(tty, defaults, aty, atx + ux,
+ width, last.bg);
} else {
if (!wrapped || atx != 0 || ux != 0)
tty_cursor(tty, atx + ux, aty);
@@ -1352,8 +1377,10 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
screen_select_cell(s, &last, gcp);
else
memcpy(&last, gcp, sizeof last);
- if (ux + gcp->data.width > nx) {
- tty_attributes(tty, &last, wp);
+ if (!tty_check_overlay(tty, atx + ux, aty))
+ ux += gcp->data.width;
+ else if (ux + gcp->data.width > nx) {
+ tty_attributes(tty, &last, defaults, palette);
tty_cursor(tty, atx + ux, aty);
for (j = 0; j < gcp->data.width; j++) {
if (ux + j > nx)
@@ -1362,11 +1389,11 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
ux++;
}
} else if (gcp->attr & GRID_ATTR_CHARSET) {
- tty_attributes(tty, &last, wp);
+ tty_attributes(tty, &last, defaults, palette);
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;
+ ux += gcp->data.width;
} else {
memcpy(buf + len, gcp->data.data, gcp->data.size);
len += gcp->data.size;
@@ -1374,10 +1401,11 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
}
}
if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) {
- tty_attributes(tty, &last, wp);
+ tty_attributes(tty, &last, defaults, palette);
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);
+ tty_clear_line(tty, defaults, aty, atx + ux, width,
+ last.bg);
} else {
if (!wrapped || atx != 0 || ux != 0)
tty_cursor(tty, atx + ux, aty);
@@ -1389,16 +1417,46 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
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);
+ tty_default_attributes(tty, defaults, palette, 8);
+ tty_clear_line(tty, defaults, aty, atx + ux, nx - ux, 8);
}
tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags;
tty_update_mode(tty, tty->mode, s);
}
+void
+tty_sync_start(struct tty *tty)
+{
+ if (tty->flags & TTY_BLOCK)
+ return;
+ if (tty->flags & TTY_SYNCING)
+ return;
+ tty->flags |= TTY_SYNCING;
+
+ if (tty_term_has(tty->term, TTYC_SYNC)) {
+ log_debug("%s sync start", tty->client->name);
+ tty_putcode1(tty, TTYC_SYNC, 1);
+ }
+}
+
+void
+tty_sync_end(struct tty *tty)
+{
+ if (tty->flags & TTY_BLOCK)
+ return;
+ if (~tty->flags & TTY_SYNCING)
+ return;
+ tty->flags &= ~TTY_SYNCING;
+
+ if (tty_term_has(tty->term, TTYC_SYNC)) {
+ log_debug("%s sync end", tty->client->name);
+ tty_putcode1(tty, TTYC_SYNC, 2);
+ }
+}
+
static int
-tty_client_ready(struct client *c, struct window_pane *wp)
+tty_client_ready(struct client *c)
{
if (c->session == NULL || c->tty.term == NULL)
return (0);
@@ -1406,10 +1464,6 @@ tty_client_ready(struct client *c, struct window_pane *wp)
return (0);
if (c->tty.flags & TTY_FREEZE)
return (0);
- if (c->session->curw->window != wp->window)
- return (0);
- if (wp->layout_cell == NULL)
- return (0);
return (1);
}
@@ -1417,27 +1471,19 @@ void
tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- struct client *c;
+ struct client *c;
+ int state;
- if (wp == NULL)
+ if (ctx->set_client_cb == NULL)
return;
- if (wp->flags & (PANE_REDRAW|PANE_DROP))
- return;
-
TAILQ_FOREACH(c, &clients, entry) {
- if (!tty_client_ready(c, wp))
+ if (!tty_client_ready(c))
+ continue;
+ state = ctx->set_client_cb(ctx, c);
+ if (state == -1)
+ break;
+ if (state == 0)
continue;
-
- ctx->bigger = tty_window_offset(&c->tty, &ctx->ox, &ctx->oy,
- &ctx->sx, &ctx->sy);
-
- ctx->xoff = wp->xoff;
- ctx->yoff = wp->yoff;
-
- if (status_at_line(c) == 0)
- ctx->yoff += status_line_size(c);
-
cmdfn(&c->tty, ctx);
}
}
@@ -1445,18 +1491,16 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
void
tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
if (ctx->bigger ||
- !tty_pane_full_width(tty, ctx) ||
- tty_fake_bce(tty, wp, ctx->bg) ||
+ !tty_full_width(tty, ctx) ||
+ tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_ICH) &&
!tty_term_has(tty->term, TTYC_ICH1))) {
tty_draw_pane(tty, ctx, ctx->ocy);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -1466,18 +1510,16 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
if (ctx->bigger ||
- !tty_pane_full_width(tty, ctx) ||
- tty_fake_bce(tty, wp, ctx->bg) ||
+ !tty_full_width(tty, ctx) ||
+ tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_DCH) &&
!tty_term_has(tty->term, TTYC_DCH1))) {
tty_draw_pane(tty, ctx, ctx->ocy);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -1492,12 +1534,12 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
return;
}
- tty_default_attributes(tty, ctx->wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
if (tty_term_has(tty->term, TTYC_ECH) &&
- !tty_fake_bce(tty, ctx->wp, 8))
+ !tty_fake_bce(tty, &ctx->defaults, 8))
tty_putcode1(tty, TTYC_ECH, ctx->num);
else
tty_repeat_space(tty, ctx->num);
@@ -1507,17 +1549,17 @@ void
tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
{
if (ctx->bigger ||
- !tty_pane_full_width(tty, ctx) ||
- tty_fake_bce(tty, ctx->wp, ctx->bg) ||
+ !tty_full_width(tty, ctx) ||
+ tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_IL1) ||
- ctx->wp->sx == 1 ||
- ctx->wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, ctx->wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty);
@@ -1531,17 +1573,17 @@ void
tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
{
if (ctx->bigger ||
- !tty_pane_full_width(tty, ctx) ||
- tty_fake_bce(tty, ctx->wp, ctx->bg) ||
+ !tty_full_width(tty, ctx) ||
+ tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_DL1) ||
- ctx->wp->sx == 1 ||
- ctx->wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, ctx->wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty);
@@ -1554,33 +1596,25 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int nx;
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
- tty_default_attributes(tty, wp, ctx->bg);
-
- nx = screen_size_x(wp->screen);
- tty_clear_pane_line(tty, ctx, ctx->ocy, 0, nx, ctx->bg);
+ tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->sx, ctx->bg);
}
void
tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int nx;
+ u_int nx = ctx->sx - ctx->ocx;
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
- nx = screen_size_x(wp->screen) - ctx->ocx;
tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, nx, ctx->bg);
}
void
tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->ocx + 1, ctx->bg);
}
@@ -1588,24 +1622,22 @@ tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
if (ctx->ocy != ctx->orupper)
return;
if (ctx->bigger ||
- (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
- tty_fake_bce(tty, wp, 8) ||
+ (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
(!tty_term_has(tty->term, TTYC_RI) &&
!tty_term_has(tty->term, TTYC_RIN)) ||
- ctx->wp->sx == 1 ||
- ctx->wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
@@ -1620,22 +1652,20 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
if (ctx->ocy != ctx->orlower)
return;
if (ctx->bigger ||
- (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
- tty_fake_bce(tty, wp, 8) ||
+ (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
- wp->sx == 1 ||
- wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
@@ -1661,20 +1691,19 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int i;
+ u_int i;
if (ctx->bigger ||
- (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
- tty_fake_bce(tty, wp, 8) ||
+ (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
- wp->sx == 1 ||
- wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
@@ -1687,7 +1716,10 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
for (i = 0; i < ctx->num; i++)
tty_putc(tty, '\n');
} else {
- tty_cursor(tty, 0, tty->cy);
+ if (tty->cy == UINT_MAX)
+ tty_cursor(tty, 0, 0);
+ else
+ tty_cursor(tty, 0, tty->cy);
tty_putcode1(tty, TTYC_INDN, ctx->num);
}
}
@@ -1695,22 +1727,21 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int i;
+ u_int i;
if (ctx->bigger ||
- (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
- tty_fake_bce(tty, wp, 8) ||
+ (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
(!tty_term_has(tty->term, TTYC_RI) &&
!tty_term_has(tty->term, TTYC_RIN)) ||
- wp->sx == 1 ||
- wp->sy == 1) {
+ ctx->sx == 1 ||
+ ctx->sy == 1) {
tty_redraw_region(tty, ctx);
return;
}
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
@@ -1727,23 +1758,22 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int px, py, nx, ny;
+ u_int px, py, nx, ny;
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
- tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
+ tty_region_pane(tty, ctx, 0, ctx->sy - 1);
tty_margin_off(tty);
px = 0;
- nx = screen_size_x(wp->screen);
+ nx = ctx->sx;
py = ctx->ocy + 1;
- ny = screen_size_y(wp->screen) - ctx->ocy - 1;
+ ny = ctx->sy - ctx->ocy - 1;
tty_clear_pane_area(tty, ctx, py, ny, px, nx, ctx->bg);
px = ctx->ocx;
- nx = screen_size_x(wp->screen) - ctx->ocx;
+ nx = ctx->sx - ctx->ocx;
py = ctx->ocy;
tty_clear_pane_line(tty, ctx, py, px, nx, ctx->bg);
@@ -1752,16 +1782,15 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int px, py, nx, ny;
+ u_int px, py, nx, ny;
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
- tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
+ tty_region_pane(tty, ctx, 0, ctx->sy - 1);
tty_margin_off(tty);
px = 0;
- nx = screen_size_x(wp->screen);
+ nx = ctx->sx;
py = 0;
ny = ctx->ocy;
@@ -1777,18 +1806,17 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- u_int px, py, nx, ny;
+ u_int px, py, nx, ny;
- tty_default_attributes(tty, wp, ctx->bg);
+ tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg);
- tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
+ tty_region_pane(tty, ctx, 0, ctx->sy - 1);
tty_margin_off(tty);
px = 0;
- nx = screen_size_x(wp->screen);
+ nx = ctx->sx;
py = 0;
- ny = screen_size_y(wp->screen);
+ ny = ctx->sy;
tty_clear_pane_area(tty, ctx, py, ny, px, nx, ctx->bg);
}
@@ -1796,23 +1824,21 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int i, j;
+ u_int i, j;
if (ctx->bigger) {
- wp->flags |= PANE_REDRAW;
+ ctx->redraw_cb(ctx);
return;
}
- tty_attributes(tty, &grid_default_cell, wp);
+ tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette);
- tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
+ tty_region_pane(tty, ctx, 0, ctx->sy - 1);
tty_margin_off(tty);
- for (j = 0; j < screen_size_y(s); j++) {
+ for (j = 0; j < ctx->sy; j++) {
tty_cursor_pane(tty, ctx, 0, j);
- for (i = 0; i < screen_size_x(s); i++)
+ for (i = 0; i < ctx->sx; i++)
tty_putc(tty, 'E');
}
}
@@ -1823,30 +1849,28 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, 1, 1))
return;
- if (ctx->xoff + ctx->ocx - ctx->ox > tty->sx - 1 &&
+ if (ctx->xoff + ctx->ocx - ctx->wox > tty->sx - 1 &&
ctx->ocy == ctx->orlower &&
- tty_pane_full_width(tty, ctx))
+ tty_full_width(tty, ctx))
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty);
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
- tty_cell(tty, ctx->cell, ctx->wp);
+ tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette);
}
void
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
{
- struct window_pane *wp = ctx->wp;
-
if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1))
return;
if (ctx->bigger &&
- (ctx->xoff + ctx->ocx < ctx->ox ||
- ctx->xoff + ctx->ocx + ctx->num > ctx->ox + ctx->sx)) {
+ (ctx->xoff + ctx->ocx < ctx->wox ||
+ ctx->xoff + ctx->ocx + ctx->num > ctx->wox + ctx->wsx)) {
if (!ctx->wrapped ||
- !tty_pane_full_width(tty, ctx) ||
+ !tty_full_width(tty, ctx) ||
(tty->term->flags & TERM_NOXENL) ||
ctx->xoff + ctx->ocx != 0 ||
ctx->yoff + ctx->ocy != tty->cy + 1 ||
@@ -1854,14 +1878,14 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
tty->cy == tty->rlower)
tty_draw_pane(tty, ctx, ctx->ocy);
else
- wp->flags |= PANE_REDRAW;
+ ctx->redraw_cb(ctx);
return;
}
tty_margin_off(tty);
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
- tty_attributes(tty, ctx->cell, ctx->wp);
+ tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette);
tty_putn(tty, ctx->ptr, ctx->num, ctx->num);
}
@@ -1890,8 +1914,15 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
tty_invalidate(tty);
}
+void
+tty_cmd_syncstart(struct tty *tty, __unused const struct tty_ctx *ctx)
+{
+ tty_sync_start(tty);
+}
+
static void
-tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp)
+tty_cell(struct tty *tty, const struct grid_cell *gc,
+ const struct grid_cell *defaults, int *palette)
{
const struct grid_cell *gcp;
@@ -1906,7 +1937,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp)
return;
/* Set the attributes. */
- tty_attributes(tty, gc, wp);
+ tty_attributes(tty, gc, defaults, palette);
/* Get the cell and if ASCII write with putc to do ACS translation. */
gcp = tty_check_codeset(tty, gc);
@@ -1932,27 +1963,22 @@ tty_reset(struct tty *tty)
tty_putcode(tty, TTYC_SGR0);
memcpy(gc, &grid_default_cell, sizeof *gc);
}
-
memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell);
- tty->last_wp = -1;
}
static void
tty_invalidate(struct tty *tty)
{
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
-
memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell);
- tty->last_wp = -1;
tty->cx = tty->cy = UINT_MAX;
-
tty->rupper = tty->rleft = UINT_MAX;
tty->rlower = tty->rright = UINT_MAX;
if (tty->flags & TTY_STARTED) {
if (tty_use_margin(tty))
- tty_puts(tty, "\033[?69h"); /* DECLRMM */
+ tty_putcode(tty, TTYC_ENMG);
tty_putcode(tty, TTYC_SGR0);
tty->mode = ALL_MODES;
@@ -1977,8 +2003,8 @@ static void
tty_region_pane(struct tty *tty, const struct tty_ctx *ctx, u_int rupper,
u_int rlower)
{
- tty_region(tty, ctx->yoff + rupper - ctx->oy,
- ctx->yoff + rlower - ctx->oy);
+ tty_region(tty, ctx->yoff + rupper - ctx->woy,
+ ctx->yoff + rlower - ctx->woy);
}
/* Set region at absolute position. */
@@ -1999,8 +2025,12 @@ tty_region(struct tty *tty, u_int rupper, u_int rlower)
* flag so further output causes a line feed). As a workaround, do an
* explicit move to 0 first.
*/
- if (tty->cx >= tty->sx)
- tty_cursor(tty, 0, tty->cy);
+ if (tty->cx >= tty->sx) {
+ if (tty->cy == UINT_MAX)
+ tty_cursor(tty, 0, 0);
+ else
+ tty_cursor(tty, 0, tty->cy);
+ }
tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower);
tty->cx = tty->cy = UINT_MAX;
@@ -2017,16 +2047,14 @@ tty_margin_off(struct tty *tty)
static void
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
{
- tty_margin(tty, ctx->xoff - ctx->ox,
- ctx->xoff + ctx->wp->sx - 1 - ctx->ox);
+ tty_margin(tty, ctx->xoff - ctx->wox,
+ ctx->xoff + ctx->sx - 1 - ctx->wox);
}
/* Set margin at absolute position. */
static void
tty_margin(struct tty *tty, u_int rleft, u_int rright)
{
- char s[64];
-
if (!tty_use_margin(tty))
return;
if (tty->rleft == rleft && tty->rright == rright)
@@ -2038,10 +2066,9 @@ tty_margin(struct tty *tty, u_int rleft, u_int rright)
tty->rright = rright;
if (rleft == 0 && rright == tty->sx - 1)
- snprintf(s, sizeof s, "\033[s");
+ tty_putcode(tty, TTYC_CLMG);
else
- snprintf(s, sizeof s, "\033[%u;%us", rleft + 1, rright + 1);
- tty_puts(tty, s);
+ tty_putcode2(tty, TTYC_CMG, rleft, rright);
tty->cx = tty->cy = UINT_MAX;
}
@@ -2054,7 +2081,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
u_int cx, u_int cy)
{
if (!ctx->wrapped ||
- !tty_pane_full_width(tty, ctx) ||
+ !tty_full_width(tty, ctx) ||
(tty->term->flags & TERM_NOXENL) ||
ctx->xoff + cx != 0 ||
ctx->yoff + cy != tty->cy + 1 ||
@@ -2069,7 +2096,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
static void
tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy)
{
- tty_cursor(tty, ctx->xoff + cx - ctx->ox, ctx->yoff + cy - ctx->oy);
+ tty_cursor(tty, ctx->xoff + cx - ctx->wox, ctx->yoff + cy - ctx->woy);
}
/* Move cursor to absolute position. */
@@ -2080,6 +2107,9 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
u_int thisx, thisy;
int change;
+ if (tty->flags & TTY_BLOCK)
+ return;
+
if (cx > tty->sx - 1)
cx = tty->sx - 1;
@@ -2211,27 +2241,24 @@ out:
void
tty_attributes(struct tty *tty, const struct grid_cell *gc,
- struct window_pane *wp)
+ const struct grid_cell *defaults, int *palette)
{
struct grid_cell *tc = &tty->cell, gc2;
int changed;
- /* Ignore cell if it is the same as the last one. */
- if (wp != NULL &&
- (int)wp->id == tty->last_wp &&
- ~(wp->flags & PANE_STYLECHANGED) &&
- gc->attr == tty->last_cell.attr &&
- gc->fg == tty->last_cell.fg &&
- 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);
-
/* Copy cell and update default colours. */
memcpy(&gc2, gc, sizeof gc2);
- if (wp != NULL)
- tty_default_colours(&gc2, wp);
+ if (gc2.fg == 8)
+ gc2.fg = defaults->fg;
+ if (gc2.bg == 8)
+ gc2.bg = defaults->bg;
+
+ /* Ignore cell if it is the same as the last one. */
+ if (gc2.attr == tty->last_cell.attr &&
+ gc2.fg == tty->last_cell.fg &&
+ gc2.bg == tty->last_cell.bg &&
+ gc2.us == tty->last_cell.us)
+ return;
/*
* If no setab, try to use the reverse attribute as a best-effort for a
@@ -2249,9 +2276,9 @@ 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);
+ tty_check_fg(tty, palette, &gc2);
+ tty_check_bg(tty, palette, &gc2);
+ tty_check_us(tty, palette, &gc2);
/*
* If any bits are being cleared or the underline colour is now default,
@@ -2306,6 +2333,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
tty_putcode(tty, TTYC_SMOL);
if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
tty_putcode(tty, TTYC_SMACS);
+
+ memcpy(&tty->last_cell, &gc2, sizeof tty->last_cell);
}
static void
@@ -2370,7 +2399,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
}
static void
-tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
+tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc)
{
u_char r, g, b;
u_int colours;
@@ -2385,21 +2414,21 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
c = gc->fg;
if (c < 8 && gc->attr & GRID_ATTR_BRIGHT)
c += 90;
- if ((c = window_pane_get_palette(wp, c)) != -1)
+ if ((c = tty_get_palette(palette, c)) != -1)
gc->fg = c;
}
/* Is this a 24-bit colour? */
if (gc->fg & COLOUR_FLAG_RGB) {
/* Not a 24-bit terminal? Translate to 256-colour palette. */
- if ((tty->term->flags|tty->term_flags) & TERM_RGBCOLOURS)
+ if (tty->term->flags & TERM_RGBCOLOURS)
return;
colour_split_rgb(gc->fg, &r, &g, &b);
gc->fg = colour_find_rgb(r, g, b);
}
/* How many colours does this terminal have? */
- if ((tty->term->flags|tty->term_flags) & TERM_256COLOURS)
+ if (tty->term->flags & TERM_256COLOURS)
colours = 256;
else
colours = tty_term_number(tty->term, TTYC_COLORS);
@@ -2426,7 +2455,7 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
}
static void
-tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
+tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc)
{
u_char r, g, b;
u_int colours;
@@ -2434,21 +2463,21 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
/* Perform substitution if this pane has a palette. */
if (~gc->flags & GRID_FLAG_NOPALETTE) {
- if ((c = window_pane_get_palette(wp, gc->bg)) != -1)
+ if ((c = tty_get_palette(palette, gc->bg)) != -1)
gc->bg = c;
}
/* Is this a 24-bit colour? */
if (gc->bg & COLOUR_FLAG_RGB) {
/* Not a 24-bit terminal? Translate to 256-colour palette. */
- if ((tty->term->flags|tty->term_flags) & TERM_RGBCOLOURS)
+ if (tty->term->flags & TERM_RGBCOLOURS)
return;
colour_split_rgb(gc->bg, &r, &g, &b);
gc->bg = colour_find_rgb(r, g, b);
}
/* How many colours does this terminal have? */
- if ((tty->term->flags|tty->term_flags) & TERM_256COLOURS)
+ if (tty->term->flags & TERM_256COLOURS)
colours = 256;
else
colours = tty_term_number(tty->term, TTYC_COLORS);
@@ -2477,14 +2506,13 @@ 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)
+tty_check_us(__unused struct tty *tty, int *palette, 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)
+ if ((c = tty_get_palette(palette, gc->us)) != -1)
gc->us = c;
}
@@ -2509,7 +2537,7 @@ tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
/* Is this an aixterm bright colour? */
if (gc->fg >= 90 && gc->fg <= 97) {
- if (tty->term_flags & TERM_256COLOURS) {
+ if (tty->term->flags & TERM_256COLOURS) {
xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
tty_puts(tty, s);
} else
@@ -2541,7 +2569,7 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
/* Is this an aixterm bright colour? */
if (gc->bg >= 90 && gc->bg <= 97) {
- if (tty->term_flags & TERM_256COLOURS) {
+ if (tty->term->flags & TERM_256COLOURS) {
xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
tty_puts(tty, s);
} else
@@ -2586,122 +2614,74 @@ static int
tty_try_colour(struct tty *tty, int colour, const char *type)
{
u_char r, g, b;
- char s[32];
if (colour & COLOUR_FLAG_256) {
- /*
- * If the user has specified -2 to the client (meaning
- * TERM_256COLOURS is set), setaf and setab may not work (or
- * they may not want to use them), so send the usual sequence.
- *
- * Also if RGB is set, setaf and setab do not support the 256
- * colour palette so use the sequences directly there too.
- */
- if ((tty->term_flags & TERM_256COLOURS) ||
- tty_term_has(tty->term, TTYC_RGB))
- goto fallback_256;
-
- /*
- * If the terminfo entry has 256 colours and setaf and setab
- * exist, assume that they work correctly.
- */
- if (tty->term->flags & TERM_256COLOURS) {
- if (*type == '3') {
- if (!tty_term_has(tty->term, TTYC_SETAF))
- goto fallback_256;
- tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
- } else {
- if (!tty_term_has(tty->term, TTYC_SETAB))
- goto fallback_256;
- tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
- }
- return (0);
- }
- goto fallback_256;
+ if (*type == '3' && tty_term_has(tty->term, TTYC_SETAF))
+ tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
+ else if (tty_term_has(tty->term, TTYC_SETAB))
+ tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
+ return (0);
}
if (colour & COLOUR_FLAG_RGB) {
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
- if (*type == '3') {
- if (!tty_term_has(tty->term, TTYC_SETRGBF))
- goto fallback_rgb;
+ if (*type == '3' && tty_term_has(tty->term, TTYC_SETRGBF))
tty_putcode3(tty, TTYC_SETRGBF, r, g, b);
- } else {
- if (!tty_term_has(tty->term, TTYC_SETRGBB))
- goto fallback_rgb;
+ else if (tty_term_has(tty->term, TTYC_SETRGBB))
tty_putcode3(tty, TTYC_SETRGBB, r, g, b);
- }
return (0);
}
return (-1);
-
-fallback_256:
- xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
- log_debug("%s: 256 colour fallback: %s", tty->client->name, s);
- tty_puts(tty, s);
- return (0);
-
-fallback_rgb:
- xsnprintf(s, sizeof s, "\033[%s;2;%d;%d;%dm", type, r, g, b);
- log_debug("%s: RGB colour fallback: %s", tty->client->name, s);
- tty_puts(tty, s);
- return (0);
}
static void
+tty_window_default_style(struct grid_cell *gc, struct window_pane *wp)
+{
+ memcpy(gc, &grid_default_cell, sizeof *gc);
+ gc->fg = wp->fg;
+ gc->bg = wp->bg;
+}
+
+void
tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
{
struct options *oo = wp->options;
- struct style *style, *active_style;
- int c;
+
+ memcpy(gc, &grid_default_cell, sizeof *gc);
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_style = &wp->cached_active_style;
- style = &wp->cached_style;
+ tty_window_default_style(&wp->cached_active_gc, wp);
+ style_add(&wp->cached_active_gc, oo, "window-active-style",
+ NULL);
+ tty_window_default_style(&wp->cached_gc, wp);
+ style_add(&wp->cached_gc, oo, "window-style", NULL);
}
if (gc->fg == 8) {
- if (wp == wp->window->active && active_style->gc.fg != 8)
- gc->fg = active_style->gc.fg;
+ if (wp == wp->window->active && wp->cached_active_gc.fg != 8)
+ gc->fg = wp->cached_active_gc.fg;
else
- gc->fg = style->gc.fg;
-
- if (gc->fg != 8) {
- c = window_pane_get_palette(wp, gc->fg);
- if (c != -1)
- gc->fg = c;
- }
+ gc->fg = wp->cached_gc.fg;
}
if (gc->bg == 8) {
- if (wp == wp->window->active && active_style->gc.bg != 8)
- gc->bg = active_style->gc.bg;
+ if (wp == wp->window->active && wp->cached_active_gc.bg != 8)
+ gc->bg = wp->cached_active_gc.bg;
else
- gc->bg = style->gc.bg;
-
- if (gc->bg != 8) {
- c = window_pane_get_palette(wp, gc->bg);
- if (c != -1)
- gc->bg = c;
- }
+ gc->bg = wp->cached_gc.bg;
}
}
static void
-tty_default_attributes(struct tty *tty, struct window_pane *wp, u_int bg)
+tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
+ int *palette, u_int bg)
{
- static struct grid_cell gc;
+ struct grid_cell gc;
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.bg = bg;
- tty_attributes(tty, &gc, wp);
+ tty_attributes(tty, &gc, defaults, palette);
}