From b8581ec80e5339be5e2c08cfec70a77f21ba06b2 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 11 Oct 2021 13:27:50 +0000 Subject: Make positions hidden by overlays range-based rather than character-based, from Anindya Mukherjee. --- tty.c | 131 +++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 50 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 0f295f6c..9a8265ef 100644 --- a/tty.c +++ b/tty.c @@ -71,6 +71,8 @@ static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int); static void tty_default_attributes(struct tty *, const struct grid_cell *, struct colour_palette *, u_int); static int tty_check_overlay(struct tty *, u_int, u_int); +static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int, + struct overlay_ranges *); #define tty_use_margin(tty) \ (tty->term->flags & TERM_DECSLRM) @@ -1046,8 +1048,9 @@ static void 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; - u_int i; + struct client *c = tty->client; + struct overlay_ranges r; + u_int i; log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); @@ -1083,18 +1086,13 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, * Couldn't use an escape sequence, use spaces. Clear only the visible * bit if there is an overlay. */ - for (i = 0; i < nx; i++) { - if (!tty_check_overlay(tty, px + i, py)) - break; - } - tty_cursor(tty, px, py); - tty_repeat_space(tty, i); - for (; i < nx; i++) { - if (tty_check_overlay(tty, px + i, py)) - break; + tty_check_overlay_range(tty, px, py, nx, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) { + if (r.nx[i] == 0) + continue; + tty_cursor(tty, r.px[i], py); + tty_repeat_space(tty, r.nx[i]); } - tty_cursor(tty, px + i, py); - tty_repeat_space(tty, nx - i); } /* Clear a line, adjusting to visible part of pane. */ @@ -1306,14 +1304,44 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc) return (&new); } +/* + * Check if a single character is obstructed by the overlay and return a + * boolean. + */ static int tty_check_overlay(struct tty *tty, u_int px, u_int py) +{ + struct overlay_ranges r; + + /* + * A unit width range will always return nx[2] == 0 from a check, even + * with multiple overlays, so it's sufficient to check just the first + * two entries. + */ + tty_check_overlay_range(tty, px, py, 1, &r); + if (r.nx[0] + r.nx[1] == 0) + return (0); + return (1); +} + +/* Return parts of the input range which are visible. */ +static void +tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx, + struct overlay_ranges *r) { struct client *c = tty->client; - if (c->overlay_check == NULL) - return (1); - return (c->overlay_check(c, c->overlay_data, px, py)); + if (c->overlay_check == NULL) { + r->px[0] = px; + r->nx[0] = nx; + r->px[1] = 0; + r->nx[1] = 0; + r->px[2] = 0; + r->nx[2] = 0; + return; + } + + c->overlay_check(c, c->overlay_data, px, py, nx, r); } void @@ -1326,11 +1354,12 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, const struct grid_cell *gcp; struct grid_line *gl; struct client *c = tty->client; - u_int i, j, ux, sx, width, hidden; + struct overlay_ranges r; + u_int i, j, ux, sx, width, hidden, eux, nxx; + u_int cellsize; int flags, cleared = 0, wrapped = 0; char buf[512]; size_t len; - u_int cellsize; log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx, atx, aty); @@ -1430,29 +1459,31 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, else memcpy(&last, gcp, sizeof last); + tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width, + &r); hidden = 0; - for (j = 0; j < gcp->data.width; j++) { - if (!tty_check_overlay(tty, atx + ux + j, aty)) - hidden++; - } + for (j = 0; j < OVERLAY_MAX_RANGES; j++) + hidden += r.nx[j]; + hidden = gcp->data.width - hidden; if (hidden != 0 && hidden == gcp->data.width) { if (~gcp->flags & GRID_FLAG_PADDING) ux += gcp->data.width; } else if (hidden != 0 || ux + gcp->data.width > nx) { if (~gcp->flags & GRID_FLAG_PADDING) { tty_attributes(tty, &last, defaults, palette); - tty_cursor(tty, atx + ux, aty); - for (j = 0; j < gcp->data.width; j++) { - if (ux > nx) - break; - if (tty_check_overlay(tty, atx + ux, - aty)) - tty_putc(tty, ' '); - else { - tty_cursor(tty, atx + ux + 1, - aty); + for (j = 0; j < OVERLAY_MAX_RANGES; j++) { + if (r.nx[j] == 0) + continue; + /* Effective width drawn so far. */ + eux = r.px[j] - atx; + if (eux < nx) { + tty_cursor(tty, r.px[j], aty); + nxx = nx - eux; + if (r.nx[j] > nxx) + r.nx[j] = nxx; + tty_repeat_space(tty, r.nx[j]); + ux = eux + r.nx[j]; } - ux++; } } } else if (gcp->attr & GRID_ATTR_CHARSET) { @@ -1926,7 +1957,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) { const struct grid_cell *gcp = ctx->cell; struct screen *s = ctx->s; - u_int i, px, py; + struct overlay_ranges r; + u_int px, py, i, vis = 0; px = ctx->xoff + ctx->ocx - ctx->wox; py = ctx->yoff + ctx->ocy - ctx->woy; @@ -1936,13 +1968,14 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) /* Handle partially obstructed wide characters. */ if (gcp->data.width > 1) { - for (i = 0; i < gcp->data.width; i++) { - if (!tty_check_overlay(tty, px + i, py)) { - tty_draw_line(tty, s, s->cx, s->cy, + tty_check_overlay_range(tty, px, py, gcp->data.width, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) + vis += r.nx[i]; + if (vis < gcp->data.width) { + tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width, px, py, &ctx->defaults, ctx->palette); return; - } } } @@ -1960,7 +1993,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) { - u_int i, hide = 0; + struct overlay_ranges r; + u_int i, px; if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) return; @@ -1985,18 +2019,15 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); - for (i = 0; i < ctx->num; i++) { - if (!tty_check_overlay(tty, tty->cx + i, tty->cy)) - break; - } - tty_putn(tty, ctx->ptr, i, i); - for (; i < ctx->num; i++) { - if (tty_check_overlay(tty, tty->cx + hide, tty->cy)) - break; - hide++; + px = tty->cx; + tty_check_overlay_range(tty, px, tty->cy, ctx->num, &r); + for (i = 0; i < OVERLAY_MAX_RANGES; i++) { + if (r.nx[i] == 0) + continue; + tty_cursor(tty, r.px[i], tty->cy); + tty_putn(tty, (char *)ctx->ptr + r.px[i] - px, r.nx[i], + r.nx[i]); } - tty_cursor(tty, tty->cx + hide, tty->cy); - tty_putn(tty, (char *)ctx->ptr + i, ctx->num - i, ctx->num - i); } void -- cgit From d0ab1a837a0ab3e26fe7195f14672f6feb43c4c4 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 14 Oct 2021 09:54:51 +0000 Subject: When checking ranges in tty_cmd_cells, cannot use the tty cursor position and tty_cursor because it may be at the final invisible cursor position on automargin terminals. The text to be drawn is confined to the pane, so use the pane cursor position for the checks instead. Fix from Anindya Mukherjee, redraw problem reported by naddy@. --- tty.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 9a8265ef..809289e0 100644 --- a/tty.c +++ b/tty.c @@ -1993,8 +1993,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) { - struct overlay_ranges r; - u_int i, px; + struct overlay_ranges r; + u_int i, px, py, cx; + char *cp = ctx->ptr; if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) return; @@ -2017,16 +2018,20 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); - px = tty->cx; - tty_check_overlay_range(tty, px, tty->cy, ctx->num, &r); + + /* Get tty position from pane position for overlay check. */ + px = ctx->xoff + ctx->ocx - ctx->wox; + py = ctx->yoff + ctx->ocy - ctx->woy; + + tty_check_overlay_range(tty, px, py, ctx->num, &r); for (i = 0; i < OVERLAY_MAX_RANGES; i++) { if (r.nx[i] == 0) continue; - tty_cursor(tty, r.px[i], tty->cy); - tty_putn(tty, (char *)ctx->ptr + r.px[i] - px, r.nx[i], - r.nx[i]); + /* Convert back to pane position for printing. */ + cx = r.px[i] - ctx->xoff + ctx->wox; + tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy); + tty_putn(tty, cp + r.px[i] - px, r.nx[i], r.nx[i]); } } -- cgit From 0cca695d6e75426e295e03668a4ed35ee62afe7c Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 25 Oct 2021 09:22:17 +0000 Subject: Instead of setting the popup default colours in the draw callback, set it up in popup_display and follow the same routine as panes in the draw and init_ctx callbacks - use the palette if the option value is default. Allows application-set fg and bg to work in panes again. --- tty.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 809289e0..243eae56 100644 --- a/tty.c +++ b/tty.c @@ -1972,10 +1972,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) for (i = 0; i < OVERLAY_MAX_RANGES; i++) vis += r.nx[i]; if (vis < gcp->data.width) { - tty_draw_line(tty, s, s->cx, s->cy, - gcp->data.width, px, py, &ctx->defaults, - ctx->palette); - return; + tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width, + px, py, &ctx->defaults, ctx->palette); + return; } } -- cgit From 4acad43013b7bb5f91103a68cfce591b1980ae17 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 28 Oct 2021 18:57:06 +0000 Subject: Do not force the cursor to move if it is in the automargin space at EOL and that is where we want it to be, GitHub issue 2956. --- tty.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 243eae56..62298a54 100644 --- a/tty.c +++ b/tty.c @@ -2278,17 +2278,25 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy) if (tty->flags & TTY_BLOCK) return; - if (cx > tty->sx - 1) - cx = tty->sx - 1; - thisx = tty->cx; thisy = tty->cy; + /* + * If in the automargin space, and want to be there, do not move. + * Otherwise, force the cursor to be in range (and complain). + */ + if (cx == thisx && cy == thisy && cx == tty->sx) + return; + if (cx > tty->sx - 1) { + log_debug("%s: x too big %u > %u", __func__, cx, tty->sx - 1); + cx = tty->sx - 1; + } + /* No change. */ if (cx == thisx && cy == thisy) return; - /* Very end of the line, just use absolute movement. */ + /* Currently at the very end of the line - use absolute movement. */ if (thisx > tty->sx - 1) goto absolute; -- cgit From 8d2286b76917debc4f6c3b0903ad2807ae254bb5 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 1 Nov 2021 09:34:49 +0000 Subject: Add a cursor-colour option, from Alexis Hildebrandt in GitHub issue 2959. --- tty.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 62298a54..38a7a752 100644 --- a/tty.c +++ b/tty.c @@ -38,7 +38,7 @@ static int tty_client_ready(struct client *); static void tty_set_italics(struct tty *); static int tty_try_colour(struct tty *, int, const char *); -static void tty_force_cursor_colour(struct tty *, const char *); +static void tty_force_cursor_colour(struct tty *, int); static void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_cursor_pane_unless_wrap(struct tty *, @@ -105,7 +105,7 @@ tty_init(struct tty *tty, struct client *c) tty->client = c; tty->cstyle = SCREEN_CURSOR_DEFAULT; - tty->ccolour = xstrdup(""); + tty->ccolour = -1; if (tcgetattr(c->fd, &tty->tio) != 0) return (-1); @@ -341,8 +341,8 @@ tty_start_tty(struct tty *tty) tty->flags |= TTY_STARTED; tty_invalidate(tty); - if (*tty->ccolour != '\0') - tty_force_cursor_colour(tty, ""); + if (tty->ccolour != -1) + tty_force_cursor_colour(tty, -1); tty->mouse_drag_flag = 0; tty->mouse_drag_update = NULL; @@ -406,7 +406,7 @@ tty_stop_tty(struct tty *tty) } if (tty->mode & MODE_BRACKETPASTE) tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP)); - if (*tty->ccolour != '\0') + if (tty->ccolour != -1) tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); @@ -451,7 +451,6 @@ void tty_free(struct tty *tty) { tty_close(tty); - free(tty->ccolour); } void @@ -650,24 +649,38 @@ tty_set_title(struct tty *tty, const char *title) } static void -tty_force_cursor_colour(struct tty *tty, const char *ccolour) +tty_force_cursor_colour(struct tty *tty, int c) { - if (*ccolour == '\0') + u_char r, g, b; + char s[13] = ""; + + if (c != -1) + c = colour_force_rgb(c); + if (c == tty->ccolour) + return; + if (c == -1) tty_putcode(tty, TTYC_CR); - else - tty_putcode_ptr1(tty, TTYC_CS, ccolour); - free(tty->ccolour); - tty->ccolour = xstrdup(ccolour); + else { + colour_split_rgb(c, &r, &g, &b); + xsnprintf(s, sizeof s, "rgb:%02hhx/%02hhx/%02hhx", r, g, b); + tty_putcode_ptr1(tty, TTYC_CS, s); + } + tty->ccolour = c; } static void tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) { - enum screen_cursor_style cstyle; + enum screen_cursor_style cstyle; + int ccolour; /* Set cursor colour if changed. */ - if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) - tty_force_cursor_colour(tty, s->ccolour); + if (s != NULL) { + ccolour = s->ccolour; + if (s->ccolour == -1) + ccolour = s->default_ccolour; + tty_force_cursor_colour(tty, ccolour); + } /* If cursor is off, set as invisible. */ if (~mode & MODE_CURSOR) { -- cgit From 57100376cc70739f53a1f8a4bacf192b8cdcd124 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 3 Nov 2021 13:37:17 +0000 Subject: Add a cursor-style option, from Alexis Hildebrandt in GitHub issue 2960. --- tty.c | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 38a7a752..70470a08 100644 --- a/tty.c +++ b/tty.c @@ -668,11 +668,11 @@ tty_force_cursor_colour(struct tty *tty, int c) tty->ccolour = c; } -static void -tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) +static int +tty_update_cursor(struct tty *tty, int mode, struct screen *s) { enum screen_cursor_style cstyle; - int ccolour; + int ccolour, changed, cmode = mode; /* Set cursor colour if changed. */ if (s != NULL) { @@ -683,19 +683,32 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) } /* If cursor is off, set as invisible. */ - if (~mode & MODE_CURSOR) { - if (changed & MODE_CURSOR) + if (~cmode & MODE_CURSOR) { + if (tty->mode & MODE_CURSOR) tty_putcode(tty, TTYC_CIVIS); - return; + return (cmode); } /* Check if blinking or very visible flag changed or style changed. */ if (s == NULL) cstyle = tty->cstyle; - else + else { cstyle = s->cstyle; + if (cstyle == SCREEN_CURSOR_DEFAULT) { + if (~cmode & MODE_CURSOR_BLINKING_SET) { + if (s->default_mode & MODE_CURSOR_BLINKING) + cmode |= MODE_CURSOR_BLINKING; + else + cmode &= ~MODE_CURSOR_BLINKING; + } + cstyle = s->default_cstyle; + } + } + + /* If nothing changed, do nothing. */ + changed = cmode ^ tty->mode; if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle) - return; + return (cmode); /* * Set cursor style. If an explicit style has been set with DECSCUSR, @@ -713,49 +726,56 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) else tty_putcode1(tty, TTYC_SS, 0); } - if (mode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) + if (cmode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) tty_putcode(tty, TTYC_CVVIS); break; case SCREEN_CURSOR_BLOCK: if (tty_term_has(tty->term, TTYC_SS)) { - if (mode & MODE_CURSOR_BLINKING) + if (cmode & MODE_CURSOR_BLINKING) tty_putcode1(tty, TTYC_SS, 1); else tty_putcode1(tty, TTYC_SS, 2); - } else if (mode & MODE_CURSOR_BLINKING) + } else if (cmode & MODE_CURSOR_BLINKING) tty_putcode(tty, TTYC_CVVIS); break; case SCREEN_CURSOR_UNDERLINE: if (tty_term_has(tty->term, TTYC_SS)) { - if (mode & MODE_CURSOR_BLINKING) + if (cmode & MODE_CURSOR_BLINKING) tty_putcode1(tty, TTYC_SS, 3); else tty_putcode1(tty, TTYC_SS, 4); - } else if (mode & MODE_CURSOR_BLINKING) + } else if (cmode & MODE_CURSOR_BLINKING) tty_putcode(tty, TTYC_CVVIS); break; case SCREEN_CURSOR_BAR: if (tty_term_has(tty->term, TTYC_SS)) { - if (mode & MODE_CURSOR_BLINKING) + if (cmode & MODE_CURSOR_BLINKING) tty_putcode1(tty, TTYC_SS, 5); else tty_putcode1(tty, TTYC_SS, 6); - } else if (mode & MODE_CURSOR_BLINKING) + } else if (cmode & MODE_CURSOR_BLINKING) tty_putcode(tty, TTYC_CVVIS); break; } tty->cstyle = cstyle; + return (cmode); } void tty_update_mode(struct tty *tty, int mode, struct screen *s) { + struct tty_term *term = tty->term; struct client *c = tty->client; int changed; if (tty->flags & TTY_NOCURSOR) mode &= ~MODE_CURSOR; + if (tty_update_cursor(tty, mode, s) & MODE_CURSOR_BLINKING) + mode |= MODE_CURSOR_BLINKING; + else + mode &= ~MODE_CURSOR_BLINKING; + changed = mode ^ tty->mode; if (log_get_level() != 0 && changed != 0) { log_debug("%s: current mode %s", c->name, @@ -764,9 +784,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) screen_mode_to_string(mode)); } - tty_update_cursor(tty, mode, changed, s); - if ((changed & ALL_MOUSE_MODES) && - tty_term_has(tty->term, TTYC_KMOUS)) { + if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) { /* * If the mouse modes have changed, clear any that are set and * apply again. There are differences in how terminals track -- cgit From 333cf6429ae16da6fb3892978ea450bc62c3e873 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 29 Nov 2021 11:05:28 +0000 Subject: Bump response timer to three seconds, GitHub issue 2984. --- tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 70470a08..233d52a8 100644 --- a/tty.c +++ b/tty.c @@ -302,7 +302,7 @@ tty_start_tty(struct tty *tty) { struct client *c = tty->client; struct termios tio; - struct timeval tv = { .tv_sec = 1 }; + struct timeval tv = { .tv_sec = 3 }; setblocking(c->fd, 0); event_add(&tty->event_in, NULL); -- cgit From 8fccbbb02673bed71676412f1a313093a39c48ff Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 6 Dec 2021 10:08:42 +0000 Subject: Do not dereference NULL window when resizing client, GitHub issue 2982. --- tty.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 233d52a8..a9678eaf 100644 --- a/tty.c +++ b/tty.c @@ -937,7 +937,9 @@ tty_update_window_offset(struct window *w) struct client *c; TAILQ_FOREACH(c, &clients, entry) { - if (c->session != NULL && c->session->curw->window == w) + if (c->session != NULL && + c->session->curw != NULL && + c->session->curw->window == w) tty_update_client_offset(c); } } -- cgit From db3aabcc34464940c286d7ce3abc8f3edc94b7bc Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 10 Dec 2021 12:42:37 +0000 Subject: Add a NOBLOCK flag rather than adding amount to wait for when dealing with potentially-long sequences. GitHub issue 3001. --- tty.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index a9678eaf..3aefe784 100644 --- a/tty.c +++ b/tty.c @@ -206,6 +206,11 @@ tty_block_maybe(struct tty *tty) size_t size = EVBUFFER_LENGTH(tty->out); struct timeval tv = { .tv_usec = TTY_BLOCK_INTERVAL }; + if (size == 0) + tty->flags &= ~TTY_NOBLOCK; + else if (tty->flags & TTY_NOBLOCK) + return (0); + if (size < TTY_BLOCK_START(tty)) return (0); @@ -2088,8 +2093,8 @@ tty_set_selection(struct tty *tty, const char *buf, size_t len) encoded = xmalloc(size); b64_ntop(buf, len, encoded, size); + tty->flags |= TTY_NOBLOCK; tty_putcode_ptr2(tty, TTYC_MS, "", encoded); - tty->client->redraw = EVBUFFER_LENGTH(tty->out); free(encoded); } @@ -2097,6 +2102,7 @@ tty_set_selection(struct tty *tty, const char *buf, size_t len) void tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) { + tty->flags |= TTY_NOBLOCK; tty_add(tty, ctx->ptr, ctx->num); tty_invalidate(tty); } -- cgit From e6e3c75ed70adece8b1cf93017f6f359d022bdb0 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 31 Dec 2021 11:35:49 +0000 Subject: Try to turn on less-capable mouse modes when turning on more-capable, to increase the chances we get something even if the terminal doesn't support the one we really want. GitHub issue 3020. --- tty.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 3aefe784..8410a64c 100644 --- a/tty.c +++ b/tty.c @@ -791,26 +791,19 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) { /* - * If the mouse modes have changed, clear any that are set and - * apply again. There are differences in how terminals track - * the various bits. + * If the mouse modes have changed, clear then all and apply + * again. There are differences in how terminals track the + * various bits. */ - if (tty->mode & MODE_MOUSE_SGR) - tty_puts(tty, "\033[?1006l"); - if (tty->mode & MODE_MOUSE_STANDARD) - tty_puts(tty, "\033[?1000l"); - if (tty->mode & MODE_MOUSE_BUTTON) - tty_puts(tty, "\033[?1002l"); - if (tty->mode & MODE_MOUSE_ALL) - tty_puts(tty, "\033[?1003l"); + tty_puts(tty, "\033[?1006l\033[?1000l\033[?1002l\033[?1003l"); if (mode & ALL_MOUSE_MODES) tty_puts(tty, "\033[?1006h"); - if (mode & MODE_MOUSE_STANDARD) - tty_puts(tty, "\033[?1000h"); - if (mode & MODE_MOUSE_BUTTON) - tty_puts(tty, "\033[?1002h"); if (mode & MODE_MOUSE_ALL) - tty_puts(tty, "\033[?1003h"); + tty_puts(tty, "\033[?1000h\033[?1002h\033[?1003h"); + if (mode & MODE_MOUSE_BUTTON) + tty_puts(tty, "\033[?1000h\033[?1002h"); + else if (mode & MODE_MOUSE_STANDARD) + tty_puts(tty, "\033[?1000h"); } if (changed & MODE_BRACKETPASTE) { if (mode & MODE_BRACKETPASTE) -- cgit From f85208602ddd43ba55f29beae8d7a05cbfedefc1 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 15 Feb 2022 13:03:02 +0000 Subject: Do not create a buffer from an OSC 52 response if we have not sent a query. --- tty.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 8410a64c..06b1bfb2 100644 --- a/tty.c +++ b/tty.c @@ -83,6 +83,8 @@ static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int, #define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8) #define TTY_BLOCK_STOP(tty) (1 + ((tty)->sx * (tty)->sy) / 8) +#define TTY_QUERY_TIMEOUT 5 + void tty_create_log(void) { @@ -307,7 +309,7 @@ tty_start_tty(struct tty *tty) { struct client *c = tty->client; struct termios tio; - struct timeval tv = { .tv_sec = 3 }; + struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; setblocking(c->fd, 0); event_add(&tty->event_in, NULL); @@ -2917,3 +2919,26 @@ tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, gc.bg = bg; tty_attributes(tty, &gc, defaults, palette); } + +static void +tty_query_timer_callback(__unused int fd, __unused short events, void *data) +{ + struct tty *tty = data; + + tty->flags &= ~TTY_OSC52QUERY; +} + +void +tty_send_osc52_query(struct tty *tty) +{ + struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; + + if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY)) + return; + tty_putcode_ptr2(tty, TTYC_MS, "", "?"); + tty->flags |= TTY_OSC52QUERY; + + evtimer_set(&tty->query_timer, tty_query_timer_callback, tty); + evtimer_add(&tty->query_timer, &tv); +} + -- cgit From ad9b8059836d424f70a8579d28e28e0186cdbaa6 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 8 Mar 2022 12:01:19 +0000 Subject: Add argument to refresh-client -l to forward clipboard to a pane. GitHub issue 3068. --- tty.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 06b1bfb2..40735ceb 100644 --- a/tty.c +++ b/tty.c @@ -2921,24 +2921,29 @@ tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, } static void -tty_query_timer_callback(__unused int fd, __unused short events, void *data) +tty_clipboard_query_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; + struct client *c = tty->client; + + c->flags &= ~CLIENT_CLIPBOARDBUFFER; + free(c->clipboard_panes); + c->clipboard_panes = NULL; + c->clipboard_npanes = 0; tty->flags &= ~TTY_OSC52QUERY; } void -tty_send_osc52_query(struct tty *tty) +tty_clipboard_query(struct tty *tty) { struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY)) return; tty_putcode_ptr2(tty, TTYC_MS, "", "?"); - tty->flags |= TTY_OSC52QUERY; - evtimer_set(&tty->query_timer, tty_query_timer_callback, tty); - evtimer_add(&tty->query_timer, &tv); + tty->flags |= TTY_OSC52QUERY; + evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty); + evtimer_add(&tty->clipboard_timer, &tv); } - -- cgit From 792d13af49f2550a9a8d11b0099528628957a1a0 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 24 Mar 2022 09:05:57 +0000 Subject: Add a capability for OSC 7 and use it similarly to how the title is set (and controlled by the same set-titles option). GitHub issue 3127. --- tty.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 40735ceb..ea10e61e 100644 --- a/tty.c +++ b/tty.c @@ -655,6 +655,18 @@ tty_set_title(struct tty *tty, const char *title) tty_putcode(tty, TTYC_FSL); } +void +tty_set_path(struct tty *tty, const char *title) +{ + if (!tty_term_has(tty->term, TTYC_SWD) || + !tty_term_has(tty->term, TTYC_FSL)) + return; + + tty_putcode(tty, TTYC_SWD); + tty_puts(tty, title); + tty_putcode(tty, TTYC_FSL); +} + static void tty_force_cursor_colour(struct tty *tty, int c) { -- cgit From 3edda3c5e71d634efd8e1e849328a68fb9da37de Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 3 Jun 2022 08:09:16 +0000 Subject: Do not unintentionally turn off all mouse mode when button is also present. --- tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index ea10e61e..49cf9795 100644 --- a/tty.c +++ b/tty.c @@ -814,7 +814,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) tty_puts(tty, "\033[?1006h"); if (mode & MODE_MOUSE_ALL) tty_puts(tty, "\033[?1000h\033[?1002h\033[?1003h"); - if (mode & MODE_MOUSE_BUTTON) + else if (mode & MODE_MOUSE_BUTTON) tty_puts(tty, "\033[?1000h\033[?1002h"); else if (mode & MODE_MOUSE_STANDARD) tty_puts(tty, "\033[?1000h"); -- cgit From ccc9dc3bb49ac258c856d8478346b4ce829b188e Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 9 Jun 2022 09:12:55 +0000 Subject: If an application gives the first parameter to OSC 52, validate and pass on to outside terminal. GitHub issue 3192. --- tty.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 49cf9795..7e0a6a3e 100644 --- a/tty.c +++ b/tty.c @@ -671,7 +671,7 @@ static void tty_force_cursor_colour(struct tty *tty, int c) { u_char r, g, b; - char s[13] = ""; + char s[13]; if (c != -1) c = colour_force_rgb(c); @@ -2082,11 +2082,12 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx) { - tty_set_selection(tty, ctx->ptr, ctx->num); + tty_set_selection(tty, ctx->ptr2, ctx->ptr, ctx->num); } void -tty_set_selection(struct tty *tty, const char *buf, size_t len) +tty_set_selection(struct tty *tty, const char *flags, const char *buf, + size_t len) { char *encoded; size_t size; @@ -2101,7 +2102,7 @@ tty_set_selection(struct tty *tty, const char *buf, size_t len) b64_ntop(buf, len, encoded, size); tty->flags |= TTY_NOBLOCK; - tty_putcode_ptr2(tty, TTYC_MS, "", encoded); + tty_putcode_ptr2(tty, TTYC_MS, flags, encoded); free(encoded); } -- cgit From cdacc12ce305ad2f3e65e2a01328a988e3200b51 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 30 Jun 2022 09:55:53 +0000 Subject: Add support for OSC 8 hyperlinks (a VTE extension now supported by other terminals such as iTerm2). Originally written by me then extended and completed by first Will Noble and later Jeff Chiang. GitHub issues 911, 2621, 2890, 3240. --- tty.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 32 deletions(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 7e0a6a3e..78961e47 100644 --- a/tty.c +++ b/tty.c @@ -69,7 +69,7 @@ static void tty_emulate_repeat(struct tty *, enum tty_code_code, 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_default_attributes(struct tty *, const struct grid_cell *, - struct colour_palette *, u_int); + struct colour_palette *, u_int, struct hyperlinks *); static int tty_check_overlay(struct tty *, u_int, u_int); static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int, struct overlay_ranges *); @@ -1455,7 +1455,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, tty_term_has(tty->term, TTYC_EL1) && !tty_fake_bce(tty, defaults, 8) && c->overlay_check == NULL) { - tty_default_attributes(tty, defaults, palette, 8); + tty_default_attributes(tty, defaults, palette, 8, + s->hyperlinks); tty_cursor(tty, nx - 1, aty); tty_putcode(tty, TTYC_EL1); cleared = 1; @@ -1480,9 +1481,11 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, gcp->fg != last.fg || gcp->bg != last.bg || gcp->us != last.us || + gcp->link != last.link || ux + width + gcp->data.width > nx || (sizeof buf) - len < gcp->data.size)) { - tty_attributes(tty, &last, defaults, palette); + tty_attributes(tty, &last, defaults, palette, + s->hyperlinks); if (last.flags & GRID_FLAG_CLEARED) { log_debug("%s: %zu cleared", __func__, len); tty_clear_line(tty, defaults, aty, atx + ux, @@ -1515,7 +1518,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, ux += gcp->data.width; } else if (hidden != 0 || ux + gcp->data.width > nx) { if (~gcp->flags & GRID_FLAG_PADDING) { - tty_attributes(tty, &last, defaults, palette); + tty_attributes(tty, &last, defaults, palette, + s->hyperlinks); for (j = 0; j < OVERLAY_MAX_RANGES; j++) { if (r.nx[j] == 0) continue; @@ -1532,7 +1536,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, } } } else if (gcp->attr & GRID_ATTR_CHARSET) { - tty_attributes(tty, &last, defaults, palette); + tty_attributes(tty, &last, defaults, palette, + s->hyperlinks); tty_cursor(tty, atx + ux, aty); for (j = 0; j < gcp->data.size; j++) tty_putc(tty, gcp->data.data[j]); @@ -1544,7 +1549,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, } } if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) { - tty_attributes(tty, &last, defaults, palette); + tty_attributes(tty, &last, defaults, palette, s->hyperlinks); if (last.flags & GRID_FLAG_CLEARED) { log_debug("%s: %zu cleared (end)", __func__, len); tty_clear_line(tty, defaults, aty, atx + ux, width, @@ -1560,7 +1565,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, if (!cleared && ux < nx) { log_debug("%s: %u to end of line (%zu cleared)", __func__, nx - ux, len); - tty_default_attributes(tty, defaults, palette, 8); + tty_default_attributes(tty, defaults, palette, 8, + s->hyperlinks); tty_clear_line(tty, defaults, aty, atx + ux, nx - ux, 8); } @@ -1646,7 +1652,8 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -1668,7 +1675,8 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -1678,7 +1686,8 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) { - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, ctx->num, ctx->bg); } @@ -1700,7 +1709,8 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_off(tty); @@ -1727,7 +1737,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_off(tty); @@ -1740,7 +1751,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx) { - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->sx, ctx->bg); } @@ -1750,7 +1762,8 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) { u_int nx = ctx->sx - ctx->ocx; - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, nx, ctx->bg); } @@ -1758,7 +1771,8 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) { - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->ocx + 1, ctx->bg); } @@ -1784,7 +1798,8 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1815,7 +1830,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1855,7 +1871,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1895,7 +1912,8 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1914,7 +1932,8 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) { u_int px, py, nx, ny; - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1938,7 +1957,8 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx) { u_int px, py, nx, ny; - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1962,7 +1982,8 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) { u_int px, py, nx, ny; - tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1985,7 +2006,8 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette); + tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette, + ctx->s->hyperlinks); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -2031,7 +2053,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette); + tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, + ctx->s->hyperlinks); } void @@ -2062,7 +2085,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); + tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette, ctx->s->hyperlinks); /* Get tty position from pane position for overlay check. */ px = ctx->xoff + ctx->ocx - ctx->wox; @@ -2136,7 +2159,8 @@ tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx) void tty_cell(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, struct colour_palette *palette) + const struct grid_cell *defaults, struct colour_palette *palette, + struct hyperlinks *hl) { const struct grid_cell *gcp; @@ -2152,11 +2176,11 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, /* Check the output codeset and apply attributes. */ gcp = tty_check_codeset(tty, gc); - tty_attributes(tty, gcp, defaults, palette); + tty_attributes(tty, gcp, defaults, palette, hl); /* If it is a single character, write with putc to handle ACS. */ if (gcp->data.size == 1) { - tty_attributes(tty, gcp, defaults, palette); + tty_attributes(tty, gcp, defaults, palette, hl); if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f) return; tty_putc(tty, *gcp->data.data); @@ -2173,6 +2197,8 @@ tty_reset(struct tty *tty) struct grid_cell *gc = &tty->cell; if (!grid_cells_equal(gc, &grid_default_cell)) { + if (gc->link != 0) + tty_putcode_ptr2(tty, TTYC_HLS, "", ""); if ((gc->attr & GRID_ATTR_CHARSET) && tty_acs_needed(tty)) tty_putcode(tty, TTYC_RMACS); tty_putcode(tty, TTYC_SGR0); @@ -2462,9 +2488,29 @@ out: tty->cy = cy; } +static void +tty_hyperlink(struct tty *tty, const struct grid_cell *gc, + struct hyperlinks *hl) +{ + const char *uri, *id; + + if (gc->link == tty->cell.link) + return; + tty->cell.link = gc->link; + + if (hl == NULL) + return; + + if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, &id)) + tty_putcode_ptr2(tty, TTYC_HLS, "", ""); + else + tty_putcode_ptr2(tty, TTYC_HLS, id, uri); +} + void tty_attributes(struct tty *tty, const struct grid_cell *gc, - const struct grid_cell *defaults, struct colour_palette *palette) + const struct grid_cell *defaults, struct colour_palette *palette, + struct hyperlinks *hl) { struct grid_cell *tc = &tty->cell, gc2; int changed; @@ -2482,7 +2528,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, 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) + gc2.us == tty->last_cell.us && + gc2.link == tty->last_cell.link) return; /* @@ -2559,6 +2606,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty)) tty_putcode(tty, TTYC_SMACS); + /* Set hyperlink if any. */ + tty_hyperlink(tty, gc, hl); + memcpy(&tty->last_cell, &gc2, sizeof tty->last_cell); } @@ -2924,13 +2974,13 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) static void tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, - struct colour_palette *palette, u_int bg) + struct colour_palette *palette, u_int bg, struct hyperlinks *hl) { struct grid_cell gc; memcpy(&gc, &grid_default_cell, sizeof gc); gc.bg = bg; - tty_attributes(tty, &gc, defaults, palette); + tty_attributes(tty, &gc, defaults, palette, hl); } static void -- cgit From d0d2c39decd1c342f2ffdb360e5d6b509b9bb34e Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 6 Jul 2022 07:36:36 +0000 Subject: Support hyperlinks with capture-pane -e and add a mouse_hyperlink format, GitHub issue 3247 from Jeff Chiang. --- tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tty.c') diff --git a/tty.c b/tty.c index 78961e47..1f373821 100644 --- a/tty.c +++ b/tty.c @@ -2501,7 +2501,7 @@ tty_hyperlink(struct tty *tty, const struct grid_cell *gc, if (hl == NULL) return; - if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, &id)) + if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, NULL, &id)) tty_putcode_ptr2(tty, TTYC_HLS, "", ""); else tty_putcode_ptr2(tty, TTYC_HLS, id, uri); -- cgit