summaryrefslogtreecommitdiff
path: root/usr.bin/tmux/grid.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2022-07-06 07:36:37 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2022-07-06 07:36:37 +0000
commit6bd40e339c592bc85e805b752cb38b6d403ce6d0 (patch)
tree0bf070acd30491424840891af7b218b7c4963831 /usr.bin/tmux/grid.c
parent8bc13742a5911c3c26e612fc67efdef829f18ee2 (diff)
Support hyperlinks with capture-pane -e and add a mouse_hyperlink
format, GitHub issue 3247 from Jeff Chiang.
Diffstat (limited to 'usr.bin/tmux/grid.c')
-rw-r--r--usr.bin/tmux/grid.c74
1 files changed, 64 insertions, 10 deletions
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 <nicholas.marriott@gmail.com>
@@ -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--;