From 6bd40e339c592bc85e805b752cb38b6d403ce6d0 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 6 Jul 2022 07:36:37 +0000 Subject: Support hyperlinks with capture-pane -e and add a mouse_hyperlink format, GitHub issue 3247 from Jeff Chiang. --- usr.bin/tmux/grid.c | 74 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 10 deletions(-) (limited to 'usr.bin/tmux/grid.c') diff --git a/usr.bin/tmux/grid.c b/usr.bin/tmux/grid.c index 3658fcc62cc..a9f276bfd1d 100644 --- a/usr.bin/tmux/grid.c +++ b/usr.bin/tmux/grid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: grid.c,v 1.125 2022/06/30 09:55:53 nicm Exp $ */ +/* $OpenBSD: grid.c,v 1.126 2022/07/06 07:36:36 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -885,18 +885,47 @@ grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc, } } +static int +grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, + const char *uri, int escape_c0) +{ + char *tmp; + + if (strlen(uri) + strlen(id) + 17 >= len) + return (0); + + if (escape_c0) + strlcat(buf, "\\033]8;", len); + else + strlcat(buf, "\033]8;", len); + if (*id != '\0') { + xasprintf(&tmp, "id=%s;", id); + strlcat(buf, tmp, len); + free(tmp); + } else + strlcat(buf, ";", len); + strlcat(buf, uri, len); + if (escape_c0) + strlcat(buf, "\\033\\\\", len); + else + strlcat(buf, "\033\\", len); + return (1); +} + /* * Returns ANSI code to set particular attributes (colour, bold and so on) * given a current state. */ static void grid_string_cells_code(const struct grid_cell *lastgc, - const struct grid_cell *gc, char *buf, size_t len, int escape_c0) + const struct grid_cell *gc, char *buf, size_t len, int escape_c0, + struct screen *sc, int *has_link) { - int oldc[64], newc[64], s[128]; - size_t noldc, nnewc, n, i; - u_int attr = gc->attr, lastattr = lastgc->attr; - char tmp[64]; + int oldc[64], newc[64], s[128]; + size_t noldc, nnewc, n, i; + u_int attr = gc->attr, lastattr = lastgc->attr; + char tmp[64]; + const char *uri, *id; struct { u_int mask; @@ -986,19 +1015,32 @@ grid_string_cells_code(const struct grid_cell *lastgc, else strlcat(buf, "\017", len); /* SI */ } + + /* Add hyperlink if changed. */ + if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) { + if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) { + *has_link = grid_string_cells_add_hyperlink(buf, len, + id, uri, escape_c0); + } else if (*has_link) { + grid_string_cells_add_hyperlink(buf, len, "", "", + escape_c0); + *has_link = 0; + } + } } /* Convert cells into a string. */ char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, - struct grid_cell **lastgc, int with_codes, int escape_c0, int trim) + struct grid_cell **lastgc, int with_codes, int escape_c0, int trim, + struct screen *s) { struct grid_cell gc; static struct grid_cell lastgc1; const char *data; - char *buf, code[128]; + char *buf, code[8192]; size_t len, off, size, codelen; - u_int xx; + u_int xx, has_link = 0; const struct grid_line *gl; if (lastgc != NULL && *lastgc == NULL) { @@ -1020,7 +1062,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, if (with_codes) { grid_string_cells_code(*lastgc, &gc, code, sizeof code, - escape_c0); + escape_c0, s, &has_link); codelen = strlen(code); memcpy(*lastgc, &gc, sizeof **lastgc); } else @@ -1046,6 +1088,18 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, off += size; } + if (has_link) { + grid_string_cells_add_hyperlink(code, sizeof code, "", "", + escape_c0); + codelen = strlen(code); + while (len < off + size + codelen + 1) { + buf = xreallocarray(buf, 2, len); + len *= 2; + } + memcpy(buf + off, code, codelen); + off += codelen; + } + if (trim) { while (off > 0 && buf[off - 1] == ' ') off--; -- cgit v1.2.3