aboutsummaryrefslogtreecommitdiff
path: root/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'tty.c')
-rw-r--r--tty.c295
1 files changed, 166 insertions, 129 deletions
diff --git a/tty.c b/tty.c
index 8efe57b5..016ce399 100644
--- a/tty.c
+++ b/tty.c
@@ -74,7 +74,7 @@ static void tty_default_attributes(struct tty *, struct window_pane *,
u_int);
#define tty_use_margin(tty) \
- ((tty->term->flags|tty->term_flags) & TERM_DECSLRM)
+ (tty->term->flags & TERM_DECSLRM)
#define tty_pane_full_width(tty, ctx) \
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
@@ -96,27 +96,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 +248,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 +287,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 +330,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 +352,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 +406,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 +416,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 +459,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 +664,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 +674,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 +700,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;
}
@@ -918,6 +931,7 @@ 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 client *c = tty->client;
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
u_int i;
@@ -927,6 +941,7 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
* likely to be followed by some more scrolling.
*/
if (tty_large_region(tty, ctx)) {
+ log_debug("%s: %s, large redraw of %%%u", __func__, c->name, wp->id);
wp->flags |= PANE_REDRAW;
return;
}
@@ -1151,8 +1166,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);
@@ -1231,7 +1245,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,6 +1258,16 @@ 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)
@@ -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 ||
@@ -1352,7 +1377,9 @@ 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) {
+ if (!tty_check_overlay(tty, atx + ux, aty))
+ ux += gcp->data.width;
+ else if (ux + gcp->data.width > nx) {
tty_attributes(tty, &last, wp);
tty_cursor(tty, atx + ux, aty);
for (j = 0; j < gcp->data.width; j++) {
@@ -1366,7 +1393,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
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;
@@ -1397,6 +1424,36 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
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)
{
@@ -1428,6 +1485,15 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
TAILQ_FOREACH(c, &clients, entry) {
if (!tty_client_ready(c, wp))
continue;
+ if (c->flags & CLIENT_REDRAWPANES) {
+ /*
+ * Redraw is already deferred to redraw another pane -
+ * redraw this one also when that happens.
+ */
+ log_debug("adding %%%u to deferred redraw", wp->id);
+ wp->flags |= PANE_REDRAW;
+ break;
+ }
ctx->bigger = tty_window_offset(&c->tty, &ctx->ox, &ctx->oy,
&ctx->sx, &ctx->sy);
@@ -1687,7 +1753,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);
}
}
@@ -1890,6 +1959,12 @@ 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)
{
@@ -1952,7 +2027,7 @@ tty_invalidate(struct tty *tty)
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;
@@ -1999,8 +2074,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;
@@ -2025,8 +2104,6 @@ tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
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 +2115,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;
}
@@ -2080,6 +2156,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;
@@ -2392,14 +2471,14 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
/* 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);
@@ -2441,14 +2520,14 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
/* 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);
@@ -2509,7 +2588,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 +2620,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,67 +2665,25 @@ 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