Support hyperlinks with capture-pane -e and add a mouse_hyperlink

format, GitHub issue 3247 from Jeff Chiang.
This commit is contained in:
nicm
2022-07-06 07:36:36 +00:00
parent 9360e0ef32
commit d0d2c39dec
9 changed files with 118 additions and 16 deletions

72
grid.c
View File

@@ -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--;