Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-06-29 18:30:06 +01:00
5 changed files with 82 additions and 6 deletions

View File

@@ -710,6 +710,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
"AFTER" };
size_t size = strlen(expanded);
struct screen *os = octx->s, s[TOTAL];
struct hyperlinks *hl = os->hyperlinks;
struct screen_write_ctx ctx[TOTAL];
u_int ocx = os->cx, ocy = os->cy, n, i, width[TOTAL];
u_int map[] = { LEFT,
@@ -723,7 +724,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
struct grid_cell gc, current_default, base_default;
struct style sy, saved_sy;
struct utf8_data *ud = &sy.gc.data;
const char *cp, *end;
const char *cp, *end, *link_uri;
enum utf8_state more;
char *tmp;
struct format_range *fr = NULL, *fr1;
@@ -838,6 +839,17 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
sy.gc.fg = base->fg;
}
/*
* Resolve any hyperlink and store it in the cell. The URI
* doubles as the internal ID so repeated links share one entry
* and the ID stays stable across redraws.
*/
link_uri = style_link(&sy);
if (link_uri != NULL && hl != NULL)
sy.gc.link = hyperlinks_put(hl, link_uri, link_uri);
else
sy.gc.link = 0;
/* If this style has a fill colour, store it for later. */
if (sy.fill != 8)
fill = sy.fill;

48
style.c
View File

@@ -42,9 +42,17 @@ static struct style style_default = {
STYLE_WIDTH_DEFAULT, 0, STYLE_PAD_DEFAULT,
STYLE_DEFAULT_BASE
STYLE_DEFAULT_BASE,
0
};
/*
* Global hyperlink set holding the URIs for #[link=...] styles, so a style
* only needs to store a small ID rather than the URI itself.
*/
static struct hyperlinks *style_hyperlinks;
/* Set range string. */
static void
style_set_range_string(struct style *sy, const char *s)
@@ -91,6 +99,7 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
sy->gc.us = base->us;
sy->gc.attr = base->attr;
sy->gc.flags = base->flags;
sy->link = 0;
} else if (strcasecmp(tmp, "ignore") == 0)
sy->ignore = 1;
else if (strcasecmp(tmp, "noignore") == 0)
@@ -234,7 +243,9 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
} else if (strcasecmp(tmp, "none") == 0)
sy->gc.attr = 0;
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
if (strcmp(tmp + 2, "attr") == 0)
if (strcmp(tmp + 2, "link") == 0)
sy->link = 0;
else if (strcmp(tmp + 2, "attr") == 0)
sy->gc.attr |= GRID_ATTR_NOATTR;
else {
value = attributes_fromstring(tmp + 2);
@@ -262,6 +273,15 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
if (errstr != NULL)
goto error;
sy->pad = (int)n;
} else if (strncasecmp(tmp, "link=", 5) == 0) {
if (tmp[5] == '\0')
sy->link = 0;
else {
if (style_hyperlinks == NULL)
style_hyperlinks = hyperlinks_init();
sy->link = hyperlinks_put(style_hyperlinks,
tmp + 5, tmp + 5);
}
} else {
if ((value = attributes_fromstring(tmp)) == -1)
goto error;
@@ -284,8 +304,8 @@ style_tostring(struct style *sy)
{
struct grid_cell *gc = &sy->gc;
int off = 0;
const char *comma = "", *tmp = "";
static char s[1024];
const char *comma = "", *tmp = "", *uri;
static char s[2048];
char b[21];
*s = '\0';
@@ -389,15 +409,33 @@ style_tostring(struct style *sy)
comma = ",";
}
if (sy->pad >= 0) {
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
off += xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
sy->pad);
comma = ",";
}
uri = style_link(sy);
if (uri != NULL) {
xsnprintf(s + off, sizeof s - off, "%slink=%s", comma, uri);
comma = ",";
}
if (*s == '\0')
return ("default");
return (s);
}
/* Get the hyperlink URI for a style, or NULL if it has none. */
const char *
style_link(struct style *sy)
{
const char *uri;
if (sy->link == 0 || style_hyperlinks == NULL)
return (NULL);
if (!hyperlinks_get(style_hyperlinks, sy->link, &uri, NULL, NULL))
return (NULL);
return (uri);
}
/* Apply a style on top of the given style. */
struct style *
style_add(struct grid_cell *gc, struct options *oo, const char *name,

22
tmux.1
View File

@@ -7268,6 +7268,28 @@ Set the width of the styled area.
.Ar N
may be a column count or a percentage (for example
.Ql 50% ) .
.It Xo Ic link=uri
(or
.Ic nolink )
.Xc
Make the styled text an OSC 8 hyperlink to
.Ar uri ,
for example
.Ql #[link=https://example.com]text#[nolink] .
This is emitted only to terminals with the
.Ic hyperlinks
feature (see
.Ic terminal-features ) ;
it works in the status line and in other formats drawn with styles.
The link continues until
.Ic nolink ,
.Ic default ,
or an empty
.Ic link=
is given.
The
.Ar uri
may not contain spaces or commas and is limited in length.
.It Xo Ic list=on ,
.Ic list=focus ,
.Ic list=left\-marker ,

3
tmux.h
View File

@@ -993,6 +993,8 @@ struct style {
int pad;
enum style_default_type default_type;
u_int link;
};
#ifdef ENABLE_SIXEL
@@ -4010,6 +4012,7 @@ int style_parse(struct style *,const struct grid_cell *,
int style_parse_colour(struct style *,
const struct grid_cell *, const char *);
const char *style_tostring(struct style *);
const char *style_link(struct style *);
struct style *style_add(struct grid_cell *, struct options *,
const char *, struct format_tree *);
void style_apply(struct grid_cell *, struct options *,

View File

@@ -580,6 +580,7 @@ tty_default_features(int *feat, const char *name, u_int version)
"cstyle,"
"extkeys,"
"focus,"
"hyperlinks,"
"usstyle"
},
{ .name = "XTerm",