=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/grid.c,v retrieving revision 1.125 retrieving revision 1.126 diff -u -r1.125 -r1.126 --- src/usr.bin/tmux/grid.c 2022/06/30 09:55:53 1.125 +++ src/usr.bin/tmux/grid.c 2022/07/06 07:36:36 1.126 @@ -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 @@ } } +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 @@ 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 @@ 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 @@ -1044,6 +1086,18 @@ } memcpy(buf + off, data, size); 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) {